inlining receivers just doesn't work well with how type-inference works since the
.
is viewed as depending on its receiver, and not influencing its receiver, and so you can only really have functions on lambdas if those lambdas are pre-existing values, but then those values can't really be inlined. That's why extension lambda receivers for inline functions are treated as
noinline
With the risk of derailing the discussion too much:
if the compiler had some sort of way to declare values that shouldn't escape an inline context (similar to how an inline method with an inline lambda parameter can't have that lambda escape) then you can have "local lambdas" that act as values, and hence they'd only be allowed to be passed to inline functions. This allows for viewing data as "curried functions", ala church encoding, and you can have zero-cost struct-like types. I made that as a
suggestion a while back, but after having a go at implementing it, it definitely is too big of a hassle, and results in frequent compiler crashes because it just wasn't designed to inline such deeply-nested code.
One "easy"-ish way for the compiler to support this would be with a new modifier similar to
crossinline
(maybe
inline
) that declares that this lambda parameter is an
inline
function w.r.t its lambda parameters. An example helps:
inline fun <T, R1, R2> letLambda(lambda: (T) -> R1, inline block: ((T) -> R1) -> R2) = block(lambda)
here
inline
declares that the block is, for all intents and purposes, an inline function, and so at the callsite you'd be defining an anonymous inline function. You'd also only be able to use callable references to other
inline
functions. This introduces a name for the lambda parameter inside without actually storing the lambda as a real object. Then, an extension on such a lambda would make sense, and by extension, it would justify having
EagerEffect.fold
being inline and hence applying to
Effect
as well (in suspending contexts only obviously).