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

Object private member (was: objects: overhead, private data, naming

 [1/8] from: dockimbel:free at: 20-Sep-2001 15:20


Hi Christophe, CRS - Psy Sel/SPO, COUSSEMENT, Christophe, CPN wrote:
> Hi REBOLians: > About object private members, could anybody explain this to me:
<<quoted lines omitted: 7>>
> ] > </code>
[...]
> So... it looks like within an object, the use of 'set invoque a > privatization of the word, which is not any more visible from the outside.
No, you've defined '_b and 'get-b in the global context ! That's why o/_b and o/get-b return an error.
>>_b
== 10
>>get-b
10 Regards, DocKimbel.

 [2/8] from: joel::neely::fedex::com at: 20-Sep-2001 3:22


Hi, Christope, It's the other way 'round! CRS - Psy Sel/SPO, COUSSEMENT, Christophe, CPN wrote:
> Hi REBOLians: > > About object private members, could anybody explain this > to me: >
...
> So... it looks like within an object, the use of 'set > invoque a privatization of the word, which is not any more > visible from the outside. >
No. The use of SET affects the global context, rather than the context of the object you're constructing.
>> o: context [
[ _a: 5 [ set '_b 10 [ get-a: does [print-a] [ set 'print-a does [print _a] [ set 'get-b does [print _b] [ ]
>> get-b
10
> Great: I can use this property for making private members, > but this way of doing is still strange to me. >
Sorry. This can't be used to create private members.
> Any clue why a 'set-word! has two different ways of > handling things, within this context ? >
You'd have to get someone from RT (Holger? Comments, please?) to explain the original motivation, but there are some easy- to-notice consequences. Notice first that
>> source o
o: make object! [ _a: 5 get-a: func [][print-a] ] shows us that not everything done during the creation of an object ends up *in* the object. This allows us to do something like the following:
>> obj-count: 0
== 0
>> obj-spec: [x: 0 y: 0 set 'obj-count obj-count + 1]
== [x: 0 y: 0 set 'obj-count obj-count + 1] ;; now we can make a bunch of similar objects...
>> ob1: make object! obj-spec >> ob2: make object! obj-spec >> ob3: make object! obj-spec
;; ...and keep up with how many there are...
>> obj-count
== 3 ;; ...without any overhead within the individual objects!
>> source ob1
ob1: make object! [ x: 0 y: 0 ] The object specification is simply a block of REBOL that is evaluated in a special way; set-words in the object spec cause new words to be placed in the context under construction, but everything else just does whatever it does normally. You can take advantage of this fact in a variety of ways:
>> chatty-spec: [
[ print "Hi! I'm making another object" [ set 'obnr obnr + 1 [ selfnr: obnr [ print ["This new object is numbered" obnr] [ set 'temp now/time [ selfwhen: temp [ print ["and was created at" temp] [ print "I've finished now!" [ ] == [ print "Hi! I'm making another object" set 'obnr obnr + 1 selfnr: obnr print ["This new object is numbered"...
>> obnr: 0
== 0 (Notice that both OBNR and TEMP are globals, but only OBNR needs to be initialized.)
>> o1: make object! chatty-spec
Hi! I'm making another object This new object is numbered 1 and was created at 3:19:42 I've finished now!
>> o2: make object! chatty-spec
Hi! I'm making another object This new object is numbered 2 and was created at 3:19:50 I've finished now!
>> o3: make object! chatty-spec
Hi! I'm making another object This new object is numbered 3 and was created at 3:19:59 I've finished now!
>> source o1
o1: make object! [ selfnr: 1 selfwhen: 3:19:42 ] HTH! -jn- -- ------------------------------------------------------------ Programming languages: compact, powerful, simple ... Pick any two! joel'dot'neely'at'fedex'dot'com

 [3/8] from: coussement:c:js:mil:be at: 20-Sep-2001 15:57


Maarten & DocKimbel: Thanks for the fast answer ! I didn't know this ;-( Thanks to this ml and you guys, I feel I'm getting a little bit more clever every day :) Long life to REBOL! ==christophe

 [4/8] from: rotenca:telvia:it at: 20-Sep-2001 20:25


Hi, Joel
> No. The use of SET affects the global context, rather than > the context of the object you're constructing.
No. It affects the context to which the word is dinamically binded, in this example a Use block:
>> a: 1 use [a] [x: context [b: 2 set 'a 3] print a] print a
3 1 in the context in which 'set is called, "a" is binded to the use block, so 'set affect the use-binded 'a: In the next example 'set affect the 'a binded to the object 'x and do not change the global 'a or the use 'a:
>> a: 1
== 1
>> use [a] [a: 2 x: context [a: 3 set 'a 4 ] print ["Use:" a]]
Use: 2
>> print ["Global:" a "Object:" x/a]
Global: 1 Object: 4 To explain, lets take this simple example: context [a: 3] At the start Rebol creates a new context with the word 'a unset, while self points to the context:
>> context [print mold first get 'self a: 3]
[self a]
>> context [print [a] a: 3]
?unset?
>> context [print mold third self a: 3]
[a:] It is like if the code would be: context compose [a: (())] Now Rebol execute the block: [a: 3] and it finds: a: 3 and bind 'a to the Actual context: at that time, the Actual context says that the 'a is local to the object 'x, so x/a is set and becomes = 3. Which is the result we are waiting. Now get this example: context [a: 3 set 'a 4 ] After all the pass we have already seen we have: set 'a 4 Rebol binds 'a to the Actual context. In this case: 'set -> global 'a -> object then executes the code which changes the value of x/a not of global 'a. In this new example:
>> a: 1 context [set 'a 4 print a a: 3 print a] a
4 3 == 1 Rebol first unset x/a, then set it at 4 then set it at 3, while the global 'a remain unchanged. So, in the block the word argument of set is always bound to the object, only if the word is not defined in the object, the bind default to the external context of the object: context [set 'b 4 a: 3] ; b is global because 'b is NOT defined in the object use [b][context [set 'b 4 a: 3]] ; b is local at Use block because 'b is NOT defined in the object use [b][context [set 'b 4 b: 3]] ;b is local at object, because 'b IS defined in the object
> -jn-
----- ciao romano

 [5/8] from: coussement:c:js:mil:be at: 21-Sep-2001 11:05


Romano & Joel: Thanks guys ! This thread is becoming _very_ interesting ;-) It does me recall one about embedded objects a few months ago. Let's go back to the subject of the first post (from Gregg Irwin I think) ... If I have understand all it has been written - which I seriously doubt ;) - it should be possible to implement privacy in a way, using the property "use [b][context [set 'b 4 a: 3]]" where "b is local at Use block because 'b is NOT defined in the object" : <code> ;--- (using Gregg's naming convention:) use [_print-a _print-b _b][ ctx: context [ ;--> declare public members a: 5 get-a: does [_print-a] get-b: does [_print-b] ;--> declare private members set '_b 20 set '_print-a does [print a] set '_print-b does [print _b] ] ] </code> So, the private members should be only _visible_ from inside the context of the object... Let's test it:
>>; are the public members visible from the global
[ context, through the object definition ?
>> ctx/a
== 5
>>; are the public members visible from the global
[ context, and are the private members visible from [ inside the object ?
>> ctx/get-a
5
>> ctx/get-b
20
>>; YES => OK >>; are any members directly visible from the
[ global context ?
>> a
** Script Error: a has no value ** Near: a
>> _b
** Script Error: _b has no value ** Near: _b
>> _print-a
** Script Error: _print-a has no value ** Near: _print-a
>> _print-b
** Script Error: _print-b has no value ** Near: _print-b
>>; NO => OK >>; are the private members visible from the
[ global context, through the object definition ?
>> ctx/_b
** Script Error: Invalid path value: _b ** Near: ctx/_b
>> ctx/_print-a
** Script Error: Invalid path value: _print-a ** Near: ctx/_print-a
>> ctx/_print-b
** Script Error: Invalid path value: _print-b ** Near: ctx/_print-b
>>; NO => OK
Isn't it the effect we were trying to reach, or did I miss something ? ==christophe

 [6/8] from: rotenca:telvia:it at: 21-Sep-2001 14:55


> Romano & Joel: > Thanks guys ! This thread is becoming _very_ interesting ;-) It does me
<<quoted lines omitted: 6>>
> NOT defined in the object" : > Isn't it the effect we were trying to reach, or did I miss something ?
Yes, you are right. You can make it with Use, like in example or with context. Here _b _print-a _print-p are not lit-word, so are not defined in the object and their words are bound to the Use block, while ctx is global because is not declared in the use block. Remark 1. If you now make: ctx2: context ctx [] ctx and ctx2 share all the privates field ('_b _print-a _print-b) while public field ('a) is not the same. The private _b... are shared by all the objects wich use ctx model (or ctx2 model an so on). Remark 2. If you do: ctx2: context ctx [_b: 0] ctx2/get-b will access always the '_b local to the use block. Remark 3. It is possible write a routine which changes the value of use _b from the inner of the object: ;public set-b: func [value][_set-b :value] .... ;private set '_set-b func [value] [set/any '_b :value] Remark 4: it is possible to write generic routines for getting/removing private values: ;private set '_set-private func [word [word!] value] [set/any bind :word '_set-private :value] set '_get-private func [word [word!]] [get/any bind :word '_get-private] then they need public stub routines. Or write routines which return by default the private value or the public if declared. I think there are few limits and that should be a good idea to write a routine which create this type of contexts: make-object: func [public [block!] private [block!] routine [block!]] it should contrust the code and Use block on the fly and execute it. --- Ciao Romano

 [7/8] from: rotenca::telvia::it at: 21-Sep-2001 16:02

errata corr.


> Yes, you are right. You can make it with Use, like in example or with
context.
> Here _b _print-a _print-p are not lit-word, so are not defined in the object
^^^^^^^ set-word --------- ciao romano

 [8/8] from: greggirwin:starband at: 21-Sep-2001 10:13

Re: Object private member (was: objects: overhead, private data, naming


WOW!! Thanks for all your investigative efforts Christophe! So, it *is* possible. I think this is a very important idiom that we all need to remember. For building large systems, or components to be used by others, this is invaluable. Now, using what you've discovered, I need to find time to play around, learn about use, and see what happens when you start inspecting contexts reflectively. E.g. if you have an object browser, what will he be able to find out about an object. Thanks again! --Gregg

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