source: branches/1.9-appstore/source/examples/cocoa/currency-converter/HOWTO_files/pages/writing_lisp.html

Last change on this file was 11571, checked in by Gary Byers, 16 years ago

Fix the #/convert method.

File size: 9.0 KB
Line 
1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3<html xmlns="http://www.w3.org/1999/xhtml">
4 <head>
5 <title>CurrencyConverter HOWTO</title>
6 <link rel="stylesheet" type="text/css" href="../stylesheets/styles.css" />
7 </head>
8
9 <body>
10
11 <div class="title">
12 <h1>Writing the Lisp Source</h1>
13 </div>
14
15 <div class="body-text">
16 <p>In this section we'll write Lisp code that duplicates the
17 features provided by the Objective-C code in Apple's
18 tutorial. In Apple's tutorial, the explanation of the Objective
19 C code begins with the
20 section <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/ObjCTutorial/06Controller/chapter_6_section_1.html#//apple_ref/doc/uid/TP40000863-CH8-SW1">Bridging
21 the Model and View: The Controller</a>.</p>
22
23 <p>The Lisp code in this section of the HOWTO is considerably
24 simpler than the corresponding Objective-C code, in part
25 because we can ignore the conventions that XCode uses for
26 laying out source files. We can just write all our definitions
27 into a single Lisp source file, and load that file into Clozure CL
28 when we are ready to build the application.</p>
29
30 <div class="section-head">
31 <h2>First Things First</h2>
32 </div>
33
34 <div class="body-text">
35 <p>Place the following line at the top of your Lisp source file:</p>
36
37 <pre>(in-package "CCL")</pre>
38
39 <p>Clozure CL's Objective-C bridge code is defined in the "CCL"
40 package. Usually, when building an application, you'll create a
41 package for that application and import the definitions you need
42 to use. In order to keep the discussion short in this simple
43 example, we just place all our definitions in the "CCL"
44 package.</p>
45
46 </div>
47
48 <div class="section-head">
49 <h2>Defining the Converter Class</h2>
50 </div>
51
52 <div class="body-text">
53 <p>We begin by defining the Converter class. Recall from Apple's
54 tutorial that this is the Model class that implements the
55 conversion between dollars and other currencies. Here is the
56 Lisp definition that implements the class you created in
57 InterfaceBuilder:</p>
58
59 <pre>
60(defclass converter (ns:ns-object)
61 ()
62 (:metaclass ns:+ns-object))
63 </pre>
64 </div>
65
66 <div class="body-text">
67 <p>This is an ordinary CLOS class definition, with a couple of
68 simple wrinkles. First, the superclass it inherits from is the
69 NS-OBJECT class in the "NS" package. NS-OBJECT is an Objective-C
70 class, the ancestor of all Objective-C objects. This CLOS
71 definition actually creates a new Objective-C class named
72 "Converter".</p>
73
74 <p>We tell Clozure CL how to build the right kind of class object
75 by including the :METACLASS option in the definition:</p>
76
77 <pre>
78 (:metaclass ns:+ns-object)
79 </pre>
80
81 <p>The Objective-C bridge knows that when the metaclass
82 is <code>ns:+ns-object</code>, it must lay out the class object
83 in memory as an Objective-C class, rather than a normal CLOS
84 STANDARD-CLASS.</p>
85
86 <p>Next, we define the method "convertCurrency:atRate:":</p>
87
88 <pre>
89(objc:defmethod (#/convertCurrency:atRate: :float)
90 ((self converter) (currency :float) (rate :float))
91 (* currency rate))
92 </pre>
93
94 <p>This is the method that actually does the currency
95 conversion. It's a Lisp method that will be called when the
96 AppKit sends the Objective-C message "convertCurrency:atRate:"
97 It's very simple&mdash;really, it just multiples
98 <code>currency</code> times <code>rate</code>. Most of the text in the definition is
99 Objective-C bridge code that links the definition to the right
100 class with the right argument and return types.</p>
101
102 <p><code>objc:defmethod</code> is a version of DEFMETHOD that
103 creates methods that can execute in response to Objective-C
104 message-sends.</p>
105
106 <p>The syntax <code>#/convertCurrency:atRate:</code> uses the
107 "#/" reader macro to read a symbol with case preserved, so that
108 you can see in your code the same name that Objective-C uses for
109 the method, without worrying about how the name might be
110 converted between Lisp and Objective-C conventions.</p>
111
112 <p>The number of arguments to an Objective-C method is the
113 number of colons in the name, plus one. Each colon indicates an
114 argument, and there is always an extra "self" argument that
115 refers to the object that receives the message. These are normal
116 Objective-C conventions, but we perhaps need to emphasize the
117 details, since we are using Lisp code to call the Objective-C
118 methods.</p>
119
120 <p>We indicate the return type and the types of arguments in
121 the method definition by surrounding parameters and the method
122 name with parentheses, and appending the type name.</p>
123
124 <p>Thus, for example, </p>
125
126 <pre>
127(#/convertCurrency:atRate: :float)
128 </pre>
129
130 <p>means that the return type of the method is :FLOAT, and </p>
131
132 <pre>
133(self converter)
134 </pre>
135
136 <p>means that the type of the receiving object is Converter.</p>
137
138 <p>You will see these same conventions repeated in the next
139 section.</p>
140 </div>
141
142 <div class="section-head">
143 <h2>Defining the ConverterController Class</h2>
144 </div>
145
146 <div class="body-text">
147 <p>The previous section defined the Model class, Converter. All
148 we need now is a definition for the ConverterController
149 class. Recall from your reading of Apple's Tutorial that the
150 CurrencyConverter example uses the Model-View-Controller
151 paradigm. You used InterfaceBuilder to construct the
152 application's views. The Converter class provides the model
153 that represents application data. Now we define the controller
154 class, ConverterController, which connects the View and the
155 Model.</p>
156
157 <p>Here's the definition of the ConverterController class:</p>
158
159 <pre>
160(defclass converter-controller (ns:ns-object)
161 ((amount-field :foreign-type :id :accessor amount-field)
162 (converter :foreign-type :id :accessor converter)
163 (dollar-field :foreign-type :id :accessor dollar-field)
164 (rate-field :foreign-type :id :accessor rate-field))
165 (:metaclass ns:+ns-object))
166 </pre>
167
168 <p>Once again we use the Objective-C bridge to define an
169 Objective-C class. This time, we provide several
170 instance-variable definitions in the class, and name accessors
171 for each of them explicitly. The <code>:FOREIGN-TYPE</code>
172 initargs enable us to specify the type of each field in the
173 foreign (Objective-C) class.</p>
174
175 <p>Each field in the definition of the ConverterController class
176 is an outlet that will be used to store a reference to one of
177 the text fields that you created in InterfaceBuilder. For
178 example, <code>amount-field</code> will be connected to the
179 "Amount" text field.</p>
180
181 <p>Why did we spell the name "amount-field" in Lisp code, and
182 "amountField" when creating the outlet in InterfaceBuilder? The
183 Objective-C bridge automatically converts Lisp-style field names
184 (like "amount-field") to Objective-C-style field names (like
185 "amountField"), when handling class definitions.</p>
186
187 <p>The <code>converter</code> field at launch time contains a
188 reference to the Converter object, whose class definition is in
189 the previous section.</p>
190
191 <p>The final piece of the implementation is a definition of the
192 "convert:" method. This is the method that is called when a
193 user clicks the "Convert" button in the user interface.</p>
194
195 <pre>
196(objc:defmethod (#/convert: :void) ((self converter-controller) sender)
197 (declare (ignore sender))
198 (let* ((conv (converter self))
199 (dollar-field (dollar-field self))
200 (rate-field (rate-field self))
201 (amount-field (amount-field self))
202 (dollars (#/floatValue dollar-field))
203 (rate (#/floatValue rate-field))
204 (amount (#/convertCurrency:atRate: conv dollars rate)))
205 (#/setFloatValue: amount-field amount)
206 (#/selectText: rate-field self)))
207 </pre>
208
209 <p>Just as in the Apple example, this method reads the dollar
210 and rate values, and passes them to the
211 "convertCurrency:atRate:" method of the Converter class. It then
212 sets the text of the amount-field to reflect the result of the
213 conversion. The only significant difference between this
214 implementation and Apple's is that the code is written in Lisp
215 rather than Objective-C.</p>
216
217 <p>This completes the definition of the CurrencyConverter's
218 behavior. All that remains is to actually build the Cocoa
219 application. The next section shows how to do that.</p>
220
221 </div>
222
223 <div class="nav">
224 <p><a href="../../HOWTO.html">start</a>|<a href="create_lisp.html">previous</a>|<a href="build_app.html">next</a></p>
225 </div>
226
227 </body>
228</html>
229
Note: See TracBrowser for help on using the repository browser.