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

Binding a changed function within a context

 [1/8] from: gscottjones:mchsi at: 5-Oct-2002 7:27


Hi, List, I am working on an enhanced version of a field widget. In order to get the enhanced functionality, I need to modify a function within the context of edit-text in REBOL. The code is too long for easy use on the list (in my opinion), so I have created a very simple example that (hopefully) recreates the problem in the "small." Here is my hypothetical context. It contains a local variable and a function that prints that variable. my-context: context [ local-var: 5 my-func: does [ print local-var ] ] where then executing: my-context/my-func ;yields 5 Now, let us say that I wish to dynamically change the function in this object to the following: my-func: does [ print ["new print" local-var] ] where my-func will be bound into the context of my-context. For your ease in running the code samples, I have included the original context object with each example. In my non-hypothetical case, the shortest code method would be to change the code in place like: ;### Method 1 ;original my-context: context [ local-var: 5 my-func: does [ print local-var ] ] ;make change insert remove remove pick pick pick my-context 2 3 2 [print ["new print" local-var]] This makes my-context "look" correct (meaning that the data representation of the code is correct when viewed with probe), but the inner function is not bound into the context: my-context/my-func ;expectedly yields an error For completeness (to be sure that I understood the precept behind bind), I also directly reassigned the function: ;### Method 2 ;original my-context: context [ local-var: 5 my-func: does [ print local-var ] ] ;make change my-context/my-func: does [ print ["new print" local-var] ] and again confirmed that an error occurs with my-context/my-func, because it has not been bound into the context. In the past, my tried and true way to make it work has been to "re-make" the object with the new function: ;### Method 3 ;original my-context: context [ local-var: 5 my-func: does [ print local-var ] ] ;make change my-context: make my-context [ my-func: does [ print ["new print" local-var] ] ] which then works correctly when executing my-context/my-func (yields "new print 5"). I understand the basic concepts behind scope and binding, and how these play out in REBOL. It seems as though it should be easy enough to use bind, but I can't figure out how to (successfully) do this when changing a function within a context, at least with methods 1 and 2. Nothing wrong with method 3, but I would love to also be able to use method 1 or 2 with a strategically and correctly placed bind statement. Any ideas? --Scott Jones

 [2/8] from: brett:codeconscious at: 5-Oct-2002 23:02


Not a general solution but given you are talking about edit-text, you could try something like: my-context: context [ local-var: 5 my-func: does [ print local-var ] ] my-context/my-func: does bind [ print ["new print" local-var] ] in my-context 'self Regards, Brett.

 [3/8] from: g:santilli:tiscalinet:it at: 5-Oct-2002 15:14


Hi Scott, On Saturday, October 5, 2002, 2:27:53 PM, you wrote: GSJ> ;### Method 1 GSJ> ;original GSJ> my-context: context [ GSJ> local-var: 5 GSJ> my-func: does [ GSJ> print local-var GSJ> ] GSJ> ] GSJ> ;make change GSJ> insert remove remove pick pick pick my-context 2 3 2 [print ["new print" GSJ> local-var]]
>> insert remove remove pick pick pick my-context 2 3 2 bind [print ["new print" local-var]] in my-context 'self
== []
>> my-context/my-func
new print 5 GSJ> ;### Method 2 GSJ> ;original GSJ> my-context: context [ GSJ> local-var: 5 GSJ> my-func: does [ GSJ> print local-var GSJ> ] GSJ> ] GSJ> ;make change GSJ> my-context/my-func: does [ GSJ> print ["new print" local-var] GSJ> ]
>> my-context/my-func: does bind [print ["new print" local-var]] in my-context 'self >> my-context/my-func
new print 5 HTH, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r

 [4/8] from: gscottjones:mchsi at: 5-Oct-2002 8:52


