Rethinking Auto-Gathered SET-WORD! Locals

#1

Having to explicitly declare locals at the top of your FUNC is certainly primitive, so there needs to be another answer.

It's important to have a way to annotate variables as being local declarations at the place you use them.

...but...I think that the decision to consider this annotation to be implicit with a SET-WORD! in R3-Alpha's FUNCTION is probably a bad idea (...for anything but a code golf language).

It creates too many spurious locals

There are many reasons you might use SET-WORD!s and not all of them warrant a local. We say these are generic dialecting parts, they don't have to mean anything related to assignment at all (though it helps if they are, usually). But even common assignment-related usages make a bunch of stray locals:

something: ...  ; some "global" thing you want to reference

foo: function [...] [
    something  ; this is null because a something: was gathered below!

    obj: make object! [
        field1: ...  ; why would FOO now have a <local> named field1 ?
        field2: ...  ; and why now a <local> named field2 ?
    ]

    bar: function [...] [
         something: ...  ; this is a local in BAR, but why in FOO too??
    ]
 ]             

Gathering locals you don't need is inefficient. You're using more storage space for the function's frame, for a variable you're never going to use. It makes the function slower to call, and also looks confusing if you look in the debugger to see a bunch of spurious locals for the frame.

It's also inconvenient--because as with something above, it may cause a variable to be nulled out that you actually had meant to use.

I think we should require an annotation

It doesn't seem to me to be too terrible to have people say let x: 10 or var x: 10 instead of just x: 10. (I'll suggest var for today's method because it would get effectively "lifted", and I have some more interesting "virtual binding" ideas for let)

Like I say, it's not that something like an auto-gathering FUNCTION just from a SET-WORD! shouldn't exist. The whole point of Rebol is that you can make such things if you want them. But the idea strikes me as flawed enough in most applications that you should do some extra typing.

Then, what we can do is just say that any SET-WORD! which aren't covered by this get unbound. If they try to run in the evaluator, you get an error.

Not a big change so much as naming change

We'll just have to come up with a name or setting for the gathering function.

Preferably not FUNCT (which is what Rebol2 called the gatherer). :slight_smile:

Having a way to express a desire to auto-gather locals in the spec, e.g. <local> #set-word! or <autolocal> or something like that is a possibility.

Questions/Comments/Concerns?

#2

In the annotating proposal I'm making here, VAR would be scanned for by name by FUNCTION. This would make it a sort of "keyword" in the "function body dialect" :-/ (though perhaps you could override it, e.g. by saying <varword> myvar in the spec).

But I don't suggest removing it from the body. I suggest leaving it there. But then, it could have a behavior at runtime like this:

>> var x: 10
== 10

>> var [x y z]: [10 20 30]
== [10 20 30]

>> var x
== x

>> var [x y z]
== [x y z]

So it would be a variadic which would look at its right, see if it was a SET-WORD! or a SET-BLOCK!, and if so run one unit of evaluation and return the result. If it were a WORD! or a BLOCK! it would return the word or block as is...acting like LIT would.

This would give you the ability to do something like both declare a local and SET it, as in:

set var x do whatever

Because it would be looked for literally, it would suffer the same problem that source-level vs. generated set-words do today...

 foo: function [] [
     do compose [
         var (to word! "wontwork"): 10
         print [wontwork]
     ]
 ]

But this is where I'm hoping that the implementation tricks I have in mind for let would be able to work.

#3

routine! seems to be unused.