> ...by the time x.len() gets executed, arg0 already exists...
So, I realize that this is the way that Java does it--and, presumably, one still doesn't get fired for doing whatever Java does ;P--but, would it not actually make more sense for the arguments to be evaluated before the target reference, making the argument order more like Haskell/Erlang (but very sadly not Elixir, which makes it awkwardly incompatible with Erlang and breaks some of the basic stuff like fold/reduce)? Particularly so, given that, as far as I can tell from this example, what makes arg0 have the type that it does is the type of the function that hasn't even been called yet? (As in, the semantic gap I am seeing between what the user probably meant and what the compiler wants to do is that "x" shouldn't really be mutably-borrowed until the call happens, and the call here clearly shouldn't happen until after the arguments are evaluated.) (Note: I do not program in Rust currently; I just have spent a number of decades analyzing languages and at times teaching college language design courses. I might be missing something obvious elsewhere that forces Rust to do this, but that one example, in isolation, at least feels like an unforced error.)
In Rust, `reciever.some_method(whatever)` is supposed to be relatively thin sugar for `TypeOfReciever::some_method(receiver, whatever)`. So the evaluation order should be the same for those two forms.
Sure, but I am saying it would actually have made more sense to put receiver as the last such argument--as one might expect from having used Haskell/Erlang--given the other design decisions clearly in play here, as the target reference isn't really the first argument for any obvious reason other than visual effect and some historical baggage from implementations of some object-oriented languages (including Java) with different constraints.
You're not wrong, but making self be the last argument would cause confusion for almost everyone coming from other languages, and for Rust it is too late to change that now. You could special case the behavior of the method call syntax to operate that way without breaking backwards compatibility (at the cost of making going back and forth between that syntax and the fully qualified call no longer being a straight forward syntactical transformation).
Doesn't Rust support having a function as a field of a struct?
If it does, then the order of evaluation of a.foo(b) would depend on whether foo is a field or a "free-standing" function of a, which seems horrible.
Also, there is a simple elegance in having the order of evaluation match the order the symbols are written that should require a very hight bar to reverse, in my opinion at least.
It does, but Rust also has separate namespaces for methods and variables. That is, a.foo(b) will always be a method foo and never a field foo, because the syntax is that of a method. In order to access a function object, then call it, you would use (a.foo)(b). The parentheses cause the contents to be parsed as a variable expression.
It doesn't remove or break anything, it just changes the order of arguments to be compatible with Elixir's (|>) operator and consistent data-first design across the language.
I do partial application in Elixir all the time. I have a function `curry/1` which takes any function and gives a curried version of it, and I have a `p` macro which introduces Scala-like "holes" (e.g. `(p Enum.map(list, _))`). The order of arguments still doesn't matter and nothing is broken or impossible because of it. I have also tweaked the (|>) macro (as well as some other operators) to support holes, so that I can "pipe" into whichever position of the call.
I think there are many more severe problems with Elixir which make it not even a remotely functional PL for me (rather, procedural + macros), but arguments order is not one of them.
I applaud your efforts, but that is a lot of work against the grain. I've yet to see a curried function in the wild outside of a handful of anonymous functions passed as HoFs.
> I think there are many more severe problems with Elixir ... but arguments order is not one of them.
Cheers, I have no dog in this game, merely expanding on what (I think) OP was alluding to.
It's definitely against the grain but also not really a lot of work. The currying function is ~3-4 lines. The macros are 5-10 lines each. As for examples of such things being used "in the wild", many use Witchcraft library which strives to give a Haskell-like experience to Elixir.
yeah but at this point, currying seems to be a loss in ergonomics in most use case we have found in the wild. I love the idea, I love the principle.
But the jury is definitely still out for if the pattern of showing it in syntax and semantics actually is beneficial. And yes, I know nearly all the examples you can come with to show how useful it can be.
But the cost of having it seems to more than compensate the benefits.
So, I realize that this is the way that Java does it--and, presumably, one still doesn't get fired for doing whatever Java does ;P--but, would it not actually make more sense for the arguments to be evaluated before the target reference, making the argument order more like Haskell/Erlang (but very sadly not Elixir, which makes it awkwardly incompatible with Erlang and breaks some of the basic stuff like fold/reduce)? Particularly so, given that, as far as I can tell from this example, what makes arg0 have the type that it does is the type of the function that hasn't even been called yet? (As in, the semantic gap I am seeing between what the user probably meant and what the compiler wants to do is that "x" shouldn't really be mutably-borrowed until the call happens, and the call here clearly shouldn't happen until after the arguments are evaluated.) (Note: I do not program in Rust currently; I just have spent a number of decades analyzing languages and at times teaching college language design courses. I might be missing something obvious elsewhere that forces Rust to do this, but that one example, in isolation, at least feels like an unforced error.)