Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

Obscure? You be the judge!

 [1/20] from: joel:neely:fedex at: 13-May-2002 23:17


I don't have a good explanation for this bit of surprising behavior. All donations of wisdom gladly accepted. Here's a odd-looking little object: bug?: make object! [ width: 3 data: [1] plop: func [b [block!]] [append data b] child-proto: make object! [ label: "no such" dataref: data dump: func [] [print [label newline tab mold dataref]] reset: func [] [dataref: head dataref] ] children: make block! width repeat i width [ append children make child-proto [ label: join "Child-" i ] ] fizz: func [] [ foreach child children [ child/dump ] ] ] It contains a data store (called DATA surprisingly enough) and a block of subordinate objects that need to share access to DATA. Within each child object, DATAREF is supposed to refer to the same series as DATA. That way, after BUG?/PLOP is used to add entries to DATA, the DUMP routine of each child should show the additions. Let's try it:
>> bug?/fizz
Child-1 [1] Child-2 [1] Child-3 [1]
>> bug?/plop [3 5 7]
== [1 3 5 7]
>> bug?/fizz
Child-1 [1] Child-2 [1] Child-3 [1]
>>
Wozzattt?? It appears that each child's DATAREF has become a completely independent block!? Howesomever... If we add one line to the initialization of CHILDREN (inside the REPEAT about a dozen lines in) like so: bug?: make object! [ width: 3 data: [1] plop: func [b [block!]] [append data b] child-proto: make object! [ label: "no such" dataref: data dump: func [] [print [label newline tab mold dataref]] reset: func [] [dataref: head dataref] ] children: make block! width repeat i width [ append children make child-proto [ label: join "Child-" i dataref: data ;;; this line added ] ] fizz: func [] [ foreach child children [ child/dump ] ] ] ... we now get the expected behavior!
>> bug?/fizz
Child-1 [1] Child-2 [1] Child-3 [1]
>> bug?/plop [3 5 7]
== [1 3 5 7]
>> bug?/fizz
Child-1 [1 3 5 7] Child-2 [1 3 5 7] Child-3 [1 3 5 7]
>>
As tempted as I am to sing "Plop, plop, fizz, fizz, Oh what a relief it is!" I'm not feeling relieved. Why does the second version behave differently? Both are initializing DATAREF to DATA, just at different times, so I'm a bit puzzled. Do I need more coffee? -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 ]

 [2/20] from: joel::neely::fedex::com at: 13-May-2002 23:45

More on obscure behavior...


I'm sure everyone on this list will understand why the following change resolves the problem... bug?: make object! [ width: 3 data: [1] plop: func [b [block!]] [append data b] child-proto: make object! [ label: "no such" dataref: func [] [dataref: data] ;; changed line here dump: func [] [print [label newline tab mold dataref]] reset: func [] [dataref: head dataref] ] children: make block! width repeat i width [ append children make child-proto [ label: join "Child-" i ] ] fizz: func [] [ foreach child children [ child/dump ] ] ] ... but that doesn't bring me any closer to understanding why there's a problem to be resolved! -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 ]

 [3/20] from: nitsch-lists:netcologne at: 14-May-2002 11:52

Re: Obscure? You be the judge!


Hi Joel,
>> a: context [ b: [1]] >> c: make a[] >> d: make a[] >> same? a/b c/b
== false
>> same? c/b d/b
== false when you 'make an 'object!, all strings, blocks and functions are copied. that allows for example in 'layout : box with[append init[my-inits]] without destroying the original in box. also blocks, like functions, are rebound. so [make child-proto []] gives a copy of 'dataref, not the original. but objects are not copied, so the 'face/feel are all the same after [make face[]]. or in your case, do [ ex: func ["probe-tool" block] [print [">>" mold/only block "^/"] do block] bug?: make object! [ width: 2 data: context [block: [1]] ;;; object! plop: func [b [block!]] [append data/block b] child-proto: make object! [ label: "no such" dataref: data dump: func [] [print [label newline tab mold dataref]] reset: func [] [dataref/block: head dataref/block] ] children: make block! width repeat i width [ append children make child-proto [ label: join "Child-" i ] ] fizz: func [] [ foreach child children [ child/dump ] ] ] ex [bug?/fizz] ex [bug?/plop [3 5 7]] ex [bug?/fizz] ]
>> bug?/fizz
Child-1 make object! [ block: [1] ] Child-2 make object! [ block: [1] ]
>> bug?/plop [3 5 7] >> bug?/fizz
Child-1 make object! [ block: [1 3 5 7] ] Child-2 make object! [ block: [1 3 5 7] ] greetings -volker Am Dienstag, 14. Mai 2002 06:17 schrieb Joel Neely:

 [4/20] from: joel:neely:fedex at: 14-May-2002 7:57


