Reference

std/core/convert

std/core/src/convert.trb

Conversion between types: From/Into for a conversion that always works, TryFrom/TryInto for one that can fail. Text is a source like any other, so Int.tryFrom("42") is a TryFrom too. Show is the direction into a String for printing, and LiteralParseError is what the generated TryFrom<String, ...> of a literal type answers.

One direction of each pair is the one to implement: From and TryFrom. Into and TryInto come from a blanket implementation over them, so an extend that writes one by hand is reported with the line to write instead.

trait From

trait From<Source>

Infallible conversion. Implement this one, Into comes for free.

Examples

const codepoint: Int = Int.from 'A'
print codepoint

This is also how a package converts its own type into a foreign one: a type of this package named as an argument of the trait is enough to own the implementation, so Float64 may be the target although it belongs to somebody else.

type Celsius {
  degrees: Float
}

extend Float64 with From<Celsius> {
  static fn from(value: Celsius): Float64 {
    value.degrees
  }
}

const degrees: Float64 = Celsius(21.5).into()
print degrees

Related

  • Into - the other direction, gained for free from this one.
  • TryFrom - the same conversion where it can fail.

fn from

static fn from(value: Source): Self

Makes a Self from a Source. This is what Self.from(source) calls, and what Into.into calls through it.

trait Into

trait Into<Target>

The other direction of From, gained for free wherever Target: From<Self>.

Pitfalls

  • Implement From and not this one; the compiler says so at an extend that tries.

Related

  • TryInto - the same step where the conversion can fail.

fn into

fn into(): Target

Makes a Target from self.

extend Source with Into<Target> where Target: From<Source>

extend<Source, Target> Source with Into<Target> where Target: From<Source>

The blanket implementation that gives every From its Into for free: nothing implements Into by hand.

fn into

fn into(): Target

extend Target with From<Never>

extend<Target> Target with From<Never>

Every type can be made from a Never, because there is no value to make it from: Never coerces to anything, so the body is the argument. What this buys is ? on a Result<Value, Never> - the reading end of a Channel cannot fail, and without this every use of one would have to take the Result apart with a pattern.

fn from

static fn from(value: Never): Target

trait TryFrom

trait TryFrom<Source, Failure>

Fallible conversion: the From for a source that may not represent a valid value. Implement this one, TryInto comes for free.

A type may implement it several times, once per source: Int8.tryFrom(300) narrows a number and Int8.tryFrom("42") reads text, and the argument decides which one is meant. Text is a source like any other - there is no separate trait for it, and no parse on a type.

Examples

const narrow: Result<Int8, NumberRangeError> = Int8.tryFrom 300
print narrow.isError()
const read: Result<Int8, NumberParseError> = Int8.tryFrom "42"
print read.isError()

Related

  • TryInto - the other direction, gained for free from this one.
  • From - the same conversion where it cannot fail.

fn tryFrom

static fn tryFrom(value: Source): Result<Self, Failure>

Makes a Self from a Source, or answers why it could not. This is what Self.tryFrom(source) calls, and what TryInto.tryInto calls through it.

trait TryInto

trait TryInto<Target, Failure>

The other direction of TryFrom, gained for free wherever Target: TryFrom<Self, Failure>.

Write the target out. tryInto() answers a Result, so a ? in front of the annotation is what a reader sees first and the target itself has nowhere else to come from. Under a ? the annotation is the target alone, and the failure is the one the target's TryFrom from this source answers with:

Examples

const narrow: Result<Int8, NumberRangeError> = 300.tryInto()
print narrow.isError()

fn port(text: String): Result<Int8, NumberParseError> {
  const number: Int8 = text.tryInto()?
  Ok number
}

print port("42")

Pitfalls

  • Implement TryFrom and not this one. The blanket implementation below is the only TryInto there is, and the compiler says so at an extend that tries.

Related

  • TryFrom - the one to implement.
  • Into - the same step where the conversion cannot fail.

fn tryInto

fn tryInto(): Result<Target, Failure>

Makes a Target from self, or answers why it could not.

extend Source with TryInto<Target, Failure> where Target: TryFrom<Source, Failure>

extend<Source, Target, Failure> Source with TryInto<Target, Failure> where Target: TryFrom<Source, Failure>

The blanket implementation that gives every TryFrom its TryInto for free: nothing implements TryInto by hand.

fn tryInto

fn tryInto(): Result<Target, Failure>

type LiteralParseError

type LiteralParseError with Show, Error

What Status.tryFrom(text) fails with when text is not one of a literal type's members:

'away' is not one of "online", "offline"

field text

text: String

The text that was given.

field expected

expected: List<String>

The members it could have been instead.

fn show

fn show(): String

'away' is not one of "online", "offline"

trait Show

shared trait Show

Used by string interpolation. Generated for every type. A shared trait, so that objects with an identity (connections, files) can be printed, too. Equals and Hash are not: == always compares content. For identity there is isSame(a, b).

Examples

print 1.show()
print "already text".show()

fn show

fn show(): String

The text a value shows as: what string interpolation calls, and what print calls through it.

fn showNested

fn showNested(): String

How the value looks inside of another value: in a list, in a field of a generated Show, in a tuple. Only String (quoted, with escapes) and Char (in single quotes) differ from show(), so that ["a", "b"] stays readable while "{name}" is still the text itself.