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.