Hi, Volker, Thanks for the explanations. As Larry Wall said: Just because something is obviously happening doesn't mean that something obvious is happening. ;-) However, I'm still left with a puzzled look on my face over one aspect of this... Volker Nitsch wrote:
> Hi Joel, > >> a: context [ b: [1]]
<<quoted lines omitted: 14>>
> so the 'face/feel are all the same after [make face[]]. > or in your case,
(Oh, by the way, did you find this documented anywhere, did you just figure it out for yourself, or is there another path to enlightenment? ;-) Thanks to your explanation, I have a more compact example... gub?: make object! [ data: [1] proto: make object! [ number: 0 dataref: data speak: func [] [print [number mold dataref]] ] things: [] append things make proto [number: 1] append things make proto [number: 2 dataref: data] tweak-n-speak: func [blk [block!]] [ insert data blk foreach thing things [thing/speak] ] ] ...which behaves as follows...
>> gub?/tweak-n-speak ["OK,"]
1 [1] 2 ["OK," 1] My remaining puzzlement is over this contrast: If I accept the description that (during the construction of GUB?/PROTO) GUB?/DATA is copied and GUB?/PROTO/DATAREF is set to refer to the copy, then that explains the behavior of GUB?/THING/1 . However, during the construction GUB?/THING/2 the additional spec block *also* refers to GUB?/DATA , but apparently the copy behavior does *not* occur (even though the referenced data value is still only a block). This makes me wonder if the issue here is a difference in the evaluation of the specblock parts of make object! [...specblock...] vs. make some-object [...specblock...] This is uncomfortably reminiscent of FORTH, in which one must have a complete operational model of the interpreter's internal state if one is to understand the behavior the more advanced (and hence more useful) aspects of the language. At least FORTH had both liberal documentation and available source to help with the construction/communication of such an operational mental model... -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 ]

 [5/20] from: cyphre:seznam:cz at: 14-May-2002 17:22


----- Original Message ----- From: "Volker Nitsch" <[nitsch-lists--netcologne--de]> To: <[rebol-list--rebol--com]> Sent: Tuesday, May 14, 2002 11:52 AM Subject: [REBOL] Re: Obscure? You be the judge! ............. when you 'make an 'object!, all strings, blocks and functions are copied. that allows for example in 'layout : box with[append init[my-inits]] without destroying the original in box. also blocks, like functions, are rebound. so [make child-proto []] gives a copy of 'dataref, not the original. but objects are not copied, so the 'face/feel are all the same after [make face[]]. .................. That's why lot of people are asking RT for adding something like 'clone or 'make/deep ;-) Or should it be a default Rebol's behaviour when working with objects? Regards, Cyphre

 [6/20] from: g:santilli:tiscalinet:it at: 14-May-2002 23:12


Hi Joel, On Tuesday, May 14, 2002, 6:17:17 AM, you wrote: JN> I don't have a good explanation for this bit of surprising behavior. I think I can help. :) MAKE copies (deep) and rebinds blocks and functions when cloning objects (so that methods work :). I think this is happening before the code block passed to MAKE is evaluated, so that your second version works as expected. JN> All donations of wisdom gladly accepted. Well, just my two euro cents. ;-) JN> Do I need more coffee? Nope, REBOL needs better docs. ;-) Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r

 [7/20] from: lmecir:mbox:vol:cz at: 15-May-2002 1:10


