There is an object constructor in rebol

I usually program functions "instinctively", but my current problem can be easily solved by objects, so I will continue this method.

Having done this, I am trying to find a way to give the object a constructor method, for example, the equivalent of init () in python.

I looked at the documentation http://www.rebol.com/docs/core-fr/fr-index.html , but I could not find anything relevant.

+7
constructor oop rebol rebol2
source share
4 answers

Actually, after reading the Rebol Core documentation again (I just followed the good old tips: β€œRead the French manual”), there is another way to implement the constructor, which is quite simple:

http://www.rebol.com/docs/core-fr/fr-rebolcore-10.html#section-8

Of course, this is also in the English Language Guide:

http://www.rebol.com/docs/core23/rebolcore-10.html#section-7

=>

Another example of using the self variable is a function that clones itself:

person: make object! [ name: days-old: none new: func [name' birthday] [ make self [ name: name' days-old: now/date - birthday ] ] ] lulu: person/new "Lulu Ulu" 17-May-1980 print lulu/days-old 7366 

I find this quite convenient, and so the constructor lies inside the object. This fact makes the object more self-sufficient.

I just implemented this for some geological materials and it works well:

 >> source orientation orientation: make object! [ matrix: [] north_reference: "Nm" plane_quadrant_dip: "" new: func [{Constructor, builds an orientation object! based on a measurement, as given by GeolPDA device, a rotation matrix represented by a suite of 9 values} m][ make self [ foreach [abc] m [append/only matrix to-block reduce [abc]] a: self/matrix/1/1 b: self/matrix/1/2 c: self/matrix/1/3 d: self/matrix/2/1 e: self/matrix/2/2 f: self/matrix/2/3 g: self/matrix/3/1 h: self/matrix/3/2 i: self/matrix/3/3 plane_normal_vector: reduce [matrix/1/3 matrix/2/3 matrix/3/3 ] axis_vector: reduce [self/matrix/1/2 self/matrix/2/2 self/matrix/3/2 ] plane_downdip_azimuth: azimuth_vector plane_normal_vector plane_direction: plane_downdip_azimuth - 90 if (plane_direction < 0) [plane_direction: plane_direction - 180] plane_dip: arccosine (plane_normal_vector/3) case [ ((plane_downdip_azimuth > 315) or (plane_downdip_azimuth <= 45)) [plane_quadrant_dip: "N"] ((plane_downdip_azimuth > 45) and (plane_downdip_azimuth <= 135)) [plane_quadrant_dip: "E"] ((plane_downdip_azimuth > 135) and (plane_downdip_azimuth <= 225)) [plane_quadrant_dip: "S"] ((plane_downdip_azimuth > 225) and (plane_downdip_azimuth <= 315)) [plane_quadrant_dip: "W"] ] line_azimuth: azimuth_vector axis_vector line_plunge: 90 - (arccosine (axis_vector/3)) ] ] repr: func [][ print rejoin ["Matrix: " tab self/matrix newline "Plane: " tab north_reference to-string to-integer self/plane_direction "/" to-string to-integer self/plane_dip "/" self/plane_quadrant_dip newline "Line: " tab rejoin [north_reference to-string to-integer self/line_azimuth "/" to-string to-integer self/line_plunge] ] ] trace_te: func [diagram [object!]][ len_queue_t: 0.3 tmp: reduce [ plane_normal_vector/1 / (square-root (((plane_normal_vector/1 ** 2) + (plane_normal_vector/2 ** 2)))) plane_normal_vector/2 / (square-root (((plane_normal_vector/1 ** 2) + (plane_normal_vector/2 ** 2)))) ] O: [0 0] A: reduce [- tmp/2 tmp/1 ] B: reduce [tmp/2 0 - tmp/1] C: reduce [tmp/1 * len_queue_t tmp/2 * len_queue_t ] L: reduce [- axis_vector/1 0 - axis_vector/2] append diagram/plot [pen black] diagram/trace_line AB diagram/trace_line OC diagram/trace_line OL ] ] >> o: orientation/new [0.375471 -0.866153 -0.32985 0.669867 0.499563 -0.549286 0.640547 -0.0147148 0.767778] >> o/repr Matrix: 0.375471 -0.866153 -0.32985 0.669867 0.499563 -0.549286 0.640547 -0.0147148 0.767778 Plane: Nm120/39/S Line: Nm299/0 

