I would like to propose the addition of transparent inline
parameters to the language.
They can only be used with inline
methods and they would be similar to normal inline parameters
, with the difference that their usage won’t be type-checked at the definition site, but at the usage site.
Thus, making them very similar to C #define
functions, allowing users to generate simple code blocks without needing to resort to more advanced tools like macros.
A motivating example of when they would be useful is something like this:
// Imagine you have the following repetitive code.
val data = List(
someRepetitiveMethodCall(foo).anotherRepetitiveMethodCall,
someRepetitiveMethodCall(bar).anotherRepetitiveMethodCall
// ...
)
One would be tempted to simplify that as:
val data = List(foo, bar, ...).map { x =>
someRepetitiveMethodCall(x).anotherRepetitiveMethodCall
)
However, in this case, foo
, bar
, etc don’t share any common supper type; thus x
becomes Any
. And, someRepetitiveMethodCall
actually requires some implicit evidence; thus needing the precise type of each element.
One may create a small helper to reduce the number of characters, but that may require importing a bunch of things, adding a lot of type parameters, repeating the implicit parameters, etc; which could lead to little code / noise reduction
Note that, the current inline
support is not enough to define such a helper, since the following would not compile; because of a type mismatch error.
transparent inline def f(inline x: Any) =
someRepetitiveMethodCall(x).anotherRepetitiveMethodCall
Thus, I am proposing the possibility to tag x
as transparent inline
and thus allowing us to write the previous function, which then would be used like this:
val data = List(
f(foo),
f(bar),
// ...
)
The code would be expanded as the original one.
On a complementary note, I also thought of having an inline for
(or something similar).
Which would have two variants: A foreach
one, which would just generate independent lines of code. And a yield
one, which would collect all emitted elements on a List
.
I imagine something like this:
foreach
inline for(foo, bar, baz) { x =>
doSomethingWith(x)
}
yield
val data = inline for(foo, bar, baz) yield { x =>
doSomethingWith(x)
}
Which would be expanded as (respectively):
foreach
doSomethingWith(foo)
doSomethingWith(bar)
doSomethingWith(baz)
yield
val data =
doSomethingWith(foo) ::
doSomethingWith(bar) ::
doSomethingWith(baz) ::
Nil
The block would follow the normal inline rules, reducing the expression all it can.
I am not particularly fond of the syntax, just the idea.
But also, I understand that this second proposal is more controversial than the first one, which is why I did s soft split; if a moderator thinks is better to split it into a different post either let me know or feel free to do it
Looking forward to reading your feedback.