Hi Joel, <<From: "Joel Neely">> ... As Larry Wall said: Just because something is obviously happening doesn't mean that something obvious is happening. ;-) However, I'm still left with a puzzled look on my face over one aspect of this... ...
> when you 'make an 'object!, all strings, blocks and functions are > copied.
<<quoted lines omitted: 6>>
> so the 'face/feel are all the same after [make face[]]. > or in your case,
... (Oh, by the way, did you find this documented anywhere, did you just figure it out for yourself, or is there another path to enlightenment? ;-) <</Joel>> <<L>> I think, that he figured it out for himself... <</L>> <<Joel>> ... Thanks to your explanation, I have a more compact example... gub?: make object! [ data: [1] proto: make object! [ number: 0 dataref: data speak: func [] [print [number mold dataref]] ] things: [] append things make proto [number: 1] append things make proto [number: 2 dataref: data] tweak-n-speak: func [blk [block!]] [ insert data blk foreach thing things [thing/speak] ] ] ...which behaves as follows...
>> gub?/tweak-n-speak ["OK,"]
1 [1] 2 ["OK," 1] My remaining puzzlement is over this contrast: If I accept the description that (during the construction of GUB?/PROTO) GUB?/DATA is copied and GUB?/PROTO/DATAREF is set to refer to the copy, then that explains the behavior of GUB?/THING/1 . However, during the construction GUB?/THING/2 the additional spec block *also* refers to GUB?/DATA , but apparently the copy behavior does *not* occur (even though the referenced data value is still only a block). <</Joel>> <<L>> That "apparently" is incorrect. Here is a Rebol model of the MAKE PROTO behaviour: (testing appreciated) make-proto: function [ {MAKE PROTO simulation} proto [object!] spec [block!] ] [set-words object sw word value spc body] [ set-words: copy [] ; get local words from proto foreach word next first proto [ append set-words to set-word! word ] ; append all set-words from SPEC parse spec [ any [ copy sw set-word! (append set-words sw) | skip ] ] ; create a blank object with the desired local words object: blank-object set-words ; set 'self in object to refer to the object object/self: object ; copy the contents of the proto repeat i (length? first proto) - 1 [ word: pick next first proto i any-type? set/any 'value pick next second proto i any [ all [string? get/any 'value set in object word copy value] all [block? get/any 'value set in object word bind/copy value in object word] all [ function? get/any 'value spc: load mold third :value body: bind/copy second :value in object word set in object word func spc body ] any-type? set/any in object word get/any 'value ] ] ; bind the SPEC to the object bind spec in object 'self ; evaluate it spec-eval spec ; return the value of 'self as the result return get/any in object 'self ] <</L>>

 [8/20] from: nitsch-lists:netcologne at: 14-May-2002 21:37


Hi Joel, Am Dienstag, 14. Mai 2002 14:57 schrieb Joel Neely:
> Hi, Volker, > Thanks for the explanations. As Larry Wall said:
<<quoted lines omitted: 30>>
> just figure it out for yourself, or is there another path to > enlightenment? ;-)
Meditation, tea and trying everything out ;)
> Thanks to your explanation, I have a more compact example... > gub?: make object! [
<<quoted lines omitted: 30>>
> vs. > make some-object [...specblock...]
All pure sientific, no magic needed. before a spec-block is executed, it is parsed for set-words. only the contents of set-words are copied. here: append things make proto [number: 1] append things make proto [number: 2 dataref: data] you see there is no set-word for 'data, so it remains untouched. the copying happens before execution, so you get a copy append things make proto [number: 2 ? dataref dataref: data] but then overwrite it with the original append things make proto [ number: 2 ? dataref dataref: data ? dataref ] the trick used for "export" is based on that. context[ set 'something-outside "this will not be part of new context" ] 'something is no set-word, so it will not be included in the new context, so the outside word stays bound and goes modified.
> This is uncomfortably reminiscent of FORTH, in which one must > have a complete operational model of the interpreter's internal
<<quoted lines omitted: 3>>
> the construction/communication of such an operational mental > model...
no state and immediate words needed in rebol. I know this should be impossible :)
> -jn-
greetings -Volker

 [9/20] from: ammon:rcslv at: 13-May-2002 4:45


A short time ago, Joel Neely, sent an email stating:

 [10/20] from: nitsch-lists:netcologne at: 15-May-2002 1:27


