It's very useful that the bare name of a function can be used as a value of the appropriate function type, e.g.
usize::from_str("1234").map(usize::is_power_of_two) // Result<bool, _>
This pattern breaks down somewhat when it comes to methods. While type::method
beheves like a function, object.method
does not - the compiler will insist we need to call it first. However, in the IMO morally equivalent case that method
is a field of function type, calling that function is done by saying (object.field)()
, exactly what you'd expect if object.field
is actually naming a function.
Of course, a function-typed field and a method call are not semantically equivalent, because only the latter case passes self
as a parameter. There is nonetheless an intuition, most easily seen in C++'s notion of pointer-to-member, that object.method
nonetheless names a function equivalent to method
but with object
already bound as the first parameter, i.e. currying the first parameter into the function. To do the same in Rust, I'm effectively suggesting sugar such that this, used as a value(*),
object.method
is equivalent to
|...| Type::method(object, ...)
with all of the existing rules about whether the resulting closure is clone/copyable, what it's capturing and for what lifetime, etc, still applying. I'm not suggesting currying (as happening implicitly or not) be codified as a language feature in any other context. The only reason this can't just be a macro is because there's no way for a macro to determine the arity of the closure it'd need to produce and the type needed.
A related construction is the Scala feature of "placeholder parameters" where one can write _ + _
and implicitly produce a closure |_1, _2| _1 + _2
. This would be a generalisation of what I'm suggesting, but if anyone's suggested something similar in Rust, I expect this suggestion would be an easy extension of that.
I don't think this creates any backwards compatibility concerns, since you're plain not allowed to do this ATM, but I can appreciate it might strike some people as too implicit. Thanks for any feedback you have
(*) I've not looked into the formal grammar, so I don't know if there's any distinctions that need to be worked around because (|a,b| Type::method(object, a, b))(foo, bar)
is not actually equivalent to, object.method(foo, bar)