@@ -144,22 +144,23 @@ Inline methods can override other non-inline methods. The rules are as follows:
144
144
145
145
``` scala
146
146
abstract class A :
147
- def f () : Int
148
- def g () : Int = f()
147
+ def f : Int
148
+ def g : Int = f
149
149
150
150
class B extends A :
151
- inline def f () = 22
152
- override inline def g () = f() + 11
151
+ inline def f = 22
152
+ override inline def g = f + 11
153
153
154
- val b = B ()
154
+ val b = new B
155
155
val a : A = b
156
156
// inlined invocatons
157
- assert(b.f() == 22 )
158
- assert(b.g() == 33 )
157
+ assert(b.f == 22 )
158
+ assert(b.g == 33 )
159
159
// dynamic invocations
160
- assert(a.f() == 22 )
161
- assert(a.g() == 33 )
160
+ assert(a.f == 22 )
161
+ assert(a.g == 33 )
162
162
```
163
+
163
164
The inlined invocations and the dynamically dispatched invocations give the same results.
164
165
165
166
2 . Inline methods are effectively final .
@@ -168,14 +169,14 @@ Inline methods can override other non-inline methods. The rules are as follows:
168
169
169
170
```scala
170
171
abstract class A :
171
- inline def f () : Int
172
+ inline def f : Int
172
173
173
174
object B extends A :
174
- inline def f () : Int = 22
175
+ inline def f : Int = 22
175
176
176
- B .f() // OK
177
+ B .f // OK
177
178
val a : A = B
178
- a.f() // error: cannot inline f() in A.
179
+ a.f // error: cannot inline f() in A.
179
180
```
180
181
181
182
### Relationship to `@inline`
@@ -224,6 +225,7 @@ including _platform-specific_ extensions such as constant folding of pure
224
225
numeric computations.
225
226
226
227
An inline value must have a literal type such as `1` or `true`.
228
+
227
229
```scala
228
230
inline val four = 4
229
231
// equivalent to
@@ -249,17 +251,18 @@ specialized to a more precise type upon expansion. Example:
249
251
``` scala
250
252
class A
251
253
class B extends A :
252
- def m () = true
254
+ def m = true
253
255
254
256
transparent inline def choose (b : Boolean ): A =
255
- if b then new A () else new B ()
257
+ if b then new A else new B
256
258
257
259
val obj1 = choose(true ) // static type is A
258
260
val obj2 = choose(false ) // static type is B
259
261
260
- // obj1.m() // compile-time error: `m` is not defined on `A`
261
- obj2.m() // OK
262
+ // obj1.m // compile-time error: `m` is not defined on `A`
263
+ obj2.m // OK
262
264
```
265
+
263
266
Here, the inline method ` choose ` returns an instance of either of the two types ` A ` or ` B ` .
264
267
If ` choose ` had not been declared to be ` transparent ` , the result
265
268
of its expansion would always be of type ` A ` , even though the computed value might be of the subtype ` B ` .
@@ -276,9 +279,9 @@ the singleton type `0` permitting the addition to be ascribed with the correct
276
279
type ` 1 ` .
277
280
278
281
``` scala
279
- transparent inline def zero () : Int = 0
282
+ transparent inline def zero : Int = 0
280
283
281
- val one : 1 = zero() + 1
284
+ val one : 1 = zero + 1
282
285
```
283
286
284
287
## Inline Conditionals
@@ -295,6 +298,7 @@ inline def update(delta: Int) =
295
298
inline if delta >= 0 then increaseBy(delta)
296
299
else decreaseBy(- delta)
297
300
```
301
+
298
302
A call ` update(22) ` would rewrite to ` increaseBy(22) ` . But if ` update ` was called with
299
303
a value that was not a compile-time constant, we would get a compile time error like the one
300
304
below:
@@ -343,10 +347,10 @@ case class Succ[N <: Nat](n: N) extends Nat
343
347
344
348
transparent inline def toInt (n : Nat ): Int =
345
349
inline n match
346
- case Zero => 0
350
+ case Zero => 0
347
351
case Succ (n1) => toInt(n1) + 1
348
352
349
- final val natTwo = toInt(Succ (Succ (Zero )))
353
+ inline val natTwo = toInt(Succ (Succ (Zero )))
350
354
val intTwo : 2 = natTwo
351
355
```
352
356
@@ -366,10 +370,10 @@ import scala.compiletime.{constValue, S}
366
370
367
371
transparent inline def toIntC [N ]: Int =
368
372
inline constValue[N ] match
369
- case 0 => 0
373
+ case 0 => 0
370
374
case _ : S [n1] => 1 + toIntC[n1]
371
375
372
- final val ctwo = toIntC[2 ]
376
+ inline val ctwo = toIntC[2 ]
373
377
```
374
378
375
379
` constValueOpt ` is the same as ` constValue ` , however returning an ` Option[T] `
@@ -402,19 +406,20 @@ import scala.compiletime.erasedValue
402
406
403
407
inline def defaultValue [T ] =
404
408
inline erasedValue[T ] match
405
- case _ : Byte => Some (0 : Byte )
406
- case _ : Char => Some (0 : Char )
407
- case _ : Short => Some (0 : Short )
408
- case _ : Int => Some (0 )
409
- case _ : Long => Some (0L )
410
- case _ : Float => Some (0.0f )
411
- case _ : Double => Some (0.0d )
409
+ case _ : Byte => Some (0 : Byte )
410
+ case _ : Char => Some (0 : Char )
411
+ case _ : Short => Some (0 : Short )
412
+ case _ : Int => Some (0 )
413
+ case _ : Long => Some (0L )
414
+ case _ : Float => Some (0.0f )
415
+ case _ : Double => Some (0.0d )
412
416
case _ : Boolean => Some (false )
413
- case _ : Unit => Some (())
414
- case _ => None
417
+ case _ : Unit => Some (())
418
+ case _ => None
415
419
```
416
420
417
421
Then:
422
+
418
423
``` scala
419
424
val dInt : Some [Int ] = defaultValue[Int ]
420
425
val dDouble : Some [Double ] = defaultValue[Double ]
@@ -434,7 +439,7 @@ transparent inline def toIntT[N <: Nat]: Int =
434
439
case _ : Zero .type => 0
435
440
case _ : Succ [n] => toIntT[n] + 1
436
441
437
- final val two = toIntT[Succ [Succ [Zero .type ]]]
442
+ inline val two = toIntT[Succ [Succ [Zero .type ]]]
438
443
```
439
444
440
445
` erasedValue ` is an ` erased ` method so it cannot be used and has no runtime
@@ -555,6 +560,7 @@ keep the viral nature of implicit search programs based on logic programming.
555
560
By contrast, the new ` summonFrom ` construct makes implicit search available
556
561
in a functional context. To solve the problem of creating the right set, one
557
562
would use it as follows:
563
+
558
564
``` scala
559
565
import scala .compiletime .summonFrom
560
566
@@ -563,12 +569,14 @@ inline def setFor[T]: Set[T] = summonFrom {
563
569
case _ => new HashSet [T ]
564
570
}
565
571
```
572
+
566
573
A ` summonFrom ` call takes a pattern matching closure as argument. All patterns
567
574
in the closure are type ascriptions of the form ` identifier : Type ` .
568
575
569
576
Patterns are tried in sequence. The first case with a pattern ` x: T ` such that an implicit value of type ` T ` can be summoned is chosen.
570
577
571
578
Alternatively, one can also use a pattern-bound given instance, which avoids the explicit using clause. For instance, ` setFor ` could also be formulated as follows:
579
+
572
580
``` scala
573
581
import scala .compiletime .summonFrom
574
582
@@ -606,6 +614,7 @@ inline def f: Any = summonFrom {
606
614
## ` summonInline `
607
615
608
616
The shorthand ` summonInline ` provides a simple way to write a ` summon ` that is delayed until the call is inlined.
617
+
609
618
``` scala
610
619
transparent inline def summonInline [T ]: T = summonFrom {
611
620
case t : T => t
0 commit comments