Am Dienstag, 14. Mai 2002 17:22 schrieb Cyphre:
> ----- Original Message ----- > From: "Volker Nitsch" <[nitsch-lists--netcologne--de]>
<<quoted lines omitted: 13>>
> That's why lot of people are asking RT for adding something like 'clone or > 'make/deep ;-)
I know.
> Or should it be a default Rebol's behaviour when working with objects? >
Actually i like it the current way. ===cloning, complex structures In my experience with other languages cloning of complex structures gets pretty complicated and automatics are not very helpfull there. make/deep could manage one or two nesting steps maybe, with more something usually needs to be shared and the language needs constructs/conventions to control clone/sharing and the programmer has to be aware of it. well, cloning is a bit like the last sentence ;) Also Carl avoids it, so i expected my "trap"-view is right, and rebol has a better "native" way. Not necessary better as in 'good, but as in "you know, if you open this other box..". So for a while I started to chose between blocks/objects based on my sharing/cloning decisions. Just to see what happens. And oops, its handy! Now it is a good commodity. ===constants, cloning deep faces? Also if i know i modify an object, by default i make it. about rebol its one sentence if you want to modify it, its object!, its shared, so 'make it , other languages have nice keywords like 'constant. and then 'mutable somewhere inside because the constant is not so completely constant in a special case. works, but another piece to keep in mind. in c its a page of paper with some extra hints in specialized books to use the constant-concept correctly. (if you have a const pointer, is the pointed stuff const too or not?) So if i want to scroll text in a face, i look which object is affected, and use [area para[]]. (fortunally i discovered that somehow, because docs..) ==switching between blocks and objects a: context[b: 123] a/b: 234 probe a/b a: [b 123] a/b: 234 probe a/b are very similar. and scripts short enough to change the other places ;)
> Regards, > > Cyphre
greetings Volker

 [11/20] from: rotenca:telvia:it at: 15-May-2002 15:18


Hi Ladislav,
> make-proto: function [ > {MAKE PROTO simulation}
<<quoted lines omitted: 41>>
> return get/any in object 'self > ]
Some observations: 1) set-words should be unique, this is not a problem with your blank-object, but is a problem with your lfunc. 2) Because of return bug, it is better get/any in object 'self instead of return get/any in object 'self 3) I did not test your code, but it seems to me that it bind the body function to the new context. This is only half correct: binding is done in Rebol before adding the new set-words of spec to the new object: d: "global" a: context [b: does [print d]] a/b; == global a2: make a [d: "local to a2"] a2/b; == global As you can see, the d word in the func body is not binded to the a2 context. But: a: context [b: does [print d] d: "local to a"] a/b; == local to a a2: make a [d: "local to a2"] a2/b; == local to a2 I think that your code gives always the result of second example (but i did not tested it). 4) instead of parsing all the block, because the only oddity of make object is copy and binding the function bodies, one could use bind and copy deep and then finding and changing only the function values, but i did not try. 5) why this any-type? ? any-type? set/any 'value pick next second proto i --- Ciao Romano Paolo Tenca

 [12/20] from: joel:neely:fedex at: 15-May-2002 8:32


