[erlang-questions] Matthew Sackman's "cut" proposal
Tim Watson
watson.timothy@REDACTED
Tue Jul 12 03:15:35 CEST 2011
>> For me, the compelling reason to have *something* like this is that
>> function composition and partial application are the bread and butter
>> of my programming style,
>
> This is not unlike saying "assignment and goto are the bread and
> buffer of my C style, so Erlang should support assignment and goto".
> Function composition and partial application are not part of
>>>Erlang's<< native style.
>
> Again, the old joke:
> Doctor: What's the problem?
> Patient: It hurts when I do <this>?
> Doctor: Then don't do <that>.
>
> If you try to write Erlang as if it were SML (or CML),
> it's obviously going to hurt. So the answer is don't do that.
>
Ok I can see your point, and to be fair I nowadays spend more time in
Erlang than OCaml so I've gotten used to not doing <that> to some
extent.
>> and in Erlang they both prove to be rather,
>> what shall we say, wordy? For example, consider this function (a
>> hamcrest matcher) which isn't too bad at all, but is indicative of the
>> amount of noise we have to deal with:
>>
>> -spec(ends_with/1 :: (string()) -> fun((string()) -> boolean())).
>> ends_with(X) ->
>> fun(Y) -> string:equal(string:right(Y, length(X)), X) end.
>
> The amount of "noise" here is precisely three tokens: 'fun' '->' 'end'.
> Your suffering cannot be said to be extreme.
>
It wasn't an horrific example, as I mentioned, but was meant to be indicative.
> As an occasional Haskell and SML programmer, I am certainly not
> against Curried functions. What I *am* against is an approach which
> is ugly, confusing, and almost never applicable.
>
Can't disagree with you there.
> If Erlang syntax were generalised to
>
> ends_with(X)(Y) -> string:equal(string:right(Y, length(X)), X).
>
> we could eliminate those three tokens.
>
> What's more, we could do that *WITHOUT* any weird restrictions on
> - whether pattern matching is allowed in the fun
> - the form of the fun body
> - where the arguments appear in the fun body
> - the order in which the arguments appear in the fun body.
> and *WITHOUT*
> - any weird non-intention-revealing tokens, whether '_' or '?'
>
Yes but you have to admit, it does look a bit odd. Why can't I just
use the variable 'Y' and let the compiler figure out that the function
signature needs to change? This was kind of my point - although I went
around the houses as was duly (and correctly) chastised for doing so -
can the compiler do more of the leg work.
>> Not personally, I would much sooner have the compiler deal with the
>> anonymous function machinery for me:
>>
>> -spec(ends_with/1 :: (string()) -> fun((string()) -> boolean())).
>> ends_with(X) ->
>> string:equal(string:right(?, length(X)), X) end.
>
> It would be much much better as
>
> ends_with(Suffix)(String) ->
> string:equal(string:right(String, length(Suffix)), Suffix).
>
>> discussing the syntax - I could happily go with any marker-character
>
> My argument is that ANY marker character is wrong because
> - you can't nest closures that way (does this ? belong to the
> inner fun or the outer one?)
> - you can't read the intent of a parameter from a weirdo like
> '?' the way you can from a name like String
> - you have all those other weird restrictions I mentioned above
I can understand your dislike of using a marker character.
> If you want to do Haskell-like things, it doesn't make sense not
> to do it in a Haskell-like way, and that is to say that
>
> <name>(<args1>)(<args2>)...(<argsn>) -> <body>
>
> is equivalent to
>
> <name>(<args1>) ->
> fun (<args2>) ->
> ...
> fun (<argsn>) ->
> <body>
> end
> ...
> end
>
> *NO* new tokens!
> *NO* weird restrictions!
> Good consistency with the way Clean and ML and Haskell do it.
> *NO* changes elsewhere in the language.
>
Great - is it going to get through the eep process? Do we need to vote
on it, contribute (e.g., test proposed patches, etc) or whatever?
> Let's see what we have to do now:
>
> c(F1, F2) -> fun (X) -> F2(F1(X)) end.
> c(F1, F2, F3) -> fun (X) -> F3(F2(F1(X))) end.
> c(F1, F2, F3, F4) -> fun (X) -> F4(F3(F2(F1(X)))) end.
>
> doodle(X) ->
> F = c(fun do_thing/1,
> fun calculate_next_thing/1,
> fun get_bored_of_typing_result_x,
> fun start_getting_annoyed_with_lazy_programmers/1),
> {ok, F(X)}.
>
> Nope, not hard. Trivial, in fact.
Boilerplate. Might as well type it out inline. There have to be neater
ways of composing and currying. I like with your <name>(a1)(a2)(a3) in
that it at least makes the application (order) visible and obvious.
>>
>> I can't understand why the parser requires me to type "fun M:F/A" when
>> the "/" character clearly indicates that I'm referencing a function in
>> a special way.
>
> The question is, in a language without static types, how do you
> tell the difference between an intentional foo/2 meaning a function
> and an erroneous foo/2 that should have been Foo/2, with Foo a
> variable bound to a number.
We're never going to get static types in Erlang, so I think the answer
is that you'd end up with a failing unit or integration test case. Not
sure how to do a "raised eyebrow" smiley.
>
> What _I_ don't understand is why fun F/2 is not allowed with F a
> variable.
>
Yeah, most annoying.
>> And if the compiler can recognise a reference to a
>> function (local or otherwise), then why not have it recognise "+" as
>> an operator for chaining function calls?
>
> Well, I've done enough mathematics to be driven screaming with rage
> up the nearest handy wall at any use of "+" for an operation that is
> not commutative. The operation you want here is often called ";" in
> denotational semantics. It's (F;G) X = G(F(X)).
Sheesh I hadn't thought about commutativity - yes '+' is a bad choice
in light of that. We aren't going to get ';' used in this way are we,
given it's existing role in the syntax. Perhaps avoiding overloaded
operators would be sensible, though I have to admit that Haskell's use
of '.' is very clean, though inadmissible for the same reason.
>
> Again, in general the compiler *CANNOT* recognise a reference to a
> function. Haskell and SML manage that by means of type checking,
> and *they* don't overload function composition with any other
> operation.
>
The compiler knows full well that (<module>)<name>/<arity> evaluates
to a fun!? I'm aware that we don't have type checking at compile time.
I'm also vaguely aware of how things work in Haskell/SML. What I'm not
aware of is what the combination of *ASTERISK AND CAPITAL LETTERS*
means. ;-)
More information about the erlang-questions
mailing list