[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Features to remove: return and noreturn



I understand that $&noreturn is a relatively new feature of the es
landscape, so I'll probably attract a lot of flamage when I propose to
get rid of it.  Not only that, I'll propose to throw away return as
well!  Don't get out the old flame throwers yet -- please listen me
out -- the reason is this: There is already a perfectly decent catch
and throw mechanism in place; and the return mechanism is nothing but
using throw with the extra magic that functions capture thrown
returns.  Unless of course they are being run with $&noreturn.  I find
this kludgy and confusing.

It can also cause subtle errors:

fn foo { ...
        # deep inside multiple nesting levels:
        return $bar
        ....}

Now the writer finds that e can more efficiently, or perhaps more
elegantly, express the foo function by using an auxiliary function:

fn foo { let (aux = @ args { .... }) blah blah; $aux $stuff; ...}

However, in copying a healthy chunk of code into the body of aux, e
includes the return statement of the original foo, breaking the code.

Now, of course I do not intend to force the user to deal with raw
catch and throw.  All we need is a convenience function.  I'd call it
tag, but other suggestions are welcome:

fn tag name cmd {
  catch @ e x {if {~ $e $name} {result $x} {throw $e $x}} \
        {local (fn $name x {throw $name $x}) $cmd}}

Now, local and non-local returns are handled in exactly the same way,
namely by tagging the function and by using the tag to return values.
For example, here is a function that given three arguments will return
one of them if the two other are equal:

fn f a b c {
  tag retvrn {let (g = @ a b c {if {~ $a $b} {retvrn $c}})
                {$g $a $b $c; $g $b $c $a; $g $c $a $b; result}}}

At the minimal price of declaring the return tag, the user is given
the freedom of not having to worry about the number of levels his
returns have to ascend.  Besides, I would assume that many present
uses of return could easily be replaced with result, perhaps after
some rewriting:

fn foo {                              fn foo {
  if {test} {return bar}    -->      if {test} {result bar} {
  blah blah ...}		          blah blah ...}}


At the risk of distracting you away from the above suggestion, let me
take another look at my suggestion to get rid of `do', which met with
such resistance.  If people want do for its convenience I guess it
stays in, but there is still no reason why we could not throw away at
least the many-variable do and let the simple case be syntactic sugar:

Rewrite    do (x = x1 x2 ...) {cmd}   as    %do @ x {cmd} x1 x2 ...

and define the hook function %do along the lines of

fn %do fun list {let (x=) {while {x list=$list; !~ $#x 0} {$fun $x}}}

assuming, of course, the multiple assignment feature that Paul has
promised us.


Summary of suggestions:

1.  Functions should no longer catch `return' exceptions.
2.  Hence $&noreturn is obsolete.
3.  Provide the `tag' function, written in es, for convenience.
4.  Throw away multiple-list `do' and re-implement the single list
    `do' as syntactic sugar.

- Harald