Hello, all, (I'm replying to self because several folks have made helpful comments during this thread. Thanks to all who've contributed!) I've done further experimenting to try to clarify the differences for myself. Perhaps they will be of help to someone else. My apologies for the length, but I'd appreciate comments on the coding convention at the end. -jn- Joel Neely wrote:
> Thanks to your explanation, I have a more compact example... >
Thanks to comments from Volker, Gabriele, and Ladislav, I have a more complete example, given below. I'm sure that all I've done here is re-discover/-state what was already said, but I'm a bit slow... ;-) gub?: make object! [ data: [1] proto: make object! [ number: 0 dataref: data speak: func [] [print [number mold dataref]] ] things: [] append things make proto [number: 1] append things make proto [number: 2 dataref: data] append things make proto [number: 3 dataref: proto/dataref] tweak-n-speak: func [blk [block!]] [ insert data blk proto/speak foreach thing things [thing/speak] ] ] By adding the line containing "PROTO/SPEAK" to the last function, I was able to get more photons from the filament!
>> gub?/tweak-n-speak ["what's" "different?"]
0 ["what's" "different?" 1] 1 [1] 2 ["what's" "different?" 1] 3 ["what's" "different?" 1] When GUB?/PROTO was made, its DATAREF was initialized to refer to GUB?/DATA as expected. When GUB?/PROTO/1 was made, it began life as a (deep) clone of GUB?/PROTO and then had its NUMBER set to 1. Its DATAREF now refers to a clone of the initial GUB?/DATA (via the reference in GUB?/PROTO/DATAREF). When GUB?/PROTO/2 was made, it began life as a (deep) clone of GUB?/PROTO and then had its NUMBER set to 2, *and* its DATAREF (re-)set to refer to the same series as GUB?/DATA (explicitly, via the GUB?/DATA reference). When GUB?/PROTO/3 was made, it began life as a (deep) clone of GUB?/PROTO and then had its NUMBER set to 3, *and* its DATAREF (re-)set to refer to the same series as GUB?/DATA (explicitly, via the GUB?/PROTO/DATAREF reference). At that point the references in GUB?/DATA and GUB?/PROTO/DATAREF and GUB?/THINGS/2/DATAREF and GUB?/THINGS/3/DATAREF are all equivalent, while the reference in GUB?/THINGS/1/DATAREF refers to a distinct block (originally cloned via GUB?/PROTO/DATAREF). Normal shared-block-reference behavior ensues *after* this point. KEY LESSON: When using an existing object as a prototype, the default behavior is to copy referenced *values*, and special effort must be taken to *suppress* the copying, in contrast to other REBOL handling of reference data, where the default behavior is to copy *references* and special effort must be taken to *cause* copying. For example, every REBOL programmer eventually learns that: palindrome: func [b [block!] /local result] [ result: [] append result b append result head reverse b result ] will (probably) surprise him/her *twice*, as in:
>> foo: [1 3 5 7]
== [1 3 5 7]
>> baz: palindrome foo
== [1 3 5 7 7 5 3 1]
>> foo
== [7 5 3 1]
>> bletch: palindrome [2 4 6]
== [1 3 5 7 7 5 3 1 2 4 6 6 4 2] and therefore should (probably) be written more like: safe-palindrome: func [b [block!] /local result] [ result: copy [] append result b append result head reverse copy b result ] (Yes, I know this dinky example can be written *much* better; please don't miss the point and try to optimize this specimen of noncopy-vs-noncopy behavior. If I had rewritten it as safe-and-short-palindrome: func [b [block!]] [ join b head reverse copy b ] the point regarding copying would have been harder to see.) In contrast to the you-must-ask-for-copying-if-you-want-it general rule, when creating objects from a prototype object that is intended to contain reference(s) to shared block(s), REBOL requires that we take special action to *avoid* the default copying behavior. It seems to me that the clearest way to do this is likely something similar to what I did above with the third anonymous object in GUB?/THINGS where the prototype contains: proto: make object! [ number: 0 dataref: data ;;... ] and the construction-from-prototype pattern of make proto [ number: 3 dataref: proto/dataref ] explicitly calls the reader's attention to the fact that the DATAREF attribute of the new object is intended to share reference with the corresponsing attribute of the prototype. (In passing, it's interesting that NUMBER must be initialized explicitly to get a different value from the prototype, but DATAREF must be initialized explicitly to get the same value as the protype.) I'm leaning toward writing dataref: proto/dataref instead of dataref: data in the construction-from-prototype expression to make it clear that the *current* value of the prototype's attribute should be the basis of the shared reference. For example... some-proto: make object! [ block-ref: some-global-block ;;... ] other-proto: make first-proto [ block-ref: other-global-block ;;... ] leaves a situation in which some-instance: make some-proto [ block-ref: some-proto/block-ref ;;... ] other-instance: make other-proto [ block-ref: other-proto/block-ref ;;... ] is more likely correct (and obvious to the reader) than some-instance: make some-proto [ block-ref: some-global-block ;;... ] other-instance: make other-proto [ block-ref: some-global-block ;;... ] Thoughts? -- ; 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 ]

 [13/20] from: greggirwin:mindspring at: 15-May-2002 12:34


Hi Joel, I like the convention you put forth. I'm learning a lot from this thread. This is behavior worth documenting in Core.pdf. --Gregg

 [14/20] from: lmecir:mbox:vol:cz at: 15-May-2002 21:34


Hi Romano, <<Romano>> ... Some observations: 1) set-words should be unique, this is not a problem with your blank-object, but is a problem with your lfunc. <</Romano>> <<L>> Yes, I know that LFUNC isn't able to handle the cases, in which duplicities occur. I should repair it... I wonder, how many users does the function have? OTOH, it is unnecessary to complicate the above code (IMHO)... <</L>> <<Romano>> 2) Because of return bug, it is better get/any in object 'self instead of return get/any in object 'self <</Romano>> <<L>> The native MAKE PROTO can return even error values. I cannot simulate that without RETURN... <</L>> <<Romano>> 3) I did not test your code, but it seems to me that it bind the body function to the new context. This is only half correct: binding is done in Rebol before adding the new set-words of spec to the new object: d: "global" a: context [b: does [print d]] a/b; == global a2: make a [d: "local to a2"] a2/b; == global As you can see, the d word in the func body is not binded to the a2 context. But: a: context [b: does [print d] d: "local to a"] a/b; == local to a a2: make a [d: "local to a2"] a2/b; == local to a2 <</Romano>> <<L>> Thanks for your analysis. This behaviour is really complicated. (I wonder what will Joel say to this?) d: "global" a: context [b: [d]] get first a/b; == global a2: make a [d: "local to a2"] get first a2/b; == global a: context [b: [d] d: "local to a"] get first a/b; == local to a a2: make a [d: "local to a2"] get first a2/b; == local to a2 (uff) I need to define a special binding function that binds only partially, I didn't find any other way how to simulate it? <</L>> <<Romano>> 4) instead of parsing all the block, because the only oddity of make object is copy and binding the function bodies, one could use bind and copy deep and then finding and changing only the function values, but i did not try. <</Romano>> <<L>> neither did I... <</L>> <<Romano>> 5) why this any-type? ? any-type? set/any 'value pick next second proto i --- Ciao Romano Paolo Tenca <</Romano>> <<L>> It could be any type value (e.g. error). Ciao Ladislav

 [15/20] from: rotenca:telvia:it at: 16-May-2002 14:25


