metaeducation / ren-c

Library for embedding a Rebol interpreter into C codebases
GNU Lesser General Public License v3.0
126 stars 27 forks source link

Functions can be invisible sometimes, vs always #1090

Closed hostilefork closed 3 years ago

hostilefork commented 3 years ago

This makes invisibility a return state that a function can have...but it can decide that while it is running. (Previously a function could be either fully invisible or not at all invisible, based on the return spec being return: [] or not.)

Returning invisibly is done by providing the return value via code to run inside of a @(...) hence just returning invisibly an be done as easily as @():

 >> foo: func [x] [print [x] return @()]

 >> <before> foo 10
 10
 == <before>

The likely-temporary way to indicate that invisibility is one of the return options in a spec is by saying <invisible>:

>> vanish-if-odd: func [return: [<invisible> integer!] x] [
       if even? x [return x]
       return @()
   ]

>> <test> vanish-if-odd 2
== 2

>> <test> vanish-if-odd 1
== <test>

The benefit of having the form for invisible-enabled return done as giving code is that it can chain, e.g. if you have another function that is sometimes-invisible and sometimes-not, you can put the call to that function inside the @(...) and it will be proxied:

>> vanish-if-even: func [return: [<invisible> integer!] y] [
       return @(vanish-if-odd y + 1)
   ]

>> <test> vanish-if-even 2
== <test>

>> <test> vanish-if-even 1
== 2

Note that plain RETURN could not do this, because the vanishing case would appear to be just the same as RETURN, which would return void.

hostilefork commented 3 years ago

@giuliolunati This is a pretty neat feature, I think! Notice that if you have used invisibles previously via return: [] (so that any return result will be erased, if it falls out the bottom of the function) then that feature is now return: <elide>. And you can no longer use plain return in such functions as that means "return void"...you have to use return @()

@IngoHohmann You seem to have looked forward to this so if you can help with more tests that would be great. It's very new and weird and will probably have edge cases for years to come, but I think invisibility brings a lot to the table for letting people exploit evaluative slots to their fullest. (RE: the "new and weird" statement, I'll mention that there's more to it than just this one commit.)