Question on functional style

Ulf Wiger (AL/EAB) ulf.wiger@REDACTED
Fri Sep 9 20:14:45 CEST 2005


Sure, why not? This is basically what throw() is for, right?

start(Arg) ->
  F = fun(X) case lists:member(X, Arg) of
                true -> throw(done);
                false -> ok
             end
      end,
  try [F(X) || X <- [foo,bar,baz]] of
     _ -> ok
  catch
      throw:done -> phase2()
  end.

(A matter of taste, surely.)

/Uffe

> -----Original Message-----
> From: owner-erlang-questions@REDACTED
> [mailto:owner-erlang-questions@REDACTED]On Behalf Of Vance Shipley
> Sent: den 9 september 2005 19:10
> To: erlang-questions@REDACTED
> Subject: Question on functional style
> 
> 
> Gurus,
> 
> Is it bad form to use try/catch to handle non-local returns
> other than exceptions?
> 
> I have some code which does a battery of tests in several phases.
> The tests are simple so it makes sense to me to just perform 
> them sequentially in one function and throw when I want to skip
> to the next phase:
> 
> start(Arg) ->
>     try begin
>         case lists:member(foo, Arg) of
>             true ->
>                 throw(done);
>             _ ->
>                 ok
>         end,
>         case lists:member(bar, Arg) of
>             true ->
>                 throw(done);
>             _ ->
>                 ok
>         end,
>         case lists:member(baz, Arg) of
>             true ->
>                 throw(done);
>             _ ->
>                 ok
>         end
>     end
>     catch
>         throw:done ->
>             phase2()
>     end.
> 
> phase2() ->
>     done.
> 
> 
> While this is easiest for me to understand my own code I wonder
> whether it is good functional style.  I do end up with a very
> large function and the throw is not really an "exception".
> 
> Alternatively I can hard cpode the sequence into the test functions:
> 
> start(Arg) ->
>     f1(Arg).
> 
> f1(Arg) ->
>     case lists:member(foo, Arg) of
>         true ->
>             phase2();
>         _ ->
>             f2(Arg)
>     end.
> 
> f2(Arg) ->
>     case lists:member(bar, Arg) of
>         true ->
>             phase2();
>         _ ->
>             f3(Arg)
>     end.
> 
> f3(Arg) ->
>     case lists:member(baz, Arg) of
>         true ->
>             phase2();
>         _ ->
>             ok
>     end.
> 
> phase2() ->
>     done.
> 
> 
> I find this makes it harder to follow the sequence and the tests
> can't be reused in a different order.  I could pass the next function 
> as an argument I suppose ...
> 
> It seems to me that the above is less deterministic.  The return 
> from f1/1 depends on what happens in f2,f3,...fn.
> 
> Using the first form I can actually perform many of the tests using
> an if statement and pattern matching.
> 
> Your opinions are welcome.
> 
> 	-Vance (who has never taken a CS course)
> 
> 



More information about the erlang-questions mailing list