[REBOL] Objects: Preventing Code Duplication Re:(11)
Hi, Rebols, Something like: !: func [ object [object!] 'method [word!] /local mth ] [ ; let's skip error checking for clarity mth: get in object/methods method bind second :mth in object 'self return :mth ] ;text skipped a: make object! [ num: 1 methods: make object! [ sumnum: func [other number] [ switch number [ 1 [self/num] 2 [ (do ! other sumnum self 1) + (do ! self sumnum other 1) ] ] ] ] ] Actually it works exactly as I would expect it to. What did you expect your expression >[ (do ! other sumnum self 1) + (do ! self sumnum other 1) ] would do? Could you explain? TIA, Elan Ladislav> Some results: >> b: make a [num: num + 1] >> do ! a sumnum b 1 == 1 >> do ! b sumnum a 1 == 2 >> do ! b sumnum a 2 == 2 >> do ! a sumnum b 2 == 4 I think its' OK for you to expect it. No problemo! I would prefer: ;Function to create methods, adds the hidden SELF argument makemethod: func [args body] [ func append copy [self] args body ] ;Function to call methods !: func [self [object!] 'method [word!] param [block!]] [ do append reduce [in self/methods method self] param ] ;end of %methods.r ;now the example: a: make object! [ num: 1 methods: make object! [ sumnum: makemethod [other number] [ switch number [ 1 [self/num] 2 [ (! other sumnum [self 1]) + (! self sumnum [other 1])] ] ] ] ] b: make a [num: num + 1] >> ! a sumnum [b 1] == 1 >> ! b sumnum [a 1] == 2 >> ! a sumnum [b 2] == 3 >> ! b sumnum [a 2] == 3 The choice is your's, but my vote is: (guess what?) Ladislav
[REBOL] Objects: Preventing Code Duplication Re:(11)
Hi Gabriele, you wrote: >Hello [EMAIL PROTECTED]! >To create simpler methods, why not binding them to the right >object at the right time? > >Something like: > >!: func [ >object [object!] >'method [word!] >/local mth >] [ >; let's skip error checking for clarity >mth: get in object/methods method >bind second :mth in object 'self >return :mth >] > A work of beauty. Simple and effective. Of the different approaches in this thread (including mine, which your function comments on) this is definitely my favorite. Your approach also simplifies the embedded method object to: root: make object! [ var: none methods: make object! [ get-var: func [] [ var ] sumnum: func [other [object!] [ (do ! other get-var) + (self get-var) ] ] ] No need for the member I called object. En passant, Gabriele, I am surprised that 'bind actually does its job in this example. I have had problems using bind sensibly. Somehow, I always manage to get bind to complain that it cannot resolve one or the other thing. Ladislav, I withdraw my proposed ! for Gabriele's. It avoids having to keep in mind which object the word 'object will be bound to, which can become a problem, if you use it thoughtlessly, as you documented. I think we should agree on Gabriele's function and add a little error handling. Do you see any problems with it? Elan
[REBOL] Objects: Preventing Code Duplication Re:(11)
Ciao, Gabriele, you wrote: To create simpler methods, why not binding them to the right object at the right time? Something like: !: func [ object [object!] 'method [word!] /local mth ] [ ; let's skip error checking for clarity mth: get in object/methods method bind second :mth in object 'self return :mth ] - a nice idea. The problem here is that this approach is static, i.e. non-re-entrant, because it uses only static storage for object parameter, namely the code block of method, so your code wouldn't work for something like this too: a: make object! [ num: 1 methods: make object! [ sumnum: func [other number] [ switch number [ 1 [self/num] 2 [ (do ! other sumnum self 1) + (do ! self sumnum other 1) ] ] ] ] ] Ladislav Regards, Gabriele. -- o) .-^-. (--o | Gabriele Santilli / /_/_\_\ \ Amiga Group Italia --- L'Aquila | | GIESSE on IRC \ \-\_/-/ / http://www.amyresource.it/AGI/ | o) `-v-' (--o
[REBOL] Objects: Preventing Code Duplication Re:(11)
Is it possible to make a sound (like a beep) from REBOL?
[REBOL] Objects: Preventing Code Duplication Re:(11)
Hi Ladislav, you wrote: >- >Of course, it works. >But try to rewrite the code like this: > >sumnum: func [other [object!]] [ (do ! other get-num) + > (do ! self get-num) > >and see what happens >--- Do you realize that REBOL supplies every object automatically with the word self? So if you are referring to the following construct: root: make object! [ var: none methods: make object! [ object: none get-num: func [] [ object/var ] sumnum: func [other [object!]] [ (do ! other get-num) + (do ! self get-num) ] then in your example self is referring to the embedded object methods. Methods does not contain a word called var, therefore the attempt to retrieve var from the methods object cannot work. Just as retrieving the value of the word elephant from the object root cannot work. There is no word elephant defined in the object root. There is not word var defined in the object methods. self/var in the methods context however tries to look up var in whatever self evaluates to at that point, which is the "methods" object. That's got nothing to do with re-entrancy! It's got nothing to do with the way I implemented "!" . Look at it like this: If I have the simple object: object: make object! [var: 1] and I then try to use the path notation: object/elephant then REBOL will report an error (as it will in the case you describe above and for the same reasons). To quote the error object/elephant will cause in this example as proof that the path notation doesn't work would be foolish, don't you think? Again, filled with suspense, awaiting your response, Elan
[REBOL] Objects: Preventing Code Duplication Re:(11)
Hi, Elan you wrote: Hi Ladislav, I wrote: (Oh, >and if I concur with my conclusions, please, please make sure that it >really does fail!) Read: (Oh, and if YOU concur ... ) Am I being a little self-centered here? ;-) Sorry, Elan - I was so sure, it would fail I didn't test it and after the send I found out that I should have switched the (! self ...) and (! other ...). I deserve all you sent, no problem. Moreover, I didn't test it for the second time either, because I was so sure... But now, after your apologies, it's tested and guaranteed: If you switch the things, you get the wrong result. I think, I should apologize myself too. I was just too lazy to try and thought, that it would be obvious... - Ladislav
[REBOL] Objects: Preventing Code Duplication Re:(11)
Once again Hi Ladislav, I believe I've figured ou why you think my function should have problems with reentrancy. You see that my function sets the object word of the methods object of the object it is passed. Therefore, whatever ! is doing, it relies on the expectation that the methods/object will have the same value it just set it to, when ! continues. If ! is now evaulated again, with a different object argument, then the first instance of ! will become confused because methods/object has been changed by the second ! invocation. The reason that *cannot* happen is because the second invocation of ! - as in your previous example - is not evaluated until the first invoked ! has already completed its execution. That is because my version of ! does not evaluate the function it retrieves. It just returns it! Since ! can never be called recursively, there is no reentrancy problem. ! will definitely finish executing by the time the function it retrieved is evaluated. Any modifications that function may cause to methods/object is no longer relevant to the successful execution of the first ! instance. Specifically, if the function calls ! again ... even several times over, the same will continue to apply. The first verion of ! already completed its execution, the second invocation of ! will retrieve whatever function it is instructed to retrieve and complete executing. Only then will the third invocation of ! occur, and when that invocation of ! modifies methods/object, the two first invocations have already long ceased to execute. And so on. Have I guessed correctly? Continuing to suspensefully expect your response, Elan