Another advantage of this method is that the variables defined by the "new" method directly relate to the "instance" object (I ran into some problems, in other ways, referring to self / sometimes to initialize the variables or not).

+3
source share

There is no special constructor function in Rebol, but it is possible to write ad hoc init code if you need it when creating an object in the spec block. For example:

 a: context [x: 123] b: make a [ y: x + 1 x: 0 ] 

So, if you define your own constructor function by convention in the base object, you can call it a spec block when you create it. If you want to do this automatically, you can wrap it in a function, for example:

 a: context [ x: 123 init: func [n [integer!]][x: n] ] new-a: func [n [integer!]][make a [init n]] b: new-a 456 

A more reliable (but longer) version of new-a, which will avoid the possible collision of passed init arguments with the object's own words:

 new-a: func [n [integer!] /local obj][ also obj: make a [] obj/init n ] 

You can also write a more general new function that will take the base object as the first argument and automatically call the constructor function by congress after cloning the object, but more complex support for additional constructor arguments in the general case.

Remember that the Rebol object model is prototype-based (based on the Python class and most other OOP languages), so the constructor function gets duplicated for each new object. You can avoid this cost if you create a huge number of objects.

+6
source share

As far as I know, there is no formal method / convention for using object constructors such as init() . Of course, there is a built-in method for constructing derived objects:

 make prototype [name: "Foo" description: "Bar"] ; where type? prototype = object! 

My best suggestion would be to define a function that checks the object for the constructor method, then apply this method, here is one such function that I suggested earlier

 new: func [prototype [object!] args [block! none!]][ prototype: make prototype [ if in self 'new [ case [ function? :new [apply :new args] block? :new [apply func [args] :new [args]] ] ] ] ] 

The use is quite simple: if the prototype object has the value new , then it will be used when building the derived object:

 thing: context [ name: description: none new: [name: args/1 description: args/2] ] derivative: new thing ["Foo" "Bar"] 

note that this approach works in both Rebol 2 and 3.

+5
source share

I am trying to figure out how OO works in REBOL. This is actually a prototype. Yesterday I stumbled upon this page, which inspired me to the classic OO model below, without duplicating features:

 ;---- Generic function for class or instance method invocation ----; invoke: func [ obj [object!] fun [word!] args [block!] ][ fun: bind fun obj/.class ;---- Class method names start with a dot and instance method names don't: unless "." = first to-string fun [args: join args obj] apply get fun args ] ;---- A class definition ----; THIS-CLASS: context [ .class: self ; the class refers to itself ;---- Class method: create new instance ----; .new: func [x' [integer!] /local obj] [ obj: context [x: x' .class: none] ; this is the object definition obj/.class: self/.class ; the object will refer to the class ; it belongs to return obj ] ;---- An instance method (last argument must be the instance itself) ----; add: func [y obj] [ return obj/x + y ] ] 

Then you can do this:

 ;---- First instance, created from its class ----; this-object: THIS-CLASS/.new 1 print invoke this-object 'add [2] ;---- Second instance, created from from a prototype ----; that-object: this-object/.class/.new 2 print invoke that-object 'add [4] ;---- Third instance, created from from a prototype in another way ----; yonder-object: invoke that-object '.new [3] print invoke yonder-object 'add [6] ;---- Fourth instance, created from from a prototype in a silly way ----; silly-object: yonder-object/.class/.class/.class/.class/.new 4 print silly-object/.class/add 8 silly-object print this-object/.class/add 8 silly-object print THIS-CLASS/add 8 silly-object 

(He works in REBOL 2 and prints 3, 6, 9, 12, 12, 12 in a row). There is hardly any overhead. It is probably not difficult to find a dozen other solutions. That is the real problem: there are too many ways to do this. (Maybe we better use LoyalScript.)

+3
source share

All Articles