source: project/wiki/eggref/4/protobj @ 31333

Last change on this file since 31333 was 31333, checked in by svnwiki, 7 years ago

Anonymous wiki edit for IP [213.250.31.28]: Replaced a dead link.

File size: 8.6 KB
Line 
1[[tags: egg]]
2
3== protobj
4
5[[toc:]]
6
7=== Description
8
9Prototype-Delegation Object Model in Scheme
10
11=== Author
12
13Neil van Dyke
14
15=== Documentation
16
17To use the definitions described in this document import its bindings
18by evaluating the {{(import protobj)}} form in the current scope.
19
20Protobj is a Scheme library that implements a simple prototype-delegation
21object model, somewhat similar to that of [Self], and also related to
22[SLIB-Object] and [OScheme].  Protobj was written mainly as a
23{{syntax-rules}} learning exercise, but also because people ask about
24prototype object models for Scheme from time to time.  Like most object
25systems, it should be regarded as an amusement.  The Protobj library defines
26both a verbose set of procedures, and terse special syntax.
27
28Protobj is based on objects with named slots that can contain
29arbitrary values.  Object have immediate slots, and single parent
30objects from which additional slots are inherited.  When setting in a
31child object a slot inherited from the parent, a new immediate slot is
32created in the child so that the parent is unaffected and the slot is
33no longer inherited.
34
35Methods are simply closures stored in slots.  When a method is
36applied, the first term of the closure is the receiver object.  Unlike
37Self, getting the contents of the slot is distinguished from
38invoking a method contained in the slot.  This distinction was made
39due to the way first-class closures are often used in Scheme.
40
41An object is cloned by invoking the {{clone}} method.  The default
42root object's {{clone}} method creates a new child object without any
43immediate slots, rather than copying any slots.  This behavior can be
44overridden to always copy certain slots, to copy immediate slots, or
45to copy all inherited slots.  An overriding {{clone}} method can be
46implemented to apply its parent's {{clone}} method to itself and then
47set certain slots in the new child appropriately.
48
49The following is a quick tour of Protobj using the terse special
50syntax.
51
52Bind {{a}} to the new object that is created by cloning the default root
53object ({{%}} is special syntax for invoking the {{clone}} method):
54
55  (define a (%))
56
57Verify that {{a}} is an object and that {{a}}'s parent is the default
58root object:
59
60  (object? a) => #t
61  (eq? (^ a) (current-root-object)) => #t
62
63Add to {{a}} a slot named {{x}} with value {{1}}:
64
65  (! a x 1)
66
67Get {{a}}'s slot {{x}}'s value:
68
69  (? a x) => 1
70
71Bind {{b}} to a clone of {{a}}:
72
73  (define b (% a))
74
75Get {{b}}'s slot {{x}}'s value, which is inherited from {{a}}:
76
77  (? b x) => 1
78
79Set {{a}}'s slot {{x}}'s value to {{42}}, and observe that {{b}}
80inherits the new value:
81
82  (! a x 42)
83  (? a x) => 42
84  (? b x) => 42
85
86Set {{b}}'s slot {{x}}'s value to {{69}}, and observe that {{a}}
87retains its own {{x}} value although {{b}}'s {{x}} value has been
88changed:
89
90  (! b x 69)
91  (? a x) => 42
92  (? b x) => 69
93
94Add to {{a}} an {{xplus}} slot containing a closure that implements a
95method of the object:
96
97  (! a xplus (lambda (self n) (+ (? self x) n)))
98
99Apply the method to the {{a}} and {{b}} objects ({{b}} inherits
100any new slots added to {{a}}):
101
102  (@ a xplus 7) => 49
103  (@ b xplus 7) => 76
104
105Observe the shorthand syntax for applying methods to an object
106multiple times, with the syntax having the value of the lastmost
107application:
108
109  (@ a (xplus 1000) (xplus 7)) => 49
110
111Bind to {{c}} an object that clones {{a}} and adds slot {{y}} with
112value {{101}}:
113
114  (define c (% a (y 101)))
115
116Get the values of both the {{x}} and {{y}} slots of {{c}}:
117
118  (? c x y) => 42 101
119
120Finally, bind {{d}} to a clone of {{a}} that overrides {{a}}'s {{x}}
121slot:
122
123  (define d (% a (x 1) (y 2) (z 3)))
124  (? d x y z) => 1 2 3
125
126The basic interface of Protobj is a set of procedures.
127
128<procedure>(object? x)</procedure>
129
130Predicate for whether or not {{x}} is a Protobj object.
131
132<procedure>(object-parent obj)</procedure>
133
134Yields the parent object of object {{obj}}.
135
136<procedure>(object-set! obj slot-symbol val)</procedure>
137
138Sets the slot identified by symbol {{slot-symbol}} in object {{obj}} to
139value {{val}}.
140
141<procedure>(object-get obj slot-symbol)</procedure>
142
143Yields the value of slot named by symbol {{slot-symbol}} in object
144{{obj}} (immediate or inherited).  If no slot of that name exists, an
145error is signaled.
146
147<procedure>(object-get obj slot-symbol noslot-thunk)</procedure>
148
149Yields the value of slot named by symbol {{slot-symbol}} in object
150{{obj}} (immediate or inherited), if any such slot exists.  If no slot
151of that name exists, then yields the value of applying closure
152{{noslot-thunk}}.
153
154<procedure>(object-apply obj slot-symbol { arg }*)
155
156Applies the method (closure) in the slot named by {{slot-symbol}} of
157object {{obj}}.  The first term of the method is {{obj}}, and one or
158more {{arg}} are the remaining terms.  If no such slot exists, an
159error is signaled.
160
161<procedure>(object-apply/noslot-thunk obj noslot-thunk slot-symbol { arg }*)</procedure>
162
163Like {{object-apply}}, except that, if the slot does not exist,
164instead of signalling an error, the value is the result of applying
165{{noslot-thunk}}.
166
167<procedure>(object-raw-clone/no-slots-copy obj)</procedure>
168<procedure>(object-raw-clone/copy-immed-slots obj)</procedure>
169<procedure>(object-raw-clone/copy-all-slots obj)</procedure>
170
171These procedures implement different ways of cloning an object, and are
172generally bound as {{clone}} methods in root objects.
173{{/no-slots-copy}} does not copy any slots, {{/copy-immed-slots}}
174copes immediate slots, and {{/copy-all-slots}} copies all slots
175including inherited ones.
176
177<parameter>(current-root-object)</parameter>
178
179Parameter for the default root object.  The initial value is a root
180object that has {{object-raw-clone/no-slots-copy}} in its {{clone}}
181slot.
182
183Since Protobj's raison d'etre was to play with syntax, here it is.
184Note that slot names are never quoted.
185
186<macro>(^ obj)</macro>
187
188Parent of {{obj}}.
189
190<macro>(! obj slot val)</macro>
191<macro>(! obj)</macro>
192
193Sets object {{obj}}'s slot {{slot}}'s value to {{val}}.  In the second
194form of this syntax, multiple slots of {{obj}} may be set at once, and
195are set in the order given.
196
197<macro>(? obj { slot }+)</macro>
198
199Yields the values of the given {{slot}}s of {{obj}}.  If more than one
200{{slot}} is given, a multiple-value return is used.
201
202<macro>(@ obj slot { arg }*)</macro>
203<macro>(@ obj { (slot { arg }* ) }+)</macro>
204
205Applies {{obj}}'s {{slot}} method, with {{obj}} as the first term and
206{{arg}}s as the remaining terms.  In the second form of this syntax,
207multiple methods may be applied, and the value is the value of the
208last method application.
209
210<macro>(% [ obj { (slot val) }* ])</macro>
211
212Clones object {{obj}}, binding any given {{slot}}s to respective given
213{{val}}s.
214
215You can override the method {{print}} to customize printing of objects:
216
217<enscript highlight=scheme>
218(define x (%))
219(! x print
220     (lambda (self #!optional (port (current-output-port)))
221       (fprintf port "#<my object>")))
222</enscript>
223
224==== References
225
226; [LGPL] : Free Software Foundation, "GNU Lesser General Public License," Version
2272.1, February 1999, 59 Temple Place, Suite 330, Boston, MA 02111-1307
228USA. [[http://www.gnu.org/copyleft/lesser.html]]
229
230; [OScheme] : Anselm Baird-Smith, "OScheme." [[http://koala.ilog.fr/abaird/oscheme/om.html]]
231
232; [Self] : David Ungar and Randall B. Smith, "Self: The Power of Simplicity," ''Lisp and Symbolic Computation'', 4, 3, 1991.
233[[http://bibliography.selflanguage.org/_static/self-power.pdf]]
234
235; [SLIB-Object] : Wade Humeniuk, "Macroless Object System," SLIB {{object}}.
236[[http://swissnet.ai.mit.edu/~jaffer/slib_7.html#SEC180]]
237
238; [SRFI-9] : Richard Kelsey, "Defining Record Types," SRFI 9, 9 September 1999.
239[[http://srfi.schemers.org/srfi-9/srfi-9.html]]
240
241; [SRFI-23] : Stephan Houben, "Error reporting mechanism," SRFI 23, 26 April 2001.
242[[http://srfi.schemers.org/srfi-23/srfi-23.html]]
243
244; [SRFI-39] : Marc Feeley, "Parameter objects," SRFI 39, 30 June 2003.
245[[http://srfi.schemers.org/srfi-39/srfi-39.html]]
246
247; [Testeez] : Neil W. Van Dyke, "Testeez: Simple Test Mechanism for Scheme," Version 0.1.
248[[http://www.neilvandyke.org/testeez/]]
249
250=== Changelog
251
252* 0.3 Added {{print}} method
253* 0.2 Bugfix, {{$}} changed to {{?}}
254* 0.1 Initial release
255
256=== License
257
258  Copyright (c) 2005 Neil W. Van Dyke.  This program is Free
259  Software; you can redistribute it and/or modify it under the terms of the
260  GNU Lesser General Public License as published by the Free Software
261  Foundation; either version 2.1 of the License, or (at your option) any
262  later version.  This program is distributed in the hope that it will be
263  useful, but without any warranty; without even the implied warranty of
264  merchantability or fitness for a particular purpose.  See the GNU Lesser
265  General Public License [LGPL] for details.  For other license options and
266  commercial consulting, contact the author.
267
Note: See TracBrowser for help on using the repository browser.