I grabbed it because it actually exists in Cats, and it came to mind because the example was a Monad
, and it was a method I knew there was a pre-existing usecase for.
Yep, at least as far as I can tell, it’s currently internally consistent and unsurprising as-is.
As an understanding check, is this how you understand the stepwise inlining would go for the Range
example?
Class definition
This is identical to the summary above, I’m copying it here for reference
class Range(inline from: Int, inline to: Int) {
inline def map[T](function: InlinedFunction[Int, T]): Seq[T] = {
var i = from
val buffer: mutable.Buffer[T] = mutable.Buffer()
while(i < to) {
buffer += function(i)
i += 1
}
buffer
}
}
Base
val seq = Range(1, 100).inlinedMap(_ * 2)
Stage 1
I’m going to handwave the compiler generating a unique identifier for i
, to
, from
, etc
val seq = {
val r = Range(1, 100)
r.inlinedMap(i => i * 2)
}
Stage 2
val seq = {
val r = Range(1, 100)
var i = r.from
val buffer: mutable.Buffer[T] = mutable.Buffer()
while(i < r.to) {
buffer += i * 2
i += 1
}
buffer
}
Stage 3
This caches the inline parameters, to avoid multiple execution, which I think is consistent with the inline constructor parameters being by-value val
s, rather than being by-name.
The implications of this is that, if we want to be able to have by-name semantics, the user would have to supply a wrapper and have the actual inline parameter be a function value.
val seq = {
var i = 1
val buffer: mutable.Buffer[T] = mutable.Buffer()
while(i < 100) {
buffer += i * 2
i += 1
}
buffer
}