Home   Archive   Permalink



How to get object context from outer function

How do I get the object context from a function which is outside of the object but called inside from the object.
    
here is my situation:
    
R E B O L []
    
o: context [a: "ooo" x: :f]
p: context [a: "ooo" y: :f]
    
same? get in o 'x get in p 'y
>> true ;o/x and p/y points to same function
    
I tried the followings for f
    
f: func [] [print a]
f: func [] [print get in self 'a]
    
o/x
>> error a has no value (for the first one)
>> error self has no value (for the second one)
    
Of course I can put a function into objects which calls the function f with parameter self;
    
f: func [obj] [print get in obj 'a]
o: context [a: "ooo" x: does [f self]]
p: context [a: "ppp" y: does [f self]]
    
o/x
>> ooo
p/y
>> ppp
    
which is the correct result, but actually o/x and p/y is NOT the same function anymore. And they are defined in each object (waste of memory)
    
Is there any solution?

posted by:   Endo       19-May-2010/18:19:17-7:00



Will something like this work for you?
    
>> f: func [obj] [print obj/a]
>> _o: context [a: none x: y: does [f self]]
>> o: make _o [a: "ooo"]
>> p: make _o [a: "ppp"]
>> o/x
ooo
>> p/y
ppp

posted by:   Gregg Irwin       20-May-2010/0:54:02-7:00



Not exactly, because when you do this there are two different functions in memory, one for o and one for p.
same? get in o 'x get in p 'x
>> false
    
if I changed one of these functions, the other one will not be changed. Because it does the same job but not the same function.
    
append second fourth third _o [print "x"]
    
probe _o
make object! [
     a: none
     x: func [][f self print "x"] ;<--
     ...
    
probe o
make object! [
     a: "ooo"
     x: func [][f self] ;<--
     ....
    
they don't point to same memory location. If I created 100 objects, then there will be 100 different functions.

posted by:   Endo       20-May-2010/3:00:58-7:00



If you want to share "code" between objects in REBOL2 you can make use of the fact that when creating an object from a prototype REBOL doesn't perform a "deep" copy. (I think REBOL 3 will be different in this aspect.
    
>> proto: make object! [
[    functions: make object! [
[        fa: func [][print "hello"]
[        ]
[    ]
>> a: make proto []
>> b: make proto []
>> a/functions/fa
hello
>> b/functions/fa
hello
>> proto/functions/fa: func [] ["world"]
>> a/functions/fa
== "world"
>> b/functions/fa
== "world"

posted by:   Peter W A Wood       20-May-2010/3:56:45-7:00



Code sharing AND using a value from the calling object:
    
a: make proto [x: "aaa"]
b: make proto [x: "bbb"]
    
a/functions/fa
>> aaa ;fa function should get the value from the object a
    
b/functions/fa
>> bbb ;same for b


posted by:   Endo       20-May-2010/4:11:50-7:00



I mean, how the function F inside the proto object, gets the value of the word 'x inside the calling object (a and b)? And that function should be a shared function between the objects.
    
Should pass the following test:
same? get in A 'f get in B 'f
>> true

posted by:   Endo       20-May-2010/4:15:31-7:00



This works:
    
a: "sss"
f: func [obj] [print bind [a] obj]
f 'system
o: context [a: "ooo" x: :f]
o/x o
p: context [a: "ppp" y: :f]
p/y p
same? get in o 'x get in p 'y

posted by:   Nick       20-May-2010/10:53:25-7:00



Still the same function - just passing the desired context as a parameter.
    
Check out these articles:
    
http://www.pat665.free.fr/doc/bind.html
http://www.rebol.net/wiki/Bindology

posted by:   Nick       20-May-2010/10:56:27-7:00



That is what I want, it would be great if it is possible to use without a parameter, using self keyword for example.
I'm not sure that it is possible or not. Thanks Nick. I read the bindology document, it is a great document.

posted by:   Endo       20-May-2010/11:42:56-7:00



Endo, Remember that REBOL is a prototype based object system, not class based. Your function needs to be bound to some context in order to evaluate words. You can either do that when the function is built, or you can re-bind the body of the function dynamically (or specific words as Nick showed).
    
There is no right or wrong, just tradeoffs. If you're creating millions of objects, shared functions may be the way to go. If you're making millions of calls against a func, the extra binding overhead may be an issue.
    
You may also need to consider scenarios like recursive functions, closure/local-series issues, etc.

posted by:   Gregg Irwin       20-May-2010/14:59:19-7:00



Thanks Gregg, I understand. I just want to learn more about binding.
"REBOL is a prototype based object system, not class based. Functions need to be bound to some context in order to evaluate words" is a great explanation.

posted by:   Endo       20-May-2010/17:13:45-7:00