Hi, Ladislav
> The native MAKE PROTO can return even error values. I cannot simulate that > without RETURN...
...
> It could be any type value (e.g. error).
I always forget error return (i do not like it).
> Thanks for your analysis.
Thank you for your emulation which made me think to the problem.
> This behaviour is really complicated.
It is hard to emulate, but it seems to me simpler to understand: 1) object is cloned as is (with func block copied) 2) new setword coming from spec added to the object context (this should mean that Rebol is internally already able to add new words to an existing context beyond global context) 3) spec block is bound to the expanded context 4) spec block is evaluated and object/self returned
> Ciao > Ladislav
--- Ciao Romano

 [16/20] from: nitsch-lists:netcologne at: 17-May-2002 21:49


Am Freitag, 17. Mai 2002 13:58 schrieb Gabriele Santilli:
> Hi Romano, > > On Thursday, May 16, 2002, 2:25:41 PM, you wrote: > > RPT> 2) new setword coming from spec added to the object context > RPT> (this should mean that Rebol is internally already able to add new > words RPT> to an existing context beyond global context) > > This raises an interesting point. Holger? >
Well, make knows the numbers of words to allocate. i think one problem with general ability is, one can not move context in memory without confusing all references currently? maybe make/keep-free object! [] 15 , keeping free 15 words to add, but..
> Regards, > Gabriele.
greetings Volker

 [17/20] from: g:santilli:tiscalinet:it at: 18-May-2002 11:41


Hi Volker, On Friday, May 17, 2002, 9:49:04 PM, you wrote: VN> Well, make knows the numbers of words to allocate. But then, why binding before actually adding the new words? VN> i think one problem with general ability is, one can not move context in VN> memory without confusing all references currently? That can be easily solvable, by having the words and values referenced by the context! and the words referencing the context! itself (maybe with an index to the position in words/values). I think it is very likely to work this way already... (Remember that before 2.2 you could modify the block of words or the block of values independently...) Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r

 [18/20] from: joel:neely:fedex at: 18-May-2002 10:34