Hi, Brett and Gabriele, From: "Brett Handley" ...
> my-context: context [ > local-var: 5
<<quoted lines omitted: 5>>
> print ["new print" local-var] > ] in my-context 'self
.. and moments later .. From: "Gabriele Santilli"
> insert remove remove pick pick pick my-context 2 3 2 bind [print ["new
print" local-var]] in my-context 'self ..and ..
> my-context/my-func: does bind [print ["new print" local-var]] in
my-context 'self Wow, you have both made it look so simple, but I can honestly say given your solutions that I would have never figured this out, despite following the list and reading Ladislav's and Patrick's bind comments. I guess this demonstrates that a gap can still exist between reading concepts and applying concepts. Thanks! --Scott Jones

 [5/8] from: laurent::giroud::libertysurf::fr at: 5-Oct-2002 18:51


Hi Gabriele,
>>> my-context/my-func: does bind [print ["new print" local-var]] in my-context 'self >>> my-context/my-func > new print 5
reading your second example I came to the conclusion that 'bind must actually do the binding then return the exact words it was passed as parameters. Since "help bind" does not indicate what data 'bind effectively returns I tested it directly by simply replicating only the last part of your example :
>> bind [print ["new print" local-var]] in my-context 'self
== [print ["other print" local-var]] which confirms that 'bind effectively returns its first parameter. But thinking a bit about this last line of code brought me more and more questions. First of all, in that test the word "self" is used in a context where it seems to be innapropriate (there is no object lying around) : what does 'self refer to in such a case ?
>> probe self
** Script Error: self has no value ** Where: halt-view ** Near: probe self
>> type? self
** Script Error: self has no value ** Where: halt-view ** Near: type? self So do you have an idea why did my test not fail ? It seems like it should have resulted in an error don't you think. Why is it not the cas ? And finally, how does rebol exactly know how to correctly interpret 'self in your example line ? In it, you redefine a field of the my-context object : is it sufficient for rebol to determine that the word self must refer to that object ? I do not see clearly yet how and when rebol affects values to the 'self word. Since context has much importance in rebol, I guess it's good to know such thing ;) Regards, Laurent -- Laurent Giroud

 [6/8] from: g:santilli:tiscalinet:it at: 5-Oct-2002 20:02


Hi Laurent, On Saturday, October 5, 2002, 6:51:14 PM, you wrote: LG> reading your second example I came to the conclusion that 'bind must actually do LG> the binding then return the exact words it was passed as parameters. It changes the argument block (unless the /COPY refinement is used) and returns it. LG> First of all, in that test the word "self" is used in a context where it seems LG> to be innapropriate (there is no object lying around) : what does 'self refer to LG> in such a case ? First of all, notice it is a lit-word, and not a word. I.e. if you write:
>> 'self
== self you don't get an error, because you are not trying to get a value from the word "self", but rather you are referring to the word itself (thus "literal word"). After that, notice also that I wrote "in my-context 'self".
>> help in
USAGE: IN object word DESCRIPTION: Returns the word in the object's context. IN is a native value. ARGUMENTS: object -- (Type: object) word -- (Type: word) So "in my-context 'self" takes the word "self" and returns it bound to the object's context. I used "self" just because any object has that word. I could have used any other word in the object. (If the passed word is not present in the object, IN returns NONE.) So we have: (bind [...] (in my-context 'self)) BIND takes a word as its second argument, and binds the block passed as its first argument to the same context to which that word is bound. Since IN returns the word 'SELF bound to the context of the object MY-CONTEXT, basically we are binding the block to the context of the object MY-CONTEXT. For better readability, one could write: bind-to-object: func [block object] [bind block in object 'self] and use that instead. LG> Since context has much importance in rebol, I guess it's good to know such thing LG> ;) Absolutely. Feel free to ask. Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r

 [7/8] from: laurent:giroud:libertysurf at: 5-Oct-2002 22:57


> For better readability, one could write: > bind-to-object: func [block object] [bind block in object 'self] > and use that instead.
Well, I am glad you clarified that one. I had completely skipped the 'in function and the quote preceeding "self" thus completely missing how the binding mecanism was actually taking place. This looked like some kind of magic was operating there ;) Thanks, Laurent -- Laurent Giroud

 [8/8] from: brett:codeconscious at: 6-Oct-2002 15:24


For amusement, below are some examples of words bound to different contexts. Just move throught the code by copying from the email and pasting bits of it at a time into the console. Regards, Brett. ; ; Amusement 1 ; ; BIND matches up words it can find in the target context. ctx-1: context [country: "Australia"] ctx-2: context [city: "Sydney"] ctx-3: context [name: "Brett"] expression: [join name [{ lives in } city {, } country]] repeat ctx reduce [ctx-1 ctx-2 ctx-3] [bind expression in ctx 'self] print expression ; ; Functions create a new context binding the words of their body block ; to their arguments: my-func: func [name] expression my-func "My wife" ; ; Amusement 2 ; ; This first bit is straight forward - what appears to be ; nesting of contexts. As others have pointed out (probably ; more clearly than me) this is an effective or apparent ; nesting. ctx-1: context [ word-a: #1a word-b: #1b word-c: #1c ctx-2: context [ word-a: #2a word-b: #2b ctx-3: context [ word-a: #3a set 'print-it does [ print ["First function" word-a word-b word-c] ] ] ] ] print-it ; ; We can simulate the apparent scoping of CONTEXT with ; script that is obviously not nested... ; ctx-1: context [word-a: #1a word-b: #1b word-c: #1c] ctx-2: context [word-a: #2a word-b: #2b] ctx-3: context [word-a: #3a] contexts: reduce [ctx-1 ctx-2 ctx-3] expression: [print ["Expression" word-a word-b word-c]] repeat ctx contexts [bind expression in ctx 'self] do expression ; ; Or indeed reverse it, or perhaps do other odd ; bindings. ; reverse contexts repeat ctx contexts [bind expression in ctx 'self] do expression ; ; Amusement 3 ; ; REBOL represents words to you using ; their names but does not have a visual representation for ; the context of those words. ; When you print the mold of the expression of this example ; you cannot see the difference between the two words that ; have the same name 'sample-word. ; Philosophical point: ; It is easy to fall into the trap of mistaking the name ; of a thing for the thing itself. As always with REBOL, ; the items you see in the console or in a file are not ; the things themselves but representations of the things. ctx-1: context [sample-word: "Context1"] ctx-2: context [sample-word: "Context2"] expression: [{A word: }] append expression in ctx-1 'sample-word append expression [{^/A different word with the same name: }] append expression in ctx-2 'sample-word print expression ; This last example was admittedly contrived, and you ; wouldn't expect to see it used much. But I think ; it has value in showing a different way to look at ; REBOL words.

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