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

Last change on this file since 12592 was 12592, checked in by felix winkelmann, 11 years ago

r4 branch

File size: 8.5 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=== Requirements
16
17[[syntax-case]]
18
19=== Download
20
21[[http://www.call-with-current-continuation.org/eggs/protobj.egg|protobj.egg]]
22
23=== Documentation
24
25This extension uses the {{syntax-case}} macro-/module-system. To use
26the definitions described in this document import its bindings by
27evaluating the {{(import protobj)}} form in the current scope.
28
29Protobj is a Scheme library that implements a simple prototype-delegation
30object model, somewhat similar to that of [Self], and also related to
31[SLIB-Object] and [OScheme].  Protobj was written mainly as a
32{{syntax-rules}} learning exercise, but also because people ask about
33prototype object models for Scheme from time to time.  Like most object
34systems, it should be regarded as an amusement.  The Protobj library defines
35both a verbose set of procedures, and terse special syntax.
36
37Protobj is based on objects with named slots that can contain
38arbitrary values.  Object have immediate slots, and single parent
39objects from which additional slots are inherited.  When setting in a
40child object a slot inherited from the parent, a new immediate slot is
41created in the child so that the parent is unaffected and the slot is
42no longer inherited.
43
44Methods are simply closures stored in slots.  When a method is
45applied, the first term of the closure is the receiver object.  Unlike
46Self, getting getting the contents of the slot is distinguished from
47invoking a method contained in the slot.  This distinction was made
48due to the way first-class closures are often used in Scheme.
49
50An object is cloned by invoking the {{clone}} method.  The default
51root object's {{clone}} method creates a new child object without any
52immediate slots, rather than copying any slots.  This behavior can be
53overridden to always copy certain slots, to copy immediate slots, or
54to copy all inherited slots.  An overriding {{clone}} method can be
55implemented to apply its parent's {{clone}} method to itself and then
56set certain slots in the new child appropriately.
57
58The following is a quick tour of Protobj using the terse special
59syntax.
60
61Bind {{a}} to the new object that is created by cloning the default root
62object ({{%}} is special syntax for invoking the {{clone}} method):
63
64  (define a (%))
65
66Verify that {{a}} is an object and that {{a}}'s parent is the default
67root object:
68
69  (object? a) => #t
70  (eq? (^ a) (current-root-object)) => #t
71
72Add to {{a}} a slot named {{x}} with value {{1}}:
73
74  (! a x 1)
75
76Get {{a}}'s slot {{x}}'s value:
77
78  (? a x) => 1
79
80Bind {{b}} to a clone of {{a}}:
81
82  (define b (% a))
83
84Get {{b}}'s slot {{x}}'s value, which is inherited from {{a}}:
85
86  (? b x) => 1
87
88Set {{a}}'s slot {{x}}'s value to {{42}}, and observe that {{b}}
89inherits the new value:
90
91  (! a x 42)
92  (? a x) => 42
93  (? b x) => 42
94
95Set {{b}}'s slot {{x}}'s value to {{69}}, and observe that {{a}}
96retains its own {{x}} value although {{b}}'s {{x}} value has been
97changed:
98
99  (! b x 69)
100  (? a x) => 42
101  (? b x) => 69
102
103Add to {{a}} an {{xplus}} slot containing a closure that implements a
104method of the object:
105
106  (! a xplus (lambda (self n) (+ (? self x) n)))
107
108Apply the method to the {{a}} and {{b}} objects ({{b}} inherits
109any new slots added to {{a}}):
110
111  (@ a xplus 7) => 49
112  (@ b xplus 7) => 76
113
114Observe the shorthand syntax for applying methods to an object
115multiple times, with the syntax having the value of the lastmost
116application:
117
118  (@ a (xplus 1000) (xplus 7)) => 49
119
120Bind to {{c}} an object that clones {{a}} and adds slot {{y}} with
121value {{101}}:
122
123  (define c (% a (y 101)))
124
125Get the values of both the {{x}} and {{y}} slots of {{c}}:
126
127  (? c x y) => 42 101
128
129Finally, bind {{d}} to a clone of {{a}} that overrides {{a}}'s {{x}}
130slot:
131
132  (define d (% a (x 1) (y 2) (z 3)))
133  (? d x y z) => 1 2 3
134
135The basic interface of Protobj is a set of procedures.
136
137<procedure>(object? x)</procedure>
138
139Predicate for whether or not {{x}} is a Protobj object.
140
141<procedure>(object-parent obj)</procedure>
142
143Yields the parent object of object {{obj}}.
144
145<procedure>(object-set! obj slot-symbol val)</procedure>
146
147Sets the slot identified by symbol {{slot-symbol}} in object {{obj}} to
148value {{val}}.
149
150<procedure>(object-get obj slot-symbol)</procedure>
151
152Yields the value of slot named by symbol {{slot-symbol}} in object
153{{obj}} (immediate or inherited).  If no slot of that name exists, an
154error is signaled.
155
156<procedure>(object-get obj slot-symbol noslot-thunk)</procedure>
157
158Yields the value of slot named by symbol {{slot-symbol}} in object
159{{obj}} (immediate or inherited), if any such slot exists.  If no slot
160of that name exists, then yields the value of applying closure
161{{noslot-thunk}}.
162
163<procedure>(object-apply obj slot-symbol { arg }*)
164
165Applies the method (closure) in the slot named by {{slot-symbol}} of
166object {{obj}}.  The first term of the method is {{obj}}, and one or
167more {{arg}} are the remaining terms.  If no such slot exists, an
168error is signaled.
169
170<procedure>(object-apply/noslot-thunk obj noslot-thunk slot-symbol { arg }*)</procedure>
171
172Like {{object-apply}}, except that, if the slot does not exist,
173instead of signalling an error, the value is the result of applying
174{{noslot-thunk}}.
175
176<procedure>(object-raw-clone/no-slots-copy obj)</procedure>
177<procedure>(object-raw-clone/copy-immed-slots obj)</procedure>
178<procedure>(object-raw-clone/copy-all-slots obj)</procedure>
179
180These procedures implement different ways of cloning an object, and are
181generally bound as {{clone}} methods in root objects.
182{{/no-slots-copy}} does not copy any slots, {{/copy-immed-slots}}
183copes immediate slots, and {{/copy-all-slots}} copies all slots
184including inherited ones.
185
186<parameter>(current-root-object)</parameter>
187
188Parameter for the default root object.  The initial value is a root
189object that has {{object-raw-clone/no-slots-copy}} in its {{clone}}
190slot.
191
192Since Protobj's raison d'etre was to play with syntax, here it is.
193Note that slot names are never quoted.
194
195<macro>(^ obj)
196
197Parent of {{obj}}.
198
199<macro>(! obj slot val)</macro>
200<macro>(! obj)</macro>
201
202Sets object {{obj}}'s slot {{slot}}'s value to {{val}}.  In the second
203form of this syntax, multiple slots of {{obj}} may be set at once, and
204are set in the order given.
205
206<macro>(? obj { slot }+)</macro>
207
208Yields the values of the given {{slot}}s of {{obj}}.  If more than one
209{{slot}} is given, a multiple-value return is used.
210
211<macro>(@ obj slot { arg }*)</macro>
212<macro>(@ obj { (slot { arg }* ) }+)</macro>
213
214Applies {{obj}}'s {{slot}} method, with {{obj}} as the first term and
215{{arg}}s as the remaining terms.  In the second form of this syntax,
216multiple methods may be applied, and the value is the value of the
217last method application.
218
219<macro>(% [ obj { (slot val) }* ])</macro>
220
221Clones object {{obj}}, binding any given {{slot}}s to respective given
222{{val}}s.
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://research.sun.com/self/papers/self-power.html]]
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.2 Bugfix, {{$}} changed to {{?}}
253* 0.1 Initial release
254
255=== License
256
257  Copyright (c) 2005 Neil W. Van Dyke.  This program is Free
258  Software; you can redistribute it and/or modify it under the terms of the
259  GNU Lesser General Public License as published by the Free Software
260  Foundation; either version 2.1 of the License, or (at your option) any
261  later version.  This program is distributed in the hope that it will be
262  useful, but without any warranty; without even the implied warranty of
263  merchantability or fitness for a particular purpose.  See the GNU Lesser
264  General Public License [LGPL] for details.  For other license options and
265  commercial consulting, contact the author.
266
Note: See TracBrowser for help on using the repository browser.