Skip to content

Commit 7890726

Browse files
committed
Update numeric literals documentation
1 parent af43f16 commit 7890726

File tree

1 file changed

+32
-2
lines changed

1 file changed

+32
-2
lines changed

docs/docs/reference/changed-features/numeric-literals.md

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ val y: BigInt = 0x123_abc_789_def_345_678_901
4545
val z: BigDecimal = 111222333444.55
4646
```
4747
are legal by rule (2), since both `BigInt` and `BigDecimal` have `FromDigits` instances
48-
(which implement the `FromDigits` subclasses `FromDigits.WithRadix` and `FromDigits.Decimal`, respectively).
48+
(which implement the `FromDigits` subclasses `FromDigits.WithRadix` and `FromDigits.Floating`, respectively).
4949
On the other hand,
5050
```scala
5151
val x = -10_000_000_000
@@ -112,6 +112,36 @@ class NumberTooSmall (msg: String = "number too small") extends FromDigi
112112
class MalformedNumber(msg: String = "malformed number literal") extends FromDigitsException(msg)
113113
```
114114

115+
### Compiler Expansion
116+
117+
The companion object `FromDigits` also defines four methods that may be used to provide a given instance of one of the subclasses of `FromDigits`:
118+
```scala
119+
inline def fromDigits[T](given x: FromDigits[T]): x.type = x
120+
121+
inline def fromRadixDigits[T](given x: FromDigits.WithRadix[T]): x.type = x
122+
123+
inline def fromDecimalDigits[T](given x: FromDigits.Decimal[T]): x.type = x
124+
125+
inline def fromFloatingDigits[T](given x: FromDigits.Floating[T]): x.type = x
126+
```
127+
128+
If a numeric literal has a known expected type `T` that is not one of the primitive numeric types, then the compiler will search for a given instance of `FromDigits[T]`. If one exists, then the compiler expands the literal to a call on the `fromDigits` method on the result obtained from calling one of the above four methods.
129+
130+
As an example, the literal below has a nonsensical expected type `BigDecimal`, which can not be constructed with hex digits:
131+
```scala
132+
0xCAFEBABE: BigDecimal
133+
```
134+
Upon the compiler finding a given instance for `FromDigits[BigDecimal]`, the hex literal above expands to the following:
135+
```scala
136+
FromDigits.fromRadixDigits[BigDecimal].fromDigits("0CAFEBABE", 16)
137+
```
138+
The given clause of `fromRadixDigits` asserts that the prior found `FromDigits` instance is a subtype of `FromDigits.WithRadix[BigDecimal]`, or else following error is issued:
139+
```scala
140+
1 |0xCAFEBABE: BigDecimal
141+
|^
142+
|Type BigDecimal does not have a FromDigits instance for whole numbers with radix other than 10.
143+
```
144+
115145
### Example
116146

117147
As a fully worked out example, here is an implementation of a new numeric class, `BigFloat`, that accepts numeric literals. `BigFloat` is defined in terms of a `BigInt` mantissa and an `Int` exponent:
@@ -174,7 +204,7 @@ With the setup of the previous section, a literal like
174204
```
175205
would be expanded by the compiler to
176206
```scala
177-
BigFloat.FromDigits.fromDigits("1e100000000000")
207+
FromDigits.fromFloatingDigits[BigFloat].fromDigits("1e100000000000")
178208
```
179209
Evaluating this expression throws a `NumberTooLarge` exception at run time. We would like it to
180210
produce a compile-time error instead. We can achieve this by tweaking the `BigFloat` class

0 commit comments

Comments
 (0)