You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/docs/reference/changed-features/numeric-literals.md
+37-8Lines changed: 37 additions & 8 deletions
Original file line number
Diff line number
Diff line change
@@ -24,47 +24,54 @@ how large they can be.
24
24
25
25
The meaning of a numeric literal is determined as follows:
26
26
27
-
- If the literal ends with `l` or `L`, it is a `Long` integer (and must fit
28
-
in its legal range).
29
-
- If the literal ends with `f` or `F`, it is a single precision floating point number of type `Float`.
30
-
- If the literal ends with `d` or `D`, it is a double precision floating point number of type `Double`.
27
+
- If the literal ends with `l` or `L`, it is a `Long` integer (and must fit in its legal range).
28
+
- If the literal ends with `f` or `F`, it is a single precision floating point number of type `Float`.
29
+
- If the literal ends with `d` or `D`, it is a double precision floating point number of type `Double`.
31
30
32
31
In each of these cases the conversion to a number is exactly as in Scala 2 or in Java. If a numeric literal does _not_ end in one of these suffixes, its meaning is determined by the expected type:
33
32
34
-
1. If the expected type is `Int`, `Long`, `Float`, or `Double`, the literal is
33
+
1. If the expected type is `Int`, `Long`, `Float`, or `Double`, the literal is
35
34
treated as a standard literal of that type.
36
-
2. If the expected type is a fully defined type `T` that has a given instance of type
35
+
2. If the expected type is a fully defined type `T` that has a given instance of type
37
36
`scala.util.FromDigits[T]`, the literal is converted to a value of type `T` by passing it as an argument to
38
37
the `fromDigits` method of that instance (more details below).
39
-
3. Otherwise, the literal is treated as a `Double` literal (if it has a decimal point or an
38
+
3. Otherwise, the literal is treated as a `Double` literal (if it has a decimal point or an
40
39
exponent), or as an `Int` literal (if not). (This last possibility is again as in Scala 2 or Java.)
41
40
42
41
With these rules, the definition
42
+
43
43
```scala
44
44
valx:Long=-10_000_000_000
45
45
```
46
+
46
47
is legal by rule (1), since the expected type is `Long`. The definitions
48
+
47
49
```scala
48
50
valy:BigInt=0x123_abc_789_def_345_678_901
49
51
valz:BigDecimal=111222333444.55
50
52
```
53
+
51
54
are legal by rule (2), since both `BigInt` and `BigDecimal` have `FromDigits` instances
52
55
(which implement the `FromDigits` subclasses `FromDigits.WithRadix` and `FromDigits.Decimal`, respectively).
53
56
On the other hand,
57
+
54
58
```scala
55
59
valx=-10_000_000_000
56
60
```
61
+
57
62
gives a type error, since without an expected type `-10_000_000_000` is treated by rule (3) as an `Int` literal, but it is too large for that type.
58
63
59
64
### The FromDigits Trait
60
65
61
66
To allow numeric literals, a type simply has to define a `given` instance of the
62
67
`scala.util.FromDigits` type class, or one of its subclasses. `FromDigits` is defined
63
68
as follows:
69
+
64
70
```scala
65
71
traitFromDigits[T]:
66
72
deffromDigits(digits: String):T
67
73
```
74
+
68
75
Implementations of the `fromDigits` convert strings of digits to the values of the
69
76
implementation type `T`.
70
77
The `digits` string consists of digits between `0` and `9`, possibly preceded by a
@@ -74,6 +81,7 @@ the string is passed to `fromDigits`.
74
81
The companion object `FromDigits` also defines subclasses of `FromDigits` for
75
82
whole numbers with a given radix, for numbers with a decimal point, and for
76
83
numbers that can have both a decimal point and an exponent:
84
+
77
85
```scala
78
86
objectFromDigits:
79
87
@@ -95,6 +103,7 @@ object FromDigits:
95
103
*/
96
104
traitFloating[T] extendsDecimal[T]
97
105
```
106
+
98
107
A user-defined number type can implement one of those, which signals to the compiler
99
108
that hexadecimal numbers, decimal points, or exponents are also accepted in literals
100
109
for this type.
@@ -104,6 +113,7 @@ for this type.
104
113
`FromDigits` implementations can signal errors by throwing exceptions of some subtype
105
114
of `FromDigitsException`. `FromDigitsException` is defined with three subclasses in the
@@ -115,17 +125,22 @@ class MalformedNumber(msg: String = "malformed number literal") extends FromDigi
115
125
### Example
116
126
117
127
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:
@@ -207,6 +232,7 @@ implementation method `fromDigitsImpl`. Here is its definition:
207
232
'{apply($digits)}
208
233
endBigFloat
209
234
```
235
+
210
236
The macro implementation takes an argument of type `Expr[String]` and yields
211
237
a result of type `Expr[BigFloat]`. It tests whether its argument is a constant
212
238
string. If that is the case, it converts the string using the `apply` method
@@ -218,10 +244,13 @@ The interesting part is the `catch` part of the case where `digits` is constant.
218
244
If the `apply` method throws a `FromDigitsException`, the exception's message is issued as a compile time error in the `ctx.error(ex.getMessage)` call.
0 commit comments