Hi Ladislav, 
At 06:32 PM 11/26/99 +0100, you wrote:
>    Hi, Rebols! tried this: trial: func [par] [     do func [/local p] [   
>     p: par         make object! [             prt: func  [] [print p]     
>       ]         ]     ] trial2: func [par /local p] [     p: par     make
>object! [         prt: func [] [print p]         ]     ] with the following
>results:    >> a: trial 1 >> a/prt 1 >> b: trial 2 >> b/prt 2 >> a/prt 1 >>
>c: trial2 1 >> c/prt 1 >> d: trial2 2 >> d/prt 2 >> c/prt 2 >>    Isn't it
>a little bit strange?   Ladislav 

I must say, I had trouble reading your message. Had to reformat it. Is
something wrong with your email software?

To answer your question, the reason is the way func is implemented:

func: func [
    "Defines a user function with given spec and body." [catch]
    spec [block!] {Help string (opt) followed by arg words (and opt type
and string)}
    body [block!] "The body block of the function"
][
    throw-on-error [make function! spec body]
]

In your trial1 function, 'p is local to the embedded function. Therefore it
is fed as part of spec to make function! each time trail1 is called and a
new 'p is created. 

In contrast, in your trial2 'p is local to the surrounding function, to
trial2 itself. It is not local to the embedded function. Therefore it is
part of spec only once, namely the one time func is evaluated when trial2
is assigned as a reference to the function. This means that in trial2 each
time you print p, p points a the same memory location, in trial1 'p is
allocated new memory each time trail1 is called.

Here is a more detailed, albeit simplified explanation:

You can simplify your examples, using the following functions f and g,
which makes what is happening more obvious:

f: func [par] [
  do func [/local p] [
    p: par
    return 'p
  ]
]

g: func [par /local p] [
  do func [] [
    p: par
    return 'p
  ]
]


>> a: f 1
>> b: f 2
>> get a
== 1

Here the 'p referenced by 'a remains unchanged, even though we called f
with a different argument.

>> c: g 1
>> d: g 2
>> get c
== 2

Here the 'p referenced by 'c changes, when g is called with a different
argument. 

The reason is the positioning of the local statement. In f p is local to
the function embedded in f. In g 'p is local to the function g itself. 

Now, functions are just simply blocks of data until they are evaluated as
part of an expression. Once they have been evaluated, they return to the
blissful state of being nothing but data.

What this means for f is that p - which is local to the function *embedded
in f*, becomes a local word only for the a short moment, namely when do
forces the evaluation of the expression func [/local p] [p: par ...].

This means that the transition from being an unbound symbol to becoming a
word that is /local to the embedded function occurs for 'p each time f is
invoked. Transition means that everything necessary to create a local word
is repeated each time f is called, including the allocation of memory to
hold the value of 'p. 

Compare the source for func:

func: func [
    "Defines a user function with given spec and body." [catch]
    spec [block!] {Help string (opt) followed by arg words (and opt type
and string)}
    body [block!] "The body block of the function"
][
    throw-on-error [make function! spec body]
]


=====>   make function! spec body 
is called each time do func is evaluated and the result in each case is a
new function based on the same spec. It behaves as though you would have said:

f-1: make function [par /local p] [p: par return 'p]
f-2: make function [par /local p] [p: par return 'p]

a: f-1 1
b: f-2 2

It is obvious that is this case 'a's value would not be influenced by b's
value.

In contrast to f, in the function g 'p is local to the function 'g itself
NOT to the embedded function. Therefore when do is called to force the
evaluation of the embedded function, p is not created each time as a new
local word, with respect to  'p

======> make function! spec body 

is called only once, when the function is originally created. 

The local word 'p is only created once during the single evaluation of make
function! spec body, and therefore there only exists a single memory
location that is referenced by 'p. Accordinly, each time you assign a new
value to p, all words that reference that same memory location via the
literal 'p (which is being returned) will evaluate to that same value.

Hope This Helps,

Elan

Reply via email to