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

Storing/loading object functions

 [1/7] from: knizhnik::garret::ru at: 6-Dec-2003 21:20


GI> Hi Konstantin, KK>> I am developer of object oriented database for dynamic languages KK>> (www.garret.ru/~knizhnik/dybase.html) KK>> Currently it supports PHP, Python and Ruby. Now I am going to develop KK>> Rebol API for DyBASE. GI> That's great! I think someone mentioned DyBase here not too long ago. GI> Christian already answered your question, but please don't hesitate to GI> ask more questions here. I think a lot of us would be glad to help, GI> and there are some real gurus here so, if it can be done, someone here GI> will know how to do it. So I have once again to ask for a help. Unlike all other languages with OO extensions I have deal before, in Rebol there are completely no classes - objects are used as prototypes to create other objects. Certainly it is very flexible approach and in most situation programmer see no difference between using class or prototype object. But to be able to store and load objects from the database, I need to store/load not only object values but also objet functions (which actually are treated as normal object fields with function value). I have never faced with this problem before (in PHP, Python or Ruby) API, because it was always assumed that application itself keeps method definition. And if method definition is changed it is likely to be changed for all objects of this class and not only for newly created objects. But in Rebol there is no class. And looks like there is no way to find out prototype object for the particular object instance. So it seems to me that the only possible solution in Rebol is to store functions inside database. So my questions are 1. May be I missed something and there is some other way of setting object functions for loaded persistent object? 2. How it is possible to store function? It seems to be two possible solutions: represent it as series or convert it to string. I do not know how to implement any of them:
>> probe :f
func [][var3: now/time]
>> to-string :f
== "?function?"
>> first :f
== []
>> second :f
== [var3: now/time]
>> block? :f
== false
>> series? :f
== false So to-string function returns only "?function?" string and although it is possible to apply to function first, second,... it is itself not a block. So is possible to convert function to block and visa versa? 3. If I store object function as string or some other way, how can I restore it? If I apply "do" to string containing function body, then I will get function. But...it will not be bounded to the context of the object - it will not be able to access instance variables. So how can I dynamically create object function? 4. And one more question - is there some kind of weak references in Rebol? A lot of thanks in advance Konstantin GI> You may even get a volunteer or two to help you! GI> --Gregg -- Best regards, Konstantin mailto:[knizhnik--garret--ru]

 [2/7] from: nitsch-lists:netcologne at: 6-Dec-2003 22:10


Am Samstag 06 Dezember 2003 19:20 schrieb Konstantin Knizhnik:
> GI> Hi Konstantin, > KK>> I am developer of object oriented database for dynamic languages
<<quoted lines omitted: 20>>
> changed for all objects of this class and not only for newly created > objects.
You want to store the class for the object or indivuidual functions? If class:
> But in Rebol there is no class. And looks like there is no way to find > out prototype object for the particular object instance.
except you store the classname in the object a-class: make object! [type: "a-class" a: none] http://rebol.it/volker/wiki/dybasify1.r a more efficient way is to use a method-object, like faces do. then you have a-handler: context [ type: "a-handler" add: func [this increment] [this/value: this/value + increment] ; ^ note we pass 'this explicitely ] a-class: context [handler: a-handler a: none] a-object: make a-class [value: 5] a-object/handler/add a-object 3 the call-syntax is not very handy, but complete /view-styles are based on this system. Usually there is a dispatch-function, so that one can write ao-add: func[this incr][this/handler/add this 3] ao-add a-object 4 see 'do-face in /view, or 'show, which dispatches to face/feel/redraw and does some more work. http://rebol.it/volker/wiki/dybasify2.r note i dropped the string-encoding for data here, to have something to add.
> So it seems to me that the only possible solution in Rebol is to store > functions inside database. So my questions are > > 1. May be I missed something and there is some other way of setting > object functions for loaded persistent object? > 2. How it is possible to store function? It seems to be two possible > solutions: represent it as series or convert it to string. >
str probe mold :append append2: do str ; the ":" is important here! ; binding may make problems. Keep the functions better outside ; the data-object. see handler-approach. (if you really want to store source in db)
> I do not know how to implement any of them: > >> probe :f
<<quoted lines omitted: 13>>
> itself not a block. So is possible to convert function to block and > visa versa?
'mold, to a string. or: append2: func third :append second :append ; rebuild from the blocks
> 3. If I store object function as string or some other way, how can I > restore it? If I apply "do" to string containing function body, then I > will get function. But...it will not be bounded to the context of the > object - it will not be able to access instance variables. > So how can I dynamically create object function? >
a) handler approach b) convert data to a rebol source-string, then do that. means wrap "make object!" around etc. then 'do does the rest.
> 4. And one more question - is there some kind of weak references in > Rebol?
No.
> A lot of thanks in advance > Konstantin > > GI> You may even get a volunteer or two to help you! > > GI> --Gregg
-Volker

 [3/7] from: lmecir:vol:cz at: 7-Dec-2003 11:27


