At the moment, if you want to partially apply a function the only way is to write a closure:
let part = |x, z| foo(x, 42, z);
That isn't to bad, but still more verbose than necessary, so I propose a special sugar for this usage:
let part = foo(_, 42, _);
The rules are simple:
_ in an expression, transform the whole expression into a closure by putting an |...| at the front and replacing the _ with the first argument in there._ in a expression, append an argument to the argument list, and replace the _ with that, too.This would also allow things like v.map(_ + 5).filter(3 < _) to work, which read really nice.
Things would get a bit hairy if you involve if or match, but each arm would just need the rule to have the same number of _s. And it would be unidiomatic to use it for bigger code structures anyway.
Rust had this feature until about a year ago; it was called bind. See #2189. It's not coming back, sorry!
(You're free to try implementing it as a macro if you'd like, though.)
For reference, Haxe 3 supports syntax much like this suggestion: http://haxe.org/ref/callback
@catamorphism : Well this would not be bind, but just sugar for a closure, as has been proposed in #2189 as a replacement for bind. I can understand not wanting a bind that has different semantics, but as pure sugar?
(And using a macro would be longer than just writing a closure)
@Kimundi That would be possible to implement as a macro, as far as I can tell, so it doesn't need an RFC... someone can just do it :-)
@catamorphism I just don't see how #2189 means 'we will never have it again', all comments there read as 'syntax is convenient, but impl should not be something separate from a closure', heck you self said basically the same there ;)
Of course the language requirements change over time, but... I don't see the harm here? Syntactically it would be a fully backwards compatible change to re-add it.
First comment ever on GitHub here :) I hope my reasoning isn't full of errors. Sorry if it is (or I should have open another new Issue) :(
Could this RFC be opened again ?
After some thoughts, I understood both @catamorphism and @Kimundi comment's and Issue #2189. But can't those problems be resolved by forbidding non-constexpr partial applications ? I don't know if this can be managed by a macro (one would need to test the constexpr-ness ?) ; if it can, maybe a partial!(...) could be tested. I really think this kind of syntax sugar for partial application is efficient (better than C++'s bind for example) and easy to learn for beginners.
fn foosum(x:i32, y:i32, z:i32) -> i32
{
x+y+z
}
Example 1 :
let part = foosum(_, 42, _);
would be translated by the compiler into
let part = |x, z| foosum(x, 42, z);
Exemple 2 :
let part = foosum(_, rand(), _);
would fail compilation
error[EXXX] : partial application uses non constexpr
[...]
let part = foosum(_, rand(), _)
.....................^^^^^ is not constexpr
help : do you mean (A) : make a closure computing the expression "rand()" each time it is called
let part = |x, z| foosum(x, rand(), z);
help : or (B) : compute once the result of expression "rand() and make a closure with it
let const_value = rand()
let part = foosum(_, const_value, _);
Most helpful comment
First comment ever on GitHub here :) I hope my reasoning isn't full of errors. Sorry if it is (or I should have open another new Issue) :(
Could this RFC be opened again ?
After some thoughts, I understood both @catamorphism and @Kimundi comment's and Issue #2189. But can't those problems be resolved by forbidding non-constexpr partial applications ? I don't know if this can be managed by a macro (one would need to test the constexpr-ness ?) ; if it can, maybe a partial!(...) could be tested. I really think this kind of syntax sugar for partial application is efficient (better than C++'s bind for example) and easy to learn for beginners.
fn foosum(x:i32, y:i32, z:i32) -> i32 { x+y+z }Example 1 :
let part = foosum(_, 42, _);would be translated by the compiler into
let part = |x, z| foosum(x, 42, z);Exemple 2 :
let part = foosum(_, rand(), _);would fail compilation
error[EXXX] : partial application uses non constexpr[...]let part = foosum(_, rand(), _).....................^^^^^ is not constexprhelp : do you mean (A) : make a closure computing the expression "rand()" each time it is calledlet part = |x, z| foosum(x, rand(), z);help : or (B) : compute once the result of expression "rand() and make a closure with itlet const_value = rand()let part = foosum(_, const_value, _);