Hi, Rishi,

My uninformed $0.02...

(Note that I try to make an alternative suggestion at the
end of my discussion.  I'd be interested in feedback on
that idea!)

The main root problem I have with your suggestion is that it
seems to make an assumption about REBOL that I do not believe
to be true -- that there's some sort of conventional "compile"
step that preprocesses the entire text of a piece of code
before generating some internal representation.

For why I think this, see below.  Please let me know if I
have misunderstood your meaning...

Rishi Oswal wrote:
> 
... 
> What I would like to see is another shortcut to
> creating local variables in any context (function,
> innerfunction, loop). The obvious way I see of doing
> this is as follows:
> 
> myfunc: func [][
>   localvar:: $25
>   myinnerfunc: func [][
>     innerlocal:: $10
>     print localvar ; prints $25
>   ]
>   print innerlocal; error!
> ]
> print localvar ; error!
>

Based on your description, should I infer that you would like
the above to be equivalent to?

    myfunc: func [/local localvar myinnerfunc] [
        localvar: $25
        myinnerfunc: func [/local innerlocal] [
            innerlocal: $10
            print localvar
        ]
        print innerlocal ; error
    ]
    print localvar ; error

Note that I assumed you meant for MYINNERFUNC to be local to
MYFUNC even though you didn't use the double colon (because
of the way you named it).

Do you intend the above meaning or do you intend an
alternative meaning, such as:

    myfunc: func [] [
        use [localvar] [
            localvar: $25
            use [myinnerfunc] [
                myinnerfunc: func [] [
                    use [innerlocal] [
                        innerlocal: $10
                        print localvar
                    ]
                ]
                print innerlocal ; error
            ]
        ]
    ]
    print localvar ; error

Alternately, I could pose it as two questions:

1)  What context do you think should contain the double-colon
    variables?

    1a)  The context of the smallest enclosing function
         definition?

    1b)  A new context whose scope is described below?

2)  How far should the scope of that context extend (lexically
    I mean)?

    2a)  From just before the double-colon expression to the end
         of the enclosing block?

    2b)  From the beginning of the enclosing block to the end of
         the enclosing block?

    2c)  Just the following expression?

>
> using the "::" for local var will make it more
> convienient to create local vars (which i use all the
> time over global vars). In addition, it will help
> prevent some errors of accidental global var creation
> because it is now easy to spot a local var.
>

Pardon me, but I must disagree.  The typographic differences
among the following expressions

    foo: 10
    bletch:: "this is a test"
    somelongervariablename: foo + length? bletch
    shortername:: somelongervariablename + 5
        * (thing1: square-root 75) - (thing2:: now/time/second)
    lastone: shortername + 7

do *not* IMHO make the local vs. non-local names stand out
all that much.

>
> Best of
> all, this type of shortcut would not break anything in
> rebol. You could even use this in a loop:
> 
> for count 1 10 1 [
>   localvar:: "hello"
> ]
> 

Based on this example, I assume you *must* mean (1b) is the
context you want, but I'm still unclear what the answer to
(2) would be.

I'm also not clear on what semantics you intend e.g. for the
following case

    myfunc1: func [s [string!]] [
        a:: 1
        foreach char s [
            a:: a + 1
            if all [#"A" <= char   char <= #"Z"] [
                a: a + 1
            ]
            if all [#"a" <= char   char <= #"z"] [
                a:: a + 1
            ]
            if all [#"0" <= char   char <= #"9"] [
                a: a + 1
            ]
        ]
        a
    ]

>
> Using the "::" shortcut in a global context would be
> the same as using a ":".
> 

So "::" behaves differently depending on "context" (I
assume you mean lexical setting, not REBOL "context"...)
and on which time it is being evaluated???

How does it know?  (See below.)

That's not the same as defining e.g.

    print flarp:: square-root length? "Yowp!"

as meaning the same as

    use [flarp] [
        print flarp: square-root length? "Yowp!"
    ]


Remember that LOADing an expression implicitly wraps it in
a block.  All of the answers to (2) above have to do with
the idea of the lexically-encl0sing block.

Being able to create, use, and discard "temporary" variables
at the global level is quite handy!

