[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