Home   Archive   Permalink



encapsulation of variables in object behaving weirdly

I was playing with objects in rebol and I found some weird encapsulation behaviour. the example I am using is a follows:-
    
----------------------------------------
R E B O L [ ]
    
m: make object! [
     mm: layout [ o: field button [print o/text]
]
    
n: make object! [
     nn: layout [ o: field button [print o/text]
]
    
view m/mm
------------------------------------------
    
when I type something in the field o and press button , I doesn't give me what I typed in. it's blank.
    
it looks like the field o in object n is interfering with the field o in object m .
    
is there a problem with the encapsulation ?
    
should rebol not be able to differentiate between the O in object m and the O in object n ?
    
can someone let me understand what is happening ?
    
thanks

posted by:   yuem       11-Nov-2010/17:12:01-8:00



I missed a ] in the previous post, this is the actual code I used
    
R E B O L [ ]
        
m: make object! [
     mm: layout [ o: field button [print o/text] ]
]
        
n: make object! [
     nn: layout [ o: field button [print o/text] ]
]
        
view m/mm

posted by:   yuem       11-Nov-2010/17:14:42-8:00



try this
    
    
n: make object! [
     o: none
     nn: layout [ o: field button [print o/text] ]
]
    

posted by:   Graham       11-Nov-2010/22:40:11-8:00



In layout dialect objects are not local.
As Graham shows, you need to make them local first.
    
Look at this example:
o: Context [f: func [] [p: 5]]
o/f
P is 5 outside of object O.
    
But if you do as below:
o: context [p: none f: does [p: 5]]
o/f ;will set p in O


posted by:   Endo       12-Nov-2010/16:13:17-8:00



thanks Graham/Endo.
    
however this is inconsistent with what rebol core documentation says.
    
http://www.rebol.com/docs/core23/rebolcore-10.html#section-8
    
" The solution to this problem of global variables is to wrap an object around both the variables and the function. When that is done, the function can still access the variables, but the variables cannot be accessed globally."
    
as quoted above, the official documentation states that any variable in a function found in an object cannot be accessed globally. so I am not sure why the o in my example is global. seems more like a bug to me.
    
all these small nagging things, that I have brought up in forums here at rebolforum.com and at graham's blog www.synapse-ehr.com , are very frustrating.
    
Rebol would gain a lot by being more consistent as a language and should adopt the "principle of least surprise."


posted by:   yuem       13-Nov-2010/15:09-8:00



Yuem, unfortunately you are wrong. There is no inconsistency in th manual.
    
Objects, functions and functions in objects change variables in global scope, if they are not in specifically local to the function or object.
    
That section is about something else: there is an object named Bank and it sets (creates) a function in global scope which uses a local variable. (make-account)
    
Look at that line:
last-account: last-account + 1
last-account is a local variable but make-account is not local to bank object. You can call it without bank/make-account notation.
    
And note that last-account is already set in the object definition to make it local otherwise it will be global.
    
Briefly, you need to define variables when creating object to make them local to the object. And you need to use /local refinement for functions.

posted by:   Endo       13-Nov-2010/16:14:53-8:00



enddo, thanks for the explanations.
    
however I am not sure if I read it the same way.
in the example I provided, I am declaring/defining    
my variable o: field inside
the layout function which is itself inside the object m
so I expect the object o to belong to the object m.
    
m: make object! [
     mm: layout [ o: field button [print o/text] ]
]
    
    
the same applies to the O in the object n. it is defined/declared
inside the layout function which is itself encapsulated in object n.
n: make object! [
     nn: layout [ o: field button [print o/text]
]
    
    
I have another example where even if I declare the variable right
on the first line of the make object! block, rebol
seems to have some difficulty to figure out what object the
variable belongs to. I will look for that example and post it
here later.
    
    
I would have liked to ask that question on altme. unfortunately
I am not on alt me ( for reasons I had posted on synapse-ehr.com)
    


posted by:   yuem       14-Nov-2010/13:07:19-8:00



enddo, thanks for the explanations.
    
however I am not sure if I read it the same way.
in the example I provided, I am declaring/defining    
my variable o: field inside
the layout function which is itself inside the object m
so I expect the object o to belong to the object m.
    
m: make object! [
     mm: layout [ o: field button [print o/text] ]
]
    
    
the same applies to the O in the object n. it is defined/declared
inside the layout function which is itself encapsulated in object n.
n: make object! [
     nn: layout [ o: field button [print o/text]
]
    
    
I have another example where even if I declare the variable right
on the first line of the make object! block, rebol
seems to have some difficulty to figure out what object the
variable belongs to. I will look for that example and post it
here later.
    
    
I would have liked to ask that question on altme. unfortunately
I am not on alt me ( for reasons I had posted on synapse-ehr.com)
    


posted by:   yuem       14-Nov-2010/13:08:41-8:00



The LAYOUT function is spoiling your expectations, because it reads the set-word O from your block into a word VAR, which then is used like this in a line of code in LAYOUT:
    
if :var [set :var new var: none]
    
Where NEW is the face that is currently being processed. VAR contains the word that will be set with the face name, in your case O.
    
This follows the rule that when using SET on a word, it will automatically be either global or restricted to the context in which SET is used, if the word is already set there.
    
The context cannot control the words that are set by a function (here LAYOUT), unless you know which ones to restrict.
    
Hence, Graham's solution is correct.

posted by:   Henrik       14-Nov-2010/14:20:26-8:00



thanks Henrik for your explanations,
    
here is another example where I declare the variable outside of the layout function.
you will see that there is a problem with focus on variable m_f1.
    
rebol is focusing only on the m_f1 field in editobject , but it does not focus on m_f1 in the addobject.
    
there is interference between the 2 objects.
    
    
    
R E B O L [ ]
    
;-- Capture screen -----------------------------------------------------------------------
    
addObject: make object! [
        
    m_f1: m_f2: none
    
    stylCapture: stylize [
            flda: field " " 140x20    
            txt1: txt 100x20 left blue
            but_a: button 150x25 120.0.20
            
    ]
    
    m_capturePanel: layout [
        styles stylCapture
        h1 "Capture screen"
        across     Txt1 "field1" m_f1: flda below
        across Txt1 "field2" m_f2: flda below
        across     but_a "Save" [     ]
    ]
    
    
    focus m_f1
]
    
    
;-- edit screen ------------------------------------------
    
editObject: make object! [
    
    m_f1: m_f2: none
    
    stylCapture: stylize [
            flda: field " " 140x20    
            txt1: txt 100x20 left blue
            but_a: button 150x25 120.0.20
            
    ]
    
    m_editPanel: layout [
        styles stylCapture
        h1 "edit screen"
        across     Txt1 "field1" m_f1: flda below
        across Txt1 "field2" m_f2: flda below
        across     but_a "Save" [     ]
    ]
    
    
    
    focus m_f1
    
]
    
    
;---------------------------------------------------------
    
    
    
    
    
    
view center-face addobject/m_capturepanel
    
    
view editobject/m_editpanel


posted by:   yuem       15-Nov-2010/8:50:25-8:00



No! This is a completely different problem.
You are calling focus m_f1 during the object creation. So your m_f1 field gets focus just for the first time.
    
You need to set focus just before to View your layout. Try this:
focus addobject/m_f1
view center-face addobject/m_capturepanel
    
focus editObject/m_f1
view editobject/m_editpanel
    
This will work as expected with no variable interference.
    
Briefly, you cannot say, in this object focus should be on this field and in the second object focus will be on that field. Focus can only be on one gui item at a time.

posted by:   Endo       15-Nov-2010/9:44:53-8:00



Or put a function in each object to show itself correctly:
    
editObject: make object! [
     m_f1: m_f2: none
     stylCapture: stylize [
         flda: field " " 140x20
         txt1: txt 100x20 left blue
         but_a: button 150x25 120.0.20
     ]
     m_editPanel: layout [
         styles stylCapture
         h1 "edit screen"
         across     Txt1 "field1" m_f1: flda below
         across Txt1 "field2" m_f2: flda below
         across     but_a "Save" [     ]
     ]
     show: does [
         focus m_f1
         view m_editpanel
     ]
]
    
editObject/show


posted by:   Endo       15-Nov-2010/9:53:27-8:00



thanks Enddo for the advice. haven't checked this site since my last post.
    
yes if I group both objects in the one .r file, then I have to use a function for the show.
    
whas I have done is put the objects in separate .r file and then do either one when it is needed.
    
I had some problem because I am used to the java way , where if I have two separate screen classes in one .java file, you could .setFocus to multiple fields in different screen classes even if they are in the same .java file. similar to the approach i was using in my example.
    


posted by:   yuem       27-Nov-2010/14:38:19-8:00