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

Jakob Praher jakob@REDACTED
Wed Feb 1 10:05:16 CET 2012


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
 
 
 
 




More information about the erlang-questions mailing list