>
> The disadvantage I see is that it adds another thing
> to the language.. But consider that now we could stop
> using the /local keyword, reduce bugs, and use it
> consistently everywhere, overall it can simplify
> things.
> 

But it's *NOT* consistent, IMHO!  In the example you give

    for count 1 10 1 [
        localvar:: "hello"
    ]

the double-colon-word LOCALVAR does something different the
first time it is evaluated compared to the subsequent time(s)
it is evaluated, although I'm not at all clear what that
"something" is.

You also seem to be saying that it must be able to figure out
(dynamically, remember!) which of an arbitrarily large number
of possible contexts should be affected.  Remember that REBOL
has no idea of "current context" so in the case (combining your
examples) of

    func1: func [n [integer!]] [
        func2: func [] [
            for count 1 n 1 [
                localvar:: count * count
            ]
        ]
    ]

I must again wonder what context LOCALVAR belongs in, and
how the reader (interpreter or human!) should figure that out,
whereas in current REBOL there are four distinct cases, each
of which is clear from the text of the expressions:

    ;; localvar belongs in the context of func1

    func1: func [n [integer!]/local localvar] [
        func2: func [] [
            for count 1 n 1 [
                localvar: count * count
            ]
        ]
    ]

    ;; localvar belongs in the context of func2

    func1: func [n [integer!]] [
        func2: func [/local localvar] [
            for count 1 n 1 [
                localvar: count * count
            ]
        ]
    ]

    ;; localvar belongs in a context inside the FOR body

    func1: func [n [integer!]] [
        func2: func [] [
            for count 1 n 1 [
                use [localvar] [
                    localvar: count * count
                ]
            ]
        ]
    ]

    ;; localvar belongs in some other context established
    ;; outside this text fragment

    func1: func [n [integer!]] [
        func2: func [] [
            for count 1 n 1 [
                localvar: count * count
            ]
        ]
    ]

Because of the way REBOL views words and contexts, I have
real trouble figuring out the interactions of this proposed
new feature with all of the mechanisms already in the
language.  There are already enough cases where there are
subtle differences and undocumented behaviors that I really
can't feel good about adding another one.

Finally, in a design situation I always like to ask "What
problem are we trying to solve?"  In this case it appears
that the primary problem is the risk of modifying the
global context by forgetting to declare a word as local
to some scope under construction.

If that's the case, I'd like to suggest an alternative.


If I understand correctly, REBOL builds contexts as required
by the expressions being evaluated (e.g., FUNC, USE, FOR,
MAKE OBJECT!, etc.) and refuses to extend those contexts
after initial creation -- with one specific exception being
the global context, which may be extended at any time.

What if REBOL had a new word, e.g. GLOBAL-CONTEXT-FROZEN (and
I'm quite happy for suggestions for a better name!), that
controlled whether adding new words to the global context were
prohibited?  Then we could write things like this:

    global-context-frozen: true
    do %somescript.r
    global-context-frozen: false

and any attempt to add a word to the global context during
the evaluation of the script file would cause an error.  In
addition, one could "nest" such protection e.g. within a 
script file such as somescript.r by writing:

    use [temp-global-safe] [
        temp-global-safe: global-context-frozen
        global-context-frozen: true
        ;; do a bunch of stuff
        ;; ...
        global-context-frozen: temp-global-safe
    ]

thus transparently ensuring that the "bunch of stuff" is
evaluated without adding globals, and then restoring the
level of safety that was in place when the above fragment
began.

(Of course, I'm avoiding the issue of whether we would get
benefit from being able to "thaw" other contexts, e.g. to
be able to add attributes to an existing object...  ;-)

-jn-

-- 
; Joel Neely                             joeldotneelyatfedexdotcom
REBOL [] do [ do func [s] [ foreach [a b] s [prin b] ] sort/skip
do function [s] [t] [ t: "" foreach [a b] s [repend t [b a]] t ] {
| e s m!zauafBpcvekexEohthjJakwLrngohOqrlryRnsctdtiub} 2 ]
-- 
To unsubscribe from this list, please send an email to
[EMAIL PROTECTED] with "unsubscribe" in the 
subject, without the quotes.

Reply via email to