Hi, Volker wrote:
> If class:
...
> a more efficient way is to use a method-object, like > faces do.
<<quoted lines omitted: 17>>
> or 'show, which dispatches to face/feel/redraw and does > some more work.
An universal dispatcher can be written as follows: msg: func [ {simple message dispatcher} [throw] message [block!] ] [ use [this method call] copy/deep [ set [this message] do/next message method: first message message: next message if not path? method [method: to path! method] insert method 'this/handler call: make block! 2 + length? message insert/only call method insert tail call this insert tail call message do call ] ] Instead of writing: a-object/handler/add a-object 3 we can use the above dispatcher and write: msg [a-object add 3] -- Eurotel Data Nonstop - Neomezený přístup na internet již od 799 Kč měsíčně! http://www.eurotel.cz/site/cz/servicesAndTariffs/specialOffer.html?list=34995

 [4/7] from: antonr:iinet:au at: 7-Dec-2003 22:38


I was about to say I found a nice way, but the following leads to a mold bug, which I mention in previous email:
>> prototype: make object! [a: 23 class: none do [class: self]] >> o: make prototype [a: 42] >> o/class/a
== 23
>> o: make prototype [a: 83] >> o/class/a
== 23
>> o/a
== 83 So you could iterate through all your objects, collecting a list of "classes" (eg. reference to prototype), then, save those "base class" objects, including the functions. Other, derived objects should have the functions clipped away. We're assuming that they are all just copies of the prototype's functions anyway.. That works as long as the derived objects do not modify/redefine the inherited functions, of course. After reading Volker's answer I think he is right about using a string for the class name, for serialisation to db. Anton.

 [5/7] from: nitsch-lists:netcologne at: 7-Dec-2003 17:04


Am Sonntag 07 Dezember 2003 11:27 schrieb [lmecir--vol--cz]:
> Hi, > > Volker wrote: > Instead of writing: > > a-object/handler/add a-object 3 > > we can use the above dispatcher and write: > > msg [a-object add 3]
I want to note quickly that the lack of dispatching is intentional imho. This dispatching is often used for optimising(memory, otherwise functions in objects work well. Or, when dispatchers are used, they often do more than one dispatch. like 'show, which calls the raffected faces to actualize face-description and then draws them. Or some stuff in protoco AFAIK, where 'copyand friends check if the have to wait and such (do they? not a protocol-writer). or 'write which dispatchs to 'open, 'insert and 'close. so being flexible, but not itself called my a dispatcher. In my experience a simple one-call-dispatcher makes rarely sense. (In the size-dimensions of a rebol-script at least). Another is that objects may have multiple dispatchers, a kind of better controlled multiple inheritance. But just for fun, we could try a dsp-add: dispatch-to a-object 'add only difficulty is passing refinements. -Volker

 [6/7] from: knizhnik:garret:ru at: 7-Dec-2003 23:33


Hello Volker, The problem is that I want to be able to store in database ANY object. So, if I correctly understand you, the only possible solution in this case is create string with definition of the object "make object! ..." and then evaluate this string using "do". It seems to me that performance of such solution will be awful. Ok, then alternative is to require persistent object to contain "class:" attribute which specifies prototype object. In this case I database do not need to store/load methods. It will use prototype object for creation of loaded instances. And one more question: I find out no way to locate object by string except using "do". Is it the only possible solution and how expensive it is? If it is really the only possible way to locate the object by name and it is not very fast, then I will use hash table to keep name->object mapping. Thanks in advance Konstantin Sunday, December 7, 2003, 12:10:56 AM, you wrote: VN> Am Samstag 06 Dezember 2003 19:20 schrieb Konstantin Knizhnik:
>> GI> Hi Konstantin, >>
<<quoted lines omitted: 25>>
>> objects. >>
VN> You want to store the class for the object or indivuidual functions? VN> If class:
>> But in Rebol there is no class. And looks like there is no way to find >> out prototype object for the particular object instance.
VN> except you store the classname in the object VN> a-class: make object! [type: "a-class" a: none] VN> http://rebol.it/volker/wiki/dybasify1.r VN> a more efficient way is to use a method-object, like faces do. VN> then you have VN> a-handler: context [ VN> type: "a-handler" VN> add: func [this increment] [this/value: this/value + increment] VN> ; ^ note we pass 'this explicitely VN> ] VN> a-class: context [handler: a-handler a: none] VN> a-object: make a-class [value: 5] VN> a-object/handler/add a-object 3 VN> the call-syntax is not very handy, VN> but complete /view-styles are based on this system. VN> Usually there is a dispatch-function, so that one can write VN> ao-add: func[this incr][this/handler/add this 3] VN> ao-add a-object 4 VN> see 'do-face in /view, VN> or 'show, which dispatches to face/feel/redraw and does some more work. VN> http://rebol.it/volker/wiki/dybasify2.r VN> note i dropped the string-encoding for data here, to have something to add.
>> So it seems to me that the only possible solution in Rebol is to store >> functions inside database. So my questions are
<<quoted lines omitted: 4>>
>> solutions: represent it as series or convert it to string. >>
VN> str probe mold :append VN> append2: do str VN> ; the ":" is important here! VN> ; binding may make problems. Keep the functions better outside VN> ; the data-object. see handler-approach. VN> (if you really want to store source in db)
>> I do not know how to implement any of them: >> >> probe :f
<<quoted lines omitted: 25>>
>> itself not a block. So is possible to convert function to block and >> visa versa?
VN> 'mold, to a string. or: VN> append2: func third :append second :append ; rebuild from the blocks
>> >> 3. If I store object function as string or some other way, how can I
<<quoted lines omitted: 3>>
>> So how can I dynamically create object function? >>
VN> a) handler approach VN> b) convert data to a rebol source-string, then do that. VN> means wrap "make object!" around etc. VN> then 'do does the rest.
>> 4. And one more question - is there some kind of weak references in >> Rebol?
VN> No.
>> >> A lot of thanks in advance
<<quoted lines omitted: 4>>
>> >> GI> --Gregg
VN> -Volker -- Best regards, Konstantin mailto:[knizhnik--garret--ru]

 [7/7] from: nitsch-lists:netcologne at: 8-Dec-2003 2:26


Am Sonntag 07 Dezember 2003 21:33 schrieb Konstantin Knizhnik:
> Hello Volker, > The problem is that I want to be able to store in database ANY object.
<<quoted lines omitted: 10>>
> locate the object by name and it is not very fast, then I will use > hash table to keep name->object mapping.
You mean to find the prototype-object? do a-word should be very fast. a word is kind if string hashed by the global context. about [to-word string] i am not sure, but should be fast. because it is done all the time by 'load, so optimized. But hashs are very fast to. so i am interested in a benchmark :) Also with hashes you have more control about naming of prototypes. Otherwise if your code does not contain a prototype, but accidentally a function with the prototype-name exists, [do to-word string] is a bad idea. there is a way to put all proto-objects in a context, like protos: context[proto1: ...] do in protos to-string word [in protos something] returns none if the word does not exist IIRC. But a hash is as good a solution. for benchmarking: findme: context[] t1: now/precise loop 1'000'000[ do to word! "findme" ] difference now/precise t1 == 0:00:05.166109 (with (to-word instead) of[to word!] == 0:00:06.617021) protos: to-hash reduce["findme" context[]] t1: now/precise loop 1'000'000[ select protos "findme" ] difference now/precise t1 == 0:00:04.995347 on p350. Hash wins, but very close.
> Thanks in advance > Konstantin >
HTH :) -Volker

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