[erlang-questions] FW: Any wisdom to offer on "tagged return values"

Bryan Fink bryan.fink@REDACTED
Thu May 7 16:34:44 CEST 2009


On Wed, May 6, 2009 at 1:24 PM, David Mercer <dmercer@REDACTED> wrote:
> You could always extract the element you want of a tuple using element/2
> thus allowing chaining.  E.g.:
>
>        element(2, {ok,_} = dict:find(...))

Having used this approach myself before, I couldn't resist enumerating
its alternatives (except for parse transform :P):

-module(tagged_tuples).

-export([ex1/0, ex2/0, ex3/0, ex4/0, ex5/0, ex6/0]).

ex1() ->
    {ok, This} = get_this(),
    {ok, That} = get_that(This),
    {ok, Next} = get_next(That),
    Next.

ex2() ->
    element(2, {ok, _}=get_next(element(2, {ok, _}=get_that(element(2,
{ok, _}=get_this()))))).

-define(OK(Expr), element(2, {ok, _}=Expr)).
ex3() ->
    ?OK(get_next(?OK(get_that(?OK(get_this()))))).

-define(UW(Match, Expr), element(2, {Match, _}=Expr)).
ex4() ->
    ?UW(ok, get_next(?UW(ok, get_that(?UW(ok, get_this()))))).

ok({ok, Val}) -> Val.
ex5() ->
    ok(get_next(ok(get_that(ok(get_this()))))).

uw(Match, {Match, Val}) -> Val.
ex6() ->
    uw(ok, get_next(uw(ok, get_that(uw(ok, get_this()))))).

get_this() -> {ok, this}.
get_that(this) -> {ok, that}.
get_next(that) -> {ok, next}.


As written, ex1-6/0 will each return the atom 'next':

> tagged_tuples:ex1().
next
> tagged_tuples:ex2().
next
> tagged_tuples:ex3().
next
> tagged_tuples:ex4().
next
> tagged_tuples:ex5().
next
> tagged_tuples:ex6().
next


Change any of the 'ok' atoms in get_*, though, and you'll get various
kinds of errors:

> tagged_tuples:ex1().
** exception error: no match of right hand side value {bork,this}
     in function  tagged_tuples:ex1/0
> tagged_tuples:ex2().
** exception error: no match of right hand side value {bork,this}
     in function  tagged_tuples:ex2/0
> tagged_tuples:ex3().
** exception error: no match of right hand side value {bork,this}
     in function  tagged_tuples:ex3/0
> tagged_tuples:ex4().
** exception error: no match of right hand side value {bork,this}
     in function  tagged_tuples:ex4/0
> tagged_tuples:ex5().
** exception error: no function clause matching tagged_tuples:ok({bork,this})
     in function  tagged_tuples:ex5/0
> tagged_tuples:ex6().
** exception error: no function clause matching tagged_tuples:uw(ok,{bork,this})
     in function  tagged_tuples:ex6/0


Completely dodging the question of whether you *should*, it's good to
have a few strategies to work with code that *does*.  (Also dodging
the question of which alternative is "best", "nicest", etc.)

-Bryan



More information about the erlang-questions mailing list