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

[REBOL] [constructors] Re: Some other questions

From: joel::neely::fedex::com at: 22-Nov-2003 23:47

Hi, Mike, Mike Loolard wrote:
> 3) Back on objects: > objects seem to be pretty neat in REBOL - but I didn't find anything about > implementing > and using constructor/destructors ? > > I know I could manually add a function that serves as constructor each time > I create an object, but is that the way REBOL requires it ? >
You don't need constructors in REBOL. Since REBOL also doesn't have classes, objects can either be created directly: tally: make object! [ count: 0 total: 0 put: func [x [number!]] [ total: total + x count: count + 1 ] get: func [] [ reduce [total total / max count 1] ] reset: func [] [count: total: 0] ] or created from a "prototype" object. In this second case, you must supply a block (possibly empty) of changes or additions. The simplest case is constructing another object with identical properties: tally2: make tally [] whose initial values will be based on the current values of the object used as a prototype. You can also base a new object on an existing one, but make some changes in the initial state, add methods/attributes, or change methods. enr0n: make tally [ total: 1000000 put: func [x [number!]] [ total: total + x + 1000000 count: count + 17 ] ] If you *want* to implement a function that serves as a constructor, you certainly can, using the above standard capabilities. As OBJECT! is a first-class data type in REBOL, there's nothing magical about writing a function which returns an object: make-tally: func [] [ make object! [ count: 0 total: 0 put: func [x [number!]] [ total: total + x count: count + 1 ] get: func [] [ reduce [total total / max count 1] ] reset: func [] [count: total: 0] ] ] ...but that doesn't buy us much. It would be more useful if we had a small number of attributes that were initialized based on the function's arguments, but that's just a convenience issue, not a fundamental issue of REBOL capabilities. Finally, when I know I will be using multiple similar objects, I have sometimes put a function within the object itself to provide me with another, similar object (again just for convenience), as in: tally: make object! [ count: 0 total: 0 put: func [x [number!]] [ total: total + x count: count + 1 ] get: func [] [ reduce [total total / max count 1] ] reset: func [] [count: total: 0] new: func [/local result] [ result: make self [] result/reset result ] ] That way the fresh "instance" is always initialized to some standard beginning state. Actually, I'd be more likely to write this as: tally: make object! [ count: 0 total: 0 put: func [x [number!]] [ total: total + x count: count + 1 ] get: func [] [ reduce [total total / max count 1] ] reset: func [] [count: total: 0 self] new: func [] [do in make self [] 'reset] ] As for "destructors", there's little need in REBOL as memory management (including garbage collecting) is automatic. If you *want* to add a method to an object to release big data structures, print final state, or whatever, you can certainly do so, but you'll have to invoke it for yourself, as the concept of an automatic call to a finalizer is not in REBOL. -jn-