source: trunk/ccl/examples/cocoa/currency-converter/HOWTO_files/pages/writing_lisp.html @ 7799

Last change on this file since 7799 was 7799, checked in by mikel, 13 years ago

various corrections to HOWTO; added section on IB 2.x

File size: 8.8 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 very simple&mdash;really, it just multiples
96      <code>currency</code> times <code>rate</code>. Most of the text in the definition is
97      Objective C bridge code that links the definition to the right
98      class with the right argument and return types.</p>
99
100      <p><code>objc:defmethod</code> is a version of DEFMETHOD that
101      creates Objective C method definitions.</p>
102
103      <p>The syntax <code>#/convertCurrency:atRate:</code> uses the
104      "#/" reader macro to read a symbol with case preserved, so that
105      you can see in your code the same name that Objective C uses for
106      the method, without worrying about how the name might be
107      converted between Lisp and Objective C conventions.</p>
108
109      <p>The number of arguments to an Objective C method is the
110      number of colons in the name, plus one. Each colon indicates an
111      argument, and there is always an extra "self" argument that
112      refers to the object that receives the message. These are normal
113      Objective C conventions, but we perhaps need to emphasize the
114      details, since we are using Lisp code to call the Objective C
115      methods.</p>
116
117      <p>We indicate the return type and the types of arguments in
118      the method definition by surrounding parameters and the method
119      name with parentheses, and appending the type name.</p> 
120
121      <p>Thus, for example, </p>
122
123      <pre>
124(#/convertCurrency:atRate: :float)
125      </pre>
126
127      <p>means that the return type of the method is :FLOAT, and </p>
128
129      <pre>
130(self converter)
131      </pre>
132
133      <p>means that the type of the receiving object is Converter.</p>
134     
135      <p>You will see these same conventions repeated in the next
136      section.</p>
137      </div>
138
139    <div class="section-head">
140      <h2>Defining the ConverterController Class</h2>
141    </div>
142
143    <div class="body-text">
144      <p>The previous section defined the Model class, Converter. All
145      we need now is a definition for the ConverterController
146      class. Recall from your reading of Apple's Tutorial that the
147      CurrencyConverter example uses the Model-View-Controller
148      paradigm. You used InterfaceBuilder to construct the
149      application's views. The Converter class provides the model
150      that represents application data. Now we define the controller
151      class, ConverterController, which connects the View and the
152      Model.</p>
153
154      <p>Here's the definition of the ConverterController class:</p>
155
156      <pre>
157(defclass converter-controller (ns:ns-object)
158  ((amount-field :foreign-type :id :accessor amount-field)
159   (converter :foreign-type :id :accessor converter)
160   (dollar-field :foreign-type :id :accessor dollar-field)
161   (rate-field :foreign-type :id :accessor rate-field))
162  (:metaclass ns:+ns-object))
163      </pre>
164     
165      <p>Once again we use the Objective C bridge to define an
166      Objective C class. This time, we provide several
167      instance-variable definitions in the class, and name accessors
168      for each of them explicitly. The <code>:FOREIGN-TYPE</code>
169      initargs enable us to specify the type of the field in the
170      foreign (Objective C) class.</p>
171
172      <p>Each field in the definition of the ConverterController class
173      is an outlet that will be used to store a reference to one of
174      the UI fields that you created in InterfaceBuilder. For
175      example, <code>amount-field</code> will be connected to the
176      "Amount" text field.</p> 
177
178      <p>Why did we spell the name "amount-field" in Lisp code, and
179      "amountField" when creating the outlet in InterfaceBuilder?  The
180      Objective C bridge automatically converts Lisp-style field names
181      (like "amount-field") to Objective C-style field names (like
182      "amountField"), when handling class definitions.</p>
183
184      <p>The <code>converter</code> field at launch time contains a
185      reference to the Converter object, whose class definition is in
186      the previous section.</p>
187
188      <p>The final piece of the implementation is a definition of the
189      "convert:" method. This is the method that is called when a
190      user clicks the "Convert" button in the user interface.</p>
191
192      <pre>
193(objc:defmethod #/convert: ((self converter-controller) sender)
194  (let* ((conv (converter self))
195         (dollar-field (dollar-field self))
196         (rate-field (rate-field self))
197         (amount-field (amount-field self))
198         (dollars (#/floatValue dollar-field))
199         (rate (#/floatValue rate-field))
200         (amount (#/convertCurrency:atRate: conv dollars rate)))
201    (#/setFloatValue: amount-field amount)
202    (#/selectText: rate-field self)))
203      </pre>
204
205      <p>Just as in the Apple example, this method reads the dollar
206      and rate values, and passes them to the
207      "convertCurrency:atRate:" method of the Converter class. It then
208      sets the text of the amount-field to reflect the result of the
209      conversion. The only significant difference between this
210      implementation and Apple's is that the code is written in Lisp
211      rather than Objective C.</p>
212
213      <p>This completes the definition of the CurrencyConverter's
214      behavior. All that remains is to actually build the cocoa
215      application. The next section shows how to do that.</p>
216
217    </div>
218
219    <div class="nav">
220      <p><a href="../../HOWTO.html">start</a>|<a href="create_lisp.html">previous</a>|<a href="build_app.html">next</a></p>
221    </div>
222
223  </body>
224</html>
225
Note: See TracBrowser for help on using the repository browser.