Hi, Ladislav, Ladislav Mecir wrote:
> <<Romano>> > 3) I did not test your code, but it seems to me that it bind the
<<quoted lines omitted: 17>>
> Thanks for your analysis. This behaviour is really complicated. > (I wonder what will Joel say to this?)
He didn't say anything. He just ran from the room screaming incoherently!!! ;-) Seriously, I wasn't nearly as surprised by this example as I have been by some other "interesting" examples. Since encountering REBOL I have been on a (non-terminating ;-) quest to find the simplest possible model/principles from which to understand and describe the behavior of the language. For example, once one understands the way REBOL uses the concepts of "word" and "context" it is follows very logically that in the following: a: make object! [ p: 42 q: "Howzabout them apples?" r: func [] [ pick q (length? q) // p + 1 ] ] b: make a [ p: 7 q: "I have nothing to say and I am saying it." ] each of A and B must have its own copy of R with no code-sharing. Similarly, the non-intuitive behavior of Romano's example above can be explained fairly simply in terms of the "definition-time binding" rule and the way MAKE OBJECT! treats top-level set-words in the spec block.
>From my mathematical background, I don't see a contradiction in
simultaneously seeing something as "non-intuitive" and "simple" because that background has taught me that intuition is trained by experience. Something outside our everyday experience is likely to be non-intuitive/surprising more from our unfamiliarity with it than from its inherent complexity. Given the fact that different people have different styles of thinking and learning, I conclude that the best way to teach something unfamiliar is to use a combination of *both*: * axiom-like basic principles from which the behavior of the new thing can be deduced (for obsessively top-down, deductive thinkers like me), and * cumulative experience, beginning with simple examples and leading up to the more out-of-the-ordinary cases (for the folks at the other end of the thinking-style spectrum who are more bottom-up and inductive). I'd love to write such an introduction to REBOL one of these days, but feel compelled to learn it better myself before doing so. I also would like to feel a high level of confidence in the stability of the core language concepts. The upcoming dosage of Valium to be adminstered to word evaluation would certainly have made some of my previous models and descriptions inaccurate! ;-) -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 ]

 [19/20] from: g:santilli:tiscalinet:it at: 17-May-2002 13:58


Hi Romano, On Thursday, May 16, 2002, 2:25:41 PM, you wrote: RPT> 2) new setword coming from spec added to the object context RPT> (this should mean that Rebol is internally already able to add new words RPT> to an existing context beyond global context) This raises an interesting point. Holger? Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r

 [20/20] from: nitsch-lists:netcologne at: 18-May-2002 20:02


Am Samstag, 18. Mai 2002 11:41 schrieb Gabriele Santilli:
> Hi Volker, > > On Friday, May 17, 2002, 9:49:04 PM, you wrote: > > VN> Well, make knows the numbers of words to allocate. > > But then, why binding before actually adding the new words?
semantics? lets say:
>> ctx: context[print-me: does[print ["iam" mold self]]] >> ctx2: make ctx[mold: "oops"] >> ctx2/print-me
iam make object! [ print-me: func [][print ["iam" mold self]] mold: "oops" ] this way one can create an object with basic functions, like 'print-me. Its obvious not to redefine them. but it is obvious too not to redefine 'mold?
> VN> i think one problem with general ability is, one can not move context > in VN> memory without confusing all references currently?
<<quoted lines omitted: 4>>
> before 2.2 you could modify the block of words or the block of > values independently...)
Well, IIRC i started around 2.2 .. AFAIK they blocked that because adding words crashed the interpreter? can imagine insert sees a block, thinks "ok, i resize", bang? Or was it asymetric resizing (adding a word, bot not a value)? Hmm, one could try to optimize by storing like 3 word word word value value value where 3 is the offset words/1 -> values/1 . that would save some pointer-lookups. Carl has some tricks in this area. Remember exec-list-headers :) but its trying to look behind the curtain.. ;)
> Regards, > Gabriele.
greetings Volker

Notes
  • Quoted lines have been omitted from some messages.
    View the message alone to see the lines that have been omitted