What happens to function args when the call ends?

What happens to function args when the call ends?

For many years, it's been accepted that function arguments outlive the function.

I think that's right. The bias should clearly be to let them live as long as references exist... and you have to ask for them to be thrown away, e.g. FUNCTION:LITE.

Perhaps those who are biased to efficiency might define FUNC as the LITE version. Or maybe even that could be the default for FUNC? So long as you got a good error accessing dead variables telling you "hey this frame was destroyed because you used FUNC instead of FUNCTION" that might be a good tradeoff.

Needing Values To Outlive Is Actually Kind of Rare

I broke the feature accidentally, and didn't notice for a bit until I looked into why QUIT had stopped working. It turns out that QUIT depended on it, because it wraps up a function you pass in that represents your local notion of QUIT (quit*). That's a parameter to MAKE-QUIT, used by the produced quit function.

But the interesting thing is that the system STILL mostly works without it. So I do think we'd likely benefit by finding some way to prune the cases.

FUNC being a lesser-featured version of FUNCTION on this axis feels like it might be the right psychological hack. It makes the language feel more solid, compared with needing CLOSURE to pick up the slack from a weak FUNCTION.

"Noticing When Things Outlive Stack Levels" Is Gone

These mechanics were wiped out a long time ago. They were incompatible with generators and other ideas, and very tricky.

And things have gotten even harder to rein in. Due to how modern binding works, if you write something like:

                            v-- the FRAME! inherits this block's binding
foo: function [msg [text!]] [
   print ["Message is:" msg]
   return [1 2 3]
]

When that [1 2 3] block was "evaluated", it captured a binding... of the FRAME! and whatever that frame inherited from the body. So you'd be returning a BLOCK! with a binding that rolls in all of that.

If you want to avoid this, you have to write:

foo: function [msg [text!]] [
   print ["Message is:" msg]
   return '[1 2 3]  ; <-- tick mark needed to dodge binding capture
]

It's seems a bit sad to have to say "if you don't ugly up your code with tick marks, it won't be as good... so you should quote your data blocks when they're just data".

BUT on the other hand, I've definitely seen places where that's a helpful cue that your BLOCK! is in an evaluative context. So it does have some benefits, and I'm warming up to it.