[erlang-questions] Why doesn't Erlang has return statement?

aman mangal <>
Wed Dec 17 11:07:45 CET 2014


I understand what to do if the only way out is to use *return *but I think
it takes away the fun of writing Erlang code and makes the program
difficult to understand. More importantly, as the Garrett Smith explains in
the video that it is important to write quality code than worrying too much
about say performance as of today and *return *statement is definitely not
the way to go. I like the approach of writing functions than using case
expressions as he explained that functions are just named case expressions,
and if next function call is the last statement in current function it
won't affect performance as well if I even think about it. Great
discussion, I have learnt so much of Erlang in such a short time, thank you
so much!

Aman Mangal

On Wed Dec 17 2014 at 4:20:21 AM Joe Armstrong <> wrote:

> The question was : Why doesn't Erlang have a return statement
>
> I can let you into a secret - the first version of Erlang *did* have a
> return statement
>
> return was written ^Expression.
>
> Something like:
>
> foo() ->
>     a,b,^c.
>
> Erlang with a return statement would look something like:
>
> foo() ->
>    a,
>    b,
>    return(c).
>
> Here's some little fragments of code with returns
>
> foo(X) ->
>    case g(X) of
>       pattern1 ->
>            a(), b, return(c);
>       pattern2 ->
>           do,de,dar, return(z)
>    end.
>
> Now what would happen if all the branches in the case clause didn't
> do a return?
>
> We could write:
>
> foo(X) ->
>    case g(X) of
>       pattern1 ->
>            a(), b, return(c);
>       pattern2 ->
>           do,de,dar, return(z);
>       pattern3 ->
>           Y = h(H), P = z(Y)
>    end,
>    foo(),
>    return(P).
>
> Which kind of sucks - case is now NOT a function with a return value
> it's something that either returns a value OR binds some variables
> whose values escape from the case construction. In this case
> P escapes so we can use it after the case construct.
>
> This is a bit messy so we might rewrite it like this
>
> foo(X) ->
>    P =  case g(X) of
>            pattern1 ->
>              a(), b, return(c);
>            pattern2 ->
>              do,de,dar, return(z);
>            pattern3 ->
>              Y = h(H), z(Y)
>    end,
>    foo(),
>    return(P).
>
> Again case is "funny" - from a flow of control point of view it can
> either a) return to the caller or b) carry on executing *after* the
> end statement.
>
> This actually makes it difficult to understand. It's really easy to
> "see" this in the small example above - but if the case statement had
> dozens of branches and one of them had a return in and all the others
> didn't this would be very difficult to spot.
>
> Now there are actually two methods for making an abrupt return
> from a function - exit(Expr) and throw(Expr).
>
> Both are in a sense "returns" (note the quotes).
>
> exit is for an abnormal return - throw is used to break out of
> computation, ie to return a value to some grand parent of the called
> function.
>
> In the absence of return(X) you can write throw(X) but this
> can make your programs more difficult to understand if abused.
>
> Cheers
>
> /Joe
>
> On Tue, Dec 16, 2014 at 11:58 PM, Viktor Söderqvist
> <> wrote:
> > On 2014-12-16 09.05, aman mangal wrote:
> >
> > Moreover, is there a good alternate to avoid nested case statements?
> >
> > One way is to avoid them is actually not to write them. Especially if the
> > cases are error handling, handle only the expected case and let
> everything
> > else crash.
> >
> > When I'm parsing some input or structure and want to return {ok, Value}
> or
> > 'error' instead of crashing, I often wrap that code in a try-catch. This
> is
> > only when dealing with untrusted input and similar situations.
> >
> > parse_foo_url(URL) ->
> >     case http_uri:parse(URL) of
> >         {ok, {_, _, _, _, Path, _}} ->
> >             case re:split(Path, "/", [{return, list}]) of
> >                 ["", "foo", Foo] ->
> >                     try list_to_integer(Foo) of
> >                         FooInt -> {ok, FooInt}
> >                     catch error:_ ->
> >                         error
> >                     end;
> >                 _BadPath ->
> >                     error
> >             end;
> >         _BadUri ->
> >             error;
> >     end.
> >
> > ---->
> >
> > parse_foo_url(URL) ->
> >     try
> >         {ok, {_, _, _, _, Path, _}} = http_uri:parse(URL),
> >         ["", "foo", Foo] = re:split(Path, "/", [{return, list}]),
> >         FooInt = list_to_integer(Foo),
> >         {ok, FooInt}
> >     catch error:_ ->
> >         error
> >     end.
> >
> > Using catch statement seems another good alternate but my intuition is
> that
> > it is not good practice, is it?
> >
> > In the above example I dare to say it's not bad practice. Just don't
> overuse
> > try-catch so that it becomes defensive programming and make sure you
> don't
> > put any other code inside the try-catch so that you accidentally catch
> > totally unrelated errors.
> >
> > Viktor
> >
> > _______________________________________________
> > erlang-questions mailing list
> > 
> > http://erlang.org/mailman/listinfo/erlang-questions
> >
> _______________________________________________
> erlang-questions mailing list
> 
> http://erlang.org/mailman/listinfo/erlang-questions
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20141217/1ec6be8e/attachment.html>


More information about the erlang-questions mailing list