[REBOL] Re: blocks in and out function !
From: joel::neely::fedex::com at: 8-Jan-2002 13:42
Hi, Olivier,
Welcome to REBOL! You've encountered the First Koan of REBOL!
Olivier Flauzac wrote:
> Hi !
>
> I'm try to developpe some rebol code, and I have a little problem :
>
> When I do the following code in the rebol console, everything is OK
> the last append instruction append 4 to the empty block following 1
> -----------------------------------------------
> gr: []
> == []
> >> append gr 1
> == [1]
> >> append/only gr []
> == [1 []]
> >> append gr 2
> == [1 [] 2]
> >> append/only gr []
> == [1 [] 2 []]
> >> append select gr 1 4
> == [4]
> >> :gr
> == [1 [4] 2 []]
> -------------------------------------------------
>
> now if I write the following functions I obtain a totally different
> result : 4 is append to all empty blocks !!
>
> ---------------------------------------------------
> >> addNode: make function! [g n][
> [ append g n
> [ append/only g []
> [ ]
> >> addLink: make function![g n v][
> [ append select g n v
> [ ]
> >> gr: []
> == []
> >> addNode gr 1
> == [1 []]
> >> addNode gr 2
> == [1 [] 2 []]
> >> addLink gr 1 4
> == [4]
> >> :gr
> == [1 [4] 2 [4]]
> -----------------------------------------
>
> I solved that problem by replacing the line "append/only g []" by
> "append/only g make block! []". With that modification It works !
>
> Could anyone give me an explaination ? Why the second code
> do not behave like the first one ?
>
The short answer is that [] inside a function does not translate
into a request for an empty block to be created, but rather *IS*
a block which is initialized as empty when the function is defined.
Subsequent modifications to the block are retained, because REBOL
does not make a distinction between code and data.
A longer answer, by way of analogy, considers the following:
>> myword: "?" == "?"
>> thing: [myword: []] == [myword: []]
>> do thing == []
>> append myword "What?" == ["What?"]
>> thing == [myword: ["What?"]]
The second line above sets THING to a "literal" block which contains
two values, a SET-WORD! value and a BLOCK! value (initially empty,
by the way).
The third line evaluates the block referred to by THING. As a
result, MYWORD now refers to the second element of THING.
The fourth line appends something to the block referred to by MYWORD.
Since this *IS* the second element of THING, the fifth line shows
that both references to that block (through MYWORD and through the
second element of THING) both "see" the change.
If you're at all familiar with LISP, I can say simply that REBOL
defaults to structure sharing.
HTH!
-jn-