Today's vocabulary word is divergent functions...when a function never returns a result in a "normal" way.
All functions that can PANIC or be THROWN or RETURN'd across have divergence as an option (which is, right now, all functions). But it becomes an issue of what to say when there really is no type a function ever returns...what do you put in the spec?
Lately I've been using just [return: []]. That seems pretty solid. An empty block indicating there's no types you can return...so any return would generate an error.
There's a practical advantage to choosing [return: []]. This means that if you're merging type specs from two different functions, adding one function's types to the others will implicitly erase the "only divergent" property unless both functions were "only divergent".
But because I can imagine people not knowing what that meant, I find myself always adding a comment so people can look up the term "divergent":
We have a new conundrum... in that I no longer think that [~foo~] means "antiform of foo" in function specs.
I said that the introduction of CHAIN!s and arbitrary SIGIL!s meant we'd be needing more destructuring. Well, that's coming in the types:
[~word!~] would match a quasiform word!
['word!] would match a quoted word
[@block!] would match a pinned block
[word!:] will match a "set-word-like CHAIN!"
[integer!.integer!.integer!] will match a TUPLE of 3 integers, e.g. 1.2.3
As exciting as all that is...it's also moving toward some literalism, where [_] would match space (what was blank), [$ ^ @] would match tie/lift/pin, etc. etc. (Tags still aren't literal, they're parameter options, and I don't know what other things would be literal.)
The importance of all this threatens my beloved return: [~] for "return trash". It would be "return quasar" e.g. quasiform space.
So the only thing more coveted in lexical space than return: [~] here would be to take return: [] for "returns trash", e.g. nothing interesting to return.
So... Divergence With Something Not-A-Block?
return: <!> looks pretty good for divergence (although maybe a bit too alarming, as if that should be a shorthand for returns ERROR!...)
But Of Course This Breaks The Nice Property
That property may be too good to lose.
Maybe it's the returning trash shorthand that should move out of the way? Maybe even lighter:
return: ~
If you say that, then what your actual return spec is becomes return: [trash!]
Due to being able to graft methodization-complicity into the spec with <.>, we no longer need to be afraid of making "too many different kinds of function generators". So PROCEDURE has made a comeback, for instance...
This makes me think DIVERGENT (or DIVERGER? DIVERGES?) could itself be a generator:
catch [
my-non-returning-function: divergent [ ; diverger ? diverges ?
"Your function spec here"
<.> ; maybe it's a method, even...
][
if .date.month = 8 [
return "It's August" ; oops, meant THROW (no RETURN defined!)
]
throw "It's not August"
]
my-non-returning-function
]
Here we get better enforcement... because the generator can not define RETURN, and it can also panic if it reaches the end of the "lambda-like-thing".
I think the value of reporting whether a function is divergent in the HELP is of limited value, and it's not very actionable in terms of composition of return typespecs, since we don't prevent any function from PANIC-ing.
But this gives us something actually useful, and it still uses the vocabulary word!
It might seem there's a contradiction here... if the meaning of return: [] is "I'm divergent" then why would you have a RETURN in the first place?
But as we know: sometimes code is generated... and if you have a BLOCK! that is produced by merging lists of types together, then if that block comes up empty... you might not want to be proactive in saying "no, you can't make that function with a RETURN"... but rather, let the problem happen if you ever actually get the RETURN called.
This seems pretty good, actually. I think the missing block helps you realize "oh this doesn't return anything" in a more visceral way, leading you to step up and take notice a little more if you see a function with an empty block and go "oooh, what's that mean? NO types?"
For better or worse, it makes return: ~ line up directly with return ~
Not having the block there helps also communicate that the feature might be "weird" (it has gotten weird, and puts the symbol of the function call as the symbol of the trash... to help you downstream trace back to where a trash might have come from).
This makes me think DIVERGENT (or DIVERGER? DIVERGES?) could itself be a generator:
DIVERGER is probably a dumb idea, if return: [] is how you indicate divergence. That's clear enough.
I guess the only argument for it would be if you want a LAMBDA diverger, and don't like the look of []: [] in the spec, and feel it's more literate to say "diverger"