[erlang-questions] Orthogonality and Principle of least surprise Was: chained functions

Jon Watte <>
Fri Feb 3 19:18:52 CET 2012


The question is: why is the grammar like that?
For people used to first class functions, Erlang doesn't actually live
up to the expectation.
I think there are both runtime efficiency and legacy implementation
reasons for this.

Note that it's a bit ambiguous what this would mean in the face of code loading:

F = module:fun
Now, reload "module"
Does F() call the old code, or the new code? I could see an argument
for either way, but the more useful behavior would be to call the new
code.

Sincerely,

jw


--
Americans might object: there is no way we would sacrifice our living
standards for the benefit of people in the rest of the world.
Nevertheless, whether we get there willingly or not, we shall soon
have lower consumption rates, because our present rates are
unsustainable.



On Wed, Feb 1, 2012 at 1:17 AM, Bengt Kleberg
<> wrote:
> I think {module,fun} is a complete ''thing'' (grammar item?) whereas
> module:fun is lacking a final () to be complete.
>
>
> bengt
>
>  On Wed, 2012-02-01 at 10:05 +0100, Jakob Praher wrote:
>> Thanks for your reply.
>>
>> As a counterargument F = {module,fun}, F(). works.
>> Also in this case F is just the designator and not the function itself.
>>
>> It would be possible for instance to evaluate module:fun as {module,fun}.
>>
>> Best,
>> Jakob
>>
>>
>>
>> Am Mittwoch, 01. Februar 2012 09:14 CET, Bengt Kleberg <> schrieb:
>>
>> > Greetings,
>> >
>> > This is perhaps totally wrong but in my mind allowing
>> > F = module:fun,
>> > F().
>> >
>> > would also mean that this is good:
>> > F = module:fun(,
>> > F).
>> >
>> > Ie, "F = module:fun" is text/syntax, not semantic.
>> >
>> >
>> > bengt
>> >
>> > On Wed, 2012-02-01 at 09:05 +0100, Jakob Praher wrote:
>> > > Hi Erlangers,
>> > >
>> > > I think people should pay attention to issues faced by experienced newcomers in exercising Erlang programming. Matz from Ruby calls a ver important design principle, the principle of least surprise.
>> > >
>> > > No matter that the following may be a syntactic surface issue, but designating function objects is neither orthogonal nor does follow the expectations of the programmer. Therefore it also makes understanding code harder.
>> > >
>> > > if I can write:
>> > >      module:fun().
>> > > I should be also able to write
>> > >      F = module:fun, F().
>> > > and not having to write
>> > >      F = fun module:fun/0, F().
>> > > .
>> > >
>> > > I am happy to learn why module:fun is not an expression.
>> > >
>> > > Best,
>> > > Jakob
>> > >
>> > >
>> > > Am Dienstag, 31. Januar 2012 14:07 CET, "Jakob Praher" <> schrieb:
>> > >
>> > > >
>> > > > As I tried out the code below I learned that tuples of module and function atoms evalute to functions, not atoms by themselves.
>> > > > If one can apply arguments to a tuple, why not to an atom if this would be denote a function in the current environment?
>> > > >
>> > > > {R, V} = apply_each([{m1,z},{m2,y},{m3,x}], Arg).
>> > > > if R = ok -> ...
>> > > >
>> > > > Thanks,
>> > > > Jakob
>> > > >
>> > > >
>> > > > Am Mittwoch, 25. Januar 2012 14:29 CET, "Jakob Praher" <> schrieb:
>> > > >
>> > > > >
>> > > > > One could also compose a sequence of functions much like in combinator parsing, and fail at the first event returning the error status, otherwise continue to call apply the functions to the result.
>> > > > >
>> > > > > apply_each([F|FS],X) ->
>> > > > >       {S, V} = F(X),
>> > > > >       if S = error  ->
>> > > > >             {S, V}
>> > > > >          S = ok ->
>> > > > >             apply_each(FS, V);
>> > > > >       end
>> > > > >       .
>> > > > >
>> > > > > {R, V} = apply_each([z,y,x], Arg).
>> > > > > if R = ok -> ...
>> > > > >
>> > > > > I have not much practice in Erlang (though I have some practice in Prolog), so this might not be 100 % correct.
>> > > > >
>> > > > > Cheers,
>> > > > > Jakob
>> > > > >
>> > > > > Am Mittwoch, 25. Januar 2012 13:16 CET, Joe Armstrong <> schrieb:
>> > > > >
>> > > > > > I think you are asking the wrong question. If a function returns
>> > > > > > {ok,Val} | {error,Reason}
>> > > > > > then I think to myself "the caller of this function expects things to
>> > > > > > go wrong and is
>> > > > > > committed to handling *both* return values.
>> > > > > >
>> > > > > > So they would *never* write w(x(y(z(....))) because this does not cater for both
>> > > > > > return values.
>> > > > > >
>> > > > > > With the "let it crash" philosophy one would make w,x,y, .. return a
>> > > > > > value OR call exit(...).
>> > > > > > With this convention things do nest in the "happy" case without using
>> > > > > > a staircase.
>> > > > > >
>> > > > > > At the top level try or catch is used to catch the error.
>> > > > > >
>> > > > > > Alternatively you could say
>> > > > > >
>> > > > > >   ok({ok,X}) -> X;
>> > > > > >   ok{error,E}) -> exit(E).
>> > > > > >
>> > > > > > and then
>> > > > > >
>> > > > > >    w(ok(x(ok(y(ok(z(X))))))
>> > > > > >
>> > > > > > Not pretty but it does the job
>> > > > > >
>> > > > > > /Joe
>> > > > > >
>> > > > > >
>> > > > > > On Tue, Jan 24, 2012 at 8:31 PM, Reynaldo Baquerizo
>> > > > > > <> wrote:
>> > > > > > >
>> > > > > > > A friend of mine asked:
>> > > > > > >
>> > > > > > > ##
>> > > > > > > If you have functions that return {ok, Result} | {error, Reason}
>> > > > > > > how do you chained them? So that you have:
>> > > > > > >
>> > > > > > > w(x(y(z(...))))
>> > > > > > >
>> > > > > > > without building a staircasing. Something that would be done in Haskell
>> > > > > > > with monads.
>> > > > > > > ##
>> > > > > > >
>> > > > > > > I would probably go for:
>> > > > > > >
>> > > > > > > x({ok, Value}) ->
>> > > > > > >  NewValue = <do something with Value>,
>> > > > > > >  {ok, NewValue};
>> > > > > > > x({error, Reason}) ->
>> > > > > > >  {error, Reason}.
>> > > > > > >
>> > > > > > > in each function
>> > > > > > >
>> > > > > > > which brings me other question, when do you tag return values?
>> > > > > > >
>> > > > > > > I tend to only use tagged return values with impure functions, were an
>> > > > > > > error is more likely due to side effects.
>> > > > > > >
>> > > > > > > --
>> > > > > > > Reynaldo
>> > > > > > > _______________________________________________
>> > > > > > > erlang-questions mailing list
>> > > > > > > 
>> > > > > > > http://erlang.org/mailman/listinfo/erlang-questions
>> > > > > > _______________________________________________
>> > > > > > erlang-questions mailing list
>> > > > > > 
>> > > > > > http://erlang.org/mailman/listinfo/erlang-questions
>> > > > >
>> > > > >
>> > > > >
>> > > > >
>> > > > >
>> > > > > _______________________________________________
>> > > > > erlang-questions mailing list
>> > > > > 
>> > > > > http://erlang.org/mailman/listinfo/erlang-questions
>> > > >
>> > > >
>> > > >
>> > > >
>> > > >
>> > >
>> > >
>> > >
>> > >
>> > >
>> > > _______________________________________________
>> > > erlang-questions mailing list
>> > > 
>> > > http://erlang.org/mailman/listinfo/erlang-questions
>> >
>> > _______________________________________________
>> > erlang-questions mailing list
>> > 
>> > http://erlang.org/mailman/listinfo/erlang-questions
>>
>>
>>
>>
>>
>
> _______________________________________________
> erlang-questions mailing list
> 
> http://erlang.org/mailman/listinfo/erlang-questions



More information about the erlang-questions mailing list