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

Hynek Vychodil hynek@REDACTED
Wed Feb 1 10:52:59 CET 2012


Disclaimer: It is mine explanation which works for me and makes me happy.
F is not designator per se but designator of variable. Erlang is
dynamic strong typed language, every value in variables have it's own
type. module:fun is not value and doesn't have type. {module,fun} is
value and has type 2-tuple with two members of atom type.
F() means call (apply) func in variable F but there is hack, that
above tuple type is magically converted to func under-hood which is
scheduled for removal in R16. So if you want use F() operation you
have to assign proper func value to variable F first and it is `F =
fun module:fun/0`.
Note that M:F() is different operation with different arity and also
accepts different types. It is perfect consistent for me at least and
it is mine explanation why it works and doesn't surprise me.

On Wed, Feb 1, 2012 at 10:05 AM, Jakob Praher <jakob@REDACTED> 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 <bengt.kleberg@REDACTED> 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" <jakob@REDACTED> 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" <jakob@REDACTED> 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 <erlang@REDACTED> 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
>> > > > > <reynaldomic@REDACTED> 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
>> > > > > > erlang-questions@REDACTED
>> > > > > > http://erlang.org/mailman/listinfo/erlang-questions
>> > > > > _______________________________________________
>> > > > > erlang-questions mailing list
>> > > > > erlang-questions@REDACTED
>> > > > > http://erlang.org/mailman/listinfo/erlang-questions
>> > > >
>> > > >
>> > > >
>> > > >
>> > > >
>> > > > _______________________________________________
>> > > > erlang-questions mailing list
>> > > > erlang-questions@REDACTED
>> > > > http://erlang.org/mailman/listinfo/erlang-questions
>> > >
>> > >
>> > >
>> > >
>> > >
>> >
>> >
>> >
>> >
>> >
>> > _______________________________________________
>> > erlang-questions mailing list
>> > erlang-questions@REDACTED
>> > http://erlang.org/mailman/listinfo/erlang-questions
>>
>> _______________________________________________
>> erlang-questions mailing list
>> erlang-questions@REDACTED
>> http://erlang.org/mailman/listinfo/erlang-questions
>
>
>
>
>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions



-- 
Hynek Vychodil
BI consultant

GoodData
náměstí 28. října 1104/17, 602 00, Brno - Černá Pole
Office:   +420 530 50 7704
E-mail:  hynek@REDACTED
Web:     www.gooddata.com



More information about the erlang-questions mailing list