1 <!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Strict//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3 <html xmlns=
"http://www.w3.org/1999/xhtml"
4 lang=
"en" xml:
lang=
"en">
6 <title>Lisp on Lines : The Missing Manual.
</title>
7 <meta http-equiv=
"Content-Type" content=
"text/html;charset=iso-8859-1"/>
8 <meta name=
"generator" content=
"Org-mode"/>
9 <meta name=
"generated" content=
"2009/07/27 01:46:25 PM"/>
10 <meta name=
"author" content=
"Drew Crampsie"/>
11 <style type=
"text/css">
13 font-family: Times
, serif
;
16 .title { text-align: center
; }
18 .done { color: green
; }
19 .timestamp { color: grey
}
20 .timestamp-kwd { color: CadetBlue
}
21 .tag { background-color:lightblue
; font-weight:normal
}
24 border: 1pt solid
#AEBDCC;
25 background-color: #F3F5F7;
27 font-family: courier
, monospace
;
30 table
{ border-collapse: collapse
; }
33 <!--border: 1pt solid
#ADB9CC;-->
35 dt
{ font-weight: bold
; }
38 <h1 class=
"title">Lisp on Lines : The Missing Manual.
</h1>
39 <i>Abstract
</i>: Lisp on Lines is a Common Lisp based framework for rapid
40 development of data-driven applications. It is particularly useful
41 for producing Web based applications, but is also useful elsewhere.
45 <div id=
"table-of-contents">
46 <h2>Table of Contents
</h2>
47 <div id=
"text-table-of-contents">
49 <li><a href=
"#sec-1">1 Introduction
</a></li>
50 <li><a href=
"#sec-2">2 Installation
</a></li>
51 <li><a href=
"#sec-3">3 Describing the domain with the MAO protocol.
</a>
53 <li><a href=
"#sec-3.1">3.1 Descriptions
</a></li>
54 <li><a href=
"#sec-3.2">3.2 Attributes and Properties
</a></li>
55 <li><a href=
"#sec-3.3">3.3 Contexts
</a></li>
58 <li><a href=
"#sec-4">4 Defining and Using Descriptions
</a>
60 <li><a href=
"#sec-4.1">4.1 Defining a simple description
</a></li>
61 <li><a href=
"#sec-4.2">4.2 Using descriptions as and with contexts.
</a></li>
62 <li><a href=
"#sec-4.3">4.3 T : The root of all descriptions.
</a></li>
63 <li><a href=
"#sec-4.4">4.4 DESCRIPTION-OF : Permanently Associate a description with a class.
</a></li>
66 <li><a href=
"#sec-5">5 The DISPLAY Protocol
</a></li>
67 <li><a href=
"#sec-6">6 Automatic Descriptions for CLOS classes.
</a>
69 <li><a href=
"#sec-6.1">6.1 Described CLOS objects an the EDITABLE description
</a></li>
70 <li><a href=
"#sec-6.2">6.2 Extending the generated description
</a></li>
73 <li><a href=
"#sec-7">7 Using Lisp-on-Lines for the Web.
</a></li>
78 <div id=
"outline-container-1" class=
"outline-2">
79 <h2 id=
"sec-1">1 Introduction
</h2>
84 Lisp on Lines (LoL) is a framework for rapid development of data-driven
85 applications, with a particular focus on web-based applications. It
86 builds on the UncommonWeb engine and Contextl, and uses CLOS and the
87 MOP extensively. Most of LoL can be used both at the REPL and through
88 the browser, offering many options for development and testing.
91 While the target audience for LoL is developers experienced with both
92 web technologies and common lisp, a good programmer with a little
93 experience in either should be able to pick things up fairly quickly.
99 <div id=
"outline-container-2" class=
"outline-2">
100 <h2 id=
"sec-2">2 Installation
</h2>
105 LoL has a load of dependencies, which themselves depend on others,
106 etc. The best way to deal with this is to use
<a href=
"http://common-lisp.net/project/clbuild/">clbuild
</a>, a library
110 If you'd prefer to manage your libraries manually, the dependencies,
111 according to clbuild, are :
114 alexandria arnesi bordeaux-threads cl-base64 cl-fad cl-mime cl-ppcre
115 cl-qprint closer-mop contextl iterate lift local-time lw-compat
116 net-telent-date parenscript parse-number portable-threads puri rfc2109
117 slime split-sequence trivial-garbage ucw usocket yaclml
120 All libraries should be installed from version control where available.
126 <div id=
"outline-container-3" class=
"outline-2">
127 <h2 id=
"sec-3">3 Describing the domain with the MAO protocol.
</h2>
132 LoL uses a protocol it calls Meta-Attributed Objects, or MAO, as the
133 basis of its display mechanism. In MAO, we create context-aware
134 DESCRIPTIONs of objects, and those descriptions are used to generate
135 the display of the object itself. By having these external
136 descriptions change based on the context in which they are used, a few
137 generic components can come together to create complex interfaces.
142 <div id=
"outline-container-3.1" class=
"outline-3">
143 <h3 id=
"sec-3.1">3.1 Descriptions
</h3>
146 <p>Descriptions are a similar conceptually to classes. Every Lisp object
147 has one, and the root description that all descriptions inherit from
148 is known as T. FIND-DESCRIPTION is used to, well, find descriptions.
152 <pre class=
"src"> (find-description t)
153 =
> #
<DESCRIPTION T {B7B9861}
>
161 <div id=
"outline-container-3.2" class=
"outline-3">
162 <h3 id=
"sec-3.2">3.2 Attributes and Properties
</h3>
165 <p>A description is a collection of ATTRIBUTEs, among other things. Each
166 attribute describes a part of an object, and any number of attributes
167 may or may not be active. The ATTRIBUTES function is used to find a
168 the list attributes that are both active and applicable in the current
173 <pre class=
"src">(attributes (find-description t))
174 =
>(#
<ATTRIBUTE IDENTITY {BBC9691}
>
175 #
<ATTRIBUTE TYPE {BBC96A1}
>
176 #
<ATTRIBUTE CLASS {BBC96B1}
>)
181 The functions DESCRIPTION-ATTRIBUTES, DESCRIPTION-ACTIVE-ATTRIBUTES
182 and DESCRIPTION-CURRENT-ATTRIBUTES return all the descriptions
183 attributes, Attributes that are currently active regardless of
184 context, and attributes that exist in the current context but may or
185 may not be active, respectively.
188 Attributes have properties, for example ATTRIBUTE-LABEL and
189 ATTRIBUTE-VALUE. By simply iterating through the attributes of a
190 described object, we can create a generic display for any lisp
191 object. This is very similar, and was inspired by the technique
192 outlined by Adrian Lienhard in
<a href=
"http://www.adrian-lienhard.ch/files/mewa.pdf">MEWA: A Meta-level Architecture for Generic Web-Application Construction_
</a>.
196 For attribute properties to be useful, the description must be
197 associated with the object it is meant to describe.
200 The function FUNCALL-WITH-DESCRIBED-OBJECT takes care of setting up
201 the proper context. There is some syntax for it in the form of
202 WITH-DESCRIBED-OBJECT :
207 (
<span style=
"color: #a020f0;">let
</span> ((description (find-description t))
208 (object
<span style=
"color: #bc8f8f;">"Hello World"</span>))
209 (
<span style=
"color: #a020f0;">with-described-object
</span> (object description)
210 (
<span style=
"color: #a020f0;">dolist
</span> (a (attributes description))
211 (format t
<span style=
"color: #bc8f8f;">"~@[~A: ~]~A~%"</span>
213 (attribute-value a)))))
216 Type: (SIMPLE-ARRAY CHARACTER (
11))
217 Class: #
<BUILT-IN-CLASS SB-KERNEL::SIMPLE-CHARACTER-STRING
>
224 FUNCALL-WITH-DESCRIBED-OBJECT binds two specials,
<b>DESCRIPTION
</b> and
225 <b>OBJECT
</b>, to its arguments. Knowing this, we can shorten our code
226 somewhat. Later on we'll be far away from the lexical bindings of
227 description and object, so these special variables are essential.
230 Another reason for the
<b>description
</b> variable is that
231 WITH-DESCRIBED-OBJECT will use DESCRIPTION-OF to determine the
232 description if the DESCRIPTION argument is NIL
236 <pre class=
"src">(
<span style=
"color: #a020f0;">with-described-object
</span> (
<span style=
"color: #bc8f8f;">"Hello World"</span> nil)
237 (
<span style=
"color: #a020f0;">dolist
</span> (a (attributes *description*))
238 (format t
<span style=
"color: #bc8f8f;">"~@[~A: ~]~A~%"</span>
240 (attribute-value a))))
242 Lets wrap that up in a function that we can re-use. LoL includes an
243 entire DISPLAY mechanism that is slightly more involved, but this
244 serves as an excellent example with not bogging us down in details.
246 <span style=
"color: #b22222;">#+BEGIN_SRC lisp
</span>
247 (
<span style=
"color: #a020f0;">defun
</span> <span style=
"color: #0000ff;">present
</span> (object
<span style=
"color: #228b22;">&optional
</span> description)
248 (
<span style=
"color: #a020f0;">with-described-object
</span> (object description)
249 (
<span style=
"color: #a020f0;">dolist
</span> (a (attributes *description*))
250 (format t
<span style=
"color: #bc8f8f;">"~@[~A: ~]~A~%"</span>
252 (attribute-value a)))))
260 <div id=
"outline-container-3.3" class=
"outline-3">
261 <h3 id=
"sec-3.3">3.3 Contexts
</h3>
266 MAO adds to MEWA the concept of dynamic context. By changing the
267 context in which an object is described, we combine and specialize the
268 generic displays, ultimately creating different views of our
269 objects. LoL uses ContextL extensively. Descriptions are contextl
270 layers, and attributes themselves are layered classes. Most of the
271 exported functions are layered methods, and the idea of dynamic
272 context-sensitivity is used throughout LoL. If you're not familiar
273 with contextl, don't worry, LoL mostly stands on its own. Still,
274 reading through the material on contextl won't hurt.
277 Descriptions may have different attributes dependant on what
278 description contexts (or layers) are currently active. Attributes
279 themselves might have different properties.
282 When an object is being described (using WITH-DESCRIBED-OBJECT), it is
283 also activated as a layer context. One can also activate/deactivate
284 contexts manually, using WITH-ACTIVE-DESCRIPTIONS and
285 WITH-INACTIVE-DESCRIPTIONS.
288 Hopefully a little code will make this more clear :
292 <pre class=
"src">(present
<span style=
"color: #bc8f8f;">"Hello World"</span>)
295 Type: (SIMPLE-ARRAY CHARACTER (
11))
296 Class: #
<BUILT-IN-CLASS SB-KERNEL::SIMPLE-CHARACTER-STRING
>
297 Simple character string
299 <span style=
"color: #b22222;">;;
</span><span style=
"color: #b22222;">Now we'll activate a built-in description, INLINE.
301 (
<span style=
"color: #a020f0;">with-active-descriptions
</span> (
<span style=
"color: #a020f0;">inline
</span>)
302 (present
<span style=
"color: #bc8f8f;">"Hello World"</span>))
309 You can see that the behavior of PRESENT changed when the INLINE
310 context was activated. This is the key innovation that makes LoL so
311 useful. In the next chapter we'll create our own descriptions and
312 demonstrate this further.
319 <div id=
"outline-container-4" class=
"outline-2">
320 <h2 id=
"sec-4">4 Defining and Using Descriptions
</h2>
327 <div id=
"outline-container-4.1" class=
"outline-3">
328 <h3 id=
"sec-4.1">4.1 Defining a simple description
</h3>
331 <p>The basics of the MAO should now (hopefully) be clear, so lets start
332 using it. First, we'll create our very own description.
336 <pre class=
"src">(
<span style=
"color: #a020f0;">define-description
</span> hello-world ()
337 ((title
<span style=
"color: #da70d6;">:value
</span> <span style=
"color: #bc8f8f;">"Lisp on Lines Demo"</span>)
338 (identity
<span style=
"color: #da70d6;">:label
</span> <span style=
"color: #bc8f8f;">"Message"</span>)
339 (length
<span style=
"color: #da70d6;">:label
</span> <span style=
"color: #bc8f8f;">"Length"</span> <span style=
"color: #da70d6;">:function
</span> #'length)
340 (active-attributes
<span style=
"color: #da70d6;">:value
</span> '(title identity length))))
345 Descriptions are defined very much like CLOS classes, and are in fact
346 implemented that way, inheritance rules apply. The object returned
347 from FIND-DESCRIPTION is best described as a prototype-based
348 singleton. In other words, there is only one instance, and it inherits
349 attributes and properties from further up its hierarchy unless
350 specifically overridden.
353 Attributes can have any number of properties, (see the class
354 STANDARD-ATTRIBUTE), but the three most important are accessed via the
355 methods ATTRIBUTE-LABEL, ATTRIBUTE-VALUE and ATTRIBUTE-FUNCTION,and
356 named (in DEFINE-DESCRIPTION forms and elsewhere)
357 by the :label, :value, and :function keywords.
360 ATTRIBUTE-LABEL is simply a textual label that describes the
361 attribute. ATTRIBUTE-VALUE is defined to return the result of calling
362 ATTRIBUTE-FUNCTION with the object as its argument. If
363 ATTRIBUTE-FUNCTION is NIL, the value of the :value property is returned
367 In the example above, the IDENTITY and ACTIVE-ATTRIBUTES attributes
368 are inherited from T, and we are simply overriding the default
369 properties for our description. LENGTH and TITLE are specific to this
370 description. A look at src/standard-descriptions/t.lisp may be
371 instructive at this point.
374 Now, we can present our object using our new description.
378 <pre class=
"src">(present
<span style=
"color: #bc8f8f;">"Hello World"</span> (find-description 'hello-world))
392 <div id=
"outline-container-4.2" class=
"outline-3">
393 <h3 id=
"sec-4.2">4.2 Using descriptions as and with contexts.
</h3>
398 A we mentioned earlier, when an object is being described, the
399 'description context' is also made active. On top of that, one can
400 define partial descriptions that are only active when other
401 description contexts have been activated.
404 We'll make a ONE-LINE description similar to the INLINE description
405 demonstrated earlier.
409 <pre class=
"src">(
<span style=
"color: #a020f0;">define-description
</span> one-line ())
411 (
<span style=
"color: #a020f0;">define-description
</span> hello-world ()
412 ((identity
<span style=
"color: #da70d6;">:label
</span> nil)
413 (active-attributes
<span style=
"color: #da70d6;">:value
</span> '(identity)))
414 (
<span style=
"color: #da70d6;">:in-description
</span> one-line))
420 Here we've defined a new description, ONE-LINE, and a
421 context-sensitive extension to our HELLO-WORLD description. This
422 partial desription will be active only when in the context of a
423 one-line description. One can have attributes that only exist in
424 certain description contexts, and attributes can have different
429 <pre class=
"src">(
<span style=
"color: #a020f0;">let
</span> ((message
<span style=
"color: #bc8f8f;">"Hello World!"</span>)
430 (description (find-description 'hello-world)))
431 (print
<span style=
"color: #da70d6;">:normal
</span>)(terpri)
432 (present message description)
433 (print
<span style=
"color: #da70d6;">:one-line
</span>)(terpri)
434 (
<span style=
"color: #a020f0;">with-active-descriptions
</span> (one-line)
435 (present message description)))
437 <span style=
"color: #da70d6;">:NORMAL
</span>
439 Message: Hello World!
442 <span style=
"color: #da70d6;">:ONE-LINE
</span>
450 By activating the description ONE-LINE, we've changed the context in
451 which our object is displayed. We can create any number of
452 descriptions and contexts and activate/deactivate them in any order.
455 Descriptions are implemented as ContextL 'layers', so if all
456 this seems weird, reading the ContextL papers might help.
462 <div id=
"outline-container-4.3" class=
"outline-3">
463 <h3 id=
"sec-4.3">4.3 T : The root of all descriptions.
</h3>
468 Because all descriptions inherit from T, we can define contexts for T
469 and they will apply to every description. The INLINE description can
470 be found in standard-descriptions/inline.lisp, where we define
471 a desription for T in the context of the INLINE description :
475 <pre class=
"src"><span style=
"color: #b22222;">;;
</span><span style=
"color: #b22222;">Defined by LoL in inline.lisp :
476 </span>(
<span style=
"color: #a020f0;">define-description
</span> t ()
477 ((identity
<span style=
"color: #da70d6;">:label
</span> nil)
478 (active-attributes
<span style=
"color: #da70d6;">:value
</span> '(identity))
479 (attribute-delimiter
<span style=
"color: #da70d6;">:value
</span> <span style=
"color: #bc8f8f;">", "</span>)
480 (label-formatter
<span style=
"color: #da70d6;">:value
</span> (curry #'format nil
<span style=
"color: #bc8f8f;">"~A: "</span>))
481 (value-formatter
<span style=
"color: #da70d6;">:value
</span> (curry #'format nil
<span style=
"color: #bc8f8f;">"~A"</span>)))
482 (
<span style=
"color: #da70d6;">:in-description
</span> inline))}
488 The does for the LoL DISPLAY mechanism what ONE-LINE did for PRESENT,
489 only with more magic. By exetending T in this way, it's easy to create
490 contexts the redefine the behavior of LoL while still reusing the basics.
496 <div id=
"outline-container-4.4" class=
"outline-3">
497 <h3 id=
"sec-4.4">4.4 DESCRIPTION-OF : Permanently Associate a description with a class.
</h3>
502 The LAYERED-FUNCTION DESCRIPTION-OF will return the description
503 associated with an object.
510 #
<DESCRIPTION NULL {AA04F49}
>
514 #
<DESCRIPTION SYMBOL {AA04541}
>
516 (description-of '(
1 2 3))
518 #
<DESCRIPTION CONS {AA04C29}
>
520 <span style=
"color: #b22222;">;;
</span><span style=
"color: #b22222;">etc
530 <div id=
"outline-container-5" class=
"outline-2">
531 <h2 id=
"sec-5">5 The DISPLAY Protocol
</h2>
536 Our function, PRESENT, is very basic, though pretty powerful when
537 combined with descriptions and contexts. LoL includes a superset of
538 such functionality built-in.
541 The main entry point into this protocol is the DISPLAY
542 function. The signature for this functions is :
546 <pre class=
"src">(display DISPLAY OBJECT
<span style=
"color: #228b22;">&REST
</span> ARGS
<span style=
"color: #228b22;">&KEY
</span> DEACTIVATE ACTIVATE
<span style=
"color: #228b22;">&ALLOW-OTHER-KEYS
</span>)
551 The first argument, DISPLAY, is the place where we will display
552 to/on/in/with. It could be a stream, a UCW component, a CLIM gadget,
553 or anything else you might want to use.
556 One can specialize on this argument (though it's better to specialize
557 DISPLAY-USING-DESCRIPTION
… more on that later) to use generic
558 descriptions to display objects in different environments.
561 The second argument is simply the object to be displayed. Here's a
566 <pre class=
"src">(display t t)
570 Class:#
<BUILT-IN-CLASS SYMBOL
>
574 Package:#
<PACKAGE
<span style=
"color: #bc8f8f;">"COMMON-LISP"</span>>
575 Function:
<UNBOUND
>
576 <span style=
"color: #b22222;">;
</span><span style=
"color: #b22222;">No value
581 The two arguments specified in the lambda-list, ACTIVATE and
582 DEACTIVATE, are used to activate and deactivate description contexts in
583 the scope of the display function.
588 (display nil t
<span style=
"color: #da70d6;">:activate
</span> '(
<span style=
"color: #a020f0;">inline
</span>))
590 <span style=
"color: #bc8f8f;">"t"</span>
591 (
<span style=
"color: #a020f0;">with-active-descriptions
</span> (
<span style=
"color: #a020f0;">inline
</span>)
592 (display nil t
<span style=
"color: #da70d6;">:deactivate
</span> '(
<span style=
"color: #a020f0;">inline
</span>)))
594 <span style=
"color: #bc8f8f;">"T
596 Class:#<BUILT-IN-CLASS SYMBOL>
600 Package:#<PACKAGE \"COMMON-LISP\
">
601 Function:<UNBOUND>"</span>
607 Any other keyword arguments passed will be used to set the value of an
608 attribute with a :keyword property, in the dynamic context of the
609 DISPLAY function call. Once such attribute, and a very useful one is
610 ACTIVE-ATTRIBUTES with its :attributes keyword :
615 (display t t
<span style=
"color: #da70d6;">:attributes
</span> '(class package))
617 Class:#
<BUILT-IN-CLASS SYMBOL
>
618 Package:#
<PACKAGE
<span style=
"color: #bc8f8f;">"COMMON-LISP"</span>>
624 The properties of attributes that do not have a :keyword property can
625 also be set dynamically. Since :attributes is the :keyword property of
626 the ACTIVE-ATTRIBUTES attribute, the following form is equivalent to
631 <pre class=
"src">(display t t
<span style=
"color: #da70d6;">:attributes
</span> '((active-attributes
632 <span style=
"color: #da70d6;">:value
</span> (class package))))
634 Class:#
<BUILT-IN-CLASS SYMBOL
>
635 Package:#
<PACKAGE
<span style=
"color: #bc8f8f;">"COMMON-LISP"</span>>
640 Setting the attributes this way is almost like creating an anonymous
641 description context
… you can express just about anything you would
642 in a DEFINE-DESCRIPTION. Here's a more involved example :
646 <pre class=
"src">(display t t
<span style=
"color: #da70d6;">:attributes
</span> `((identity
<span style=
"color: #da70d6;">:label
</span> <span style=
"color: #bc8f8f;">"The Object"</span>)
647 (class
<span style=
"color: #da70d6;">:label
</span> <span style=
"color: #bc8f8f;">"CLOS Class"</span>)
648 (package
<span style=
"color: #da70d6;">:value
</span> <span style=
"color: #bc8f8f;">"COMMON LISP"</span> <span style=
"color: #da70d6;">:function
</span> nil)
649 (type
<span style=
"color: #da70d6;">:value-formatter
</span>
650 ,(
<span style=
"color: #a020f0;">lambda
</span> (a)
651 (format nil
<span style=
"color: #bc8f8f;">"Got a value? ~A"</span> a)))))
655 CLOS Class:#
<BUILT-IN-CLASS SYMBOL
>
657 Type:Got a value? BOOLEAN
663 I hope that serves well to demonstrate the concepts behind LoL, as
664 there is no API documentation available at the moment
… use the
672 <div id=
"outline-container-6" class=
"outline-2">
673 <h2 id=
"sec-6">6 Automatic Descriptions for CLOS classes.
</h2>
678 Lisp-on-Lines includes a compose-able metaclass, DESCRIBED-CLASS. It
679 can be combined with
<u>any
</u> other metaclass without affecting the
680 behavior of that class. DESCRIBED-CLASS has been used with the
681 metaclasses provided by CLSQL, ROFL, Rucksack and UCW simply by
682 defining a class that inherits from both metaclasses.
685 DESCRIBED-CLASS creates a base description for the class, named
686 DESCRIPTION-FOR-
<class
>, and another description with the same name
687 as the class that has the previous description as a superclass. The
688 then defines a method on DESCRIPTION-OF that returns the second
692 LoL includes DESCRIBED-STANDARD-CLASS, which is subclass of
693 STANDARD-CLASS and DESCRIBED-CLASS. We'll use this to create a class
699 (
<span style=
"color: #a020f0;">defclass
</span> <span style=
"color: #228b22;">person
</span> ()
700 (first-name last-name company-name
701 date-of-birth phone fax email
702 address city province postal-code)
703 (
<span style=
"color: #da70d6;">:metaclass
</span> described-standard-class))
705 #
<DESCRIBED-STANDARD-CLASS PERSON
>
707 (display t (make-instance 'person))
709 First name:#
<UNBOUND
>
710 Last name:#
<UNBOUND
>
711 Company name:#
<UNBOUND
>
712 Date of birth:#
<UNBOUND
>
713 Phone:#
<UNBOUND
>
715 Email:#
<UNBOUND
>
716 Address:#
<UNBOUND
>
717 City:#
<UNBOUND
>
718 Province:#
<UNBOUND
>
719 Postal code:#
<UNBOUND
>
727 <div id=
"outline-container-6.1" class=
"outline-3">
728 <h3 id=
"sec-6.1">6.1 Described CLOS objects an the EDITABLE description
</h3>
733 The slots of an object are SETF'able places, and LoL takes
734 advantage of that to provide EDITABLE descriptions
735 automatically. When the EDITABLE description is active, and editor
736 will be presented. The REPL based editor is pretty basic, but still
737 useful. The HTML based editor will be described later.
742 <pre class=
"src">(
<span style=
"color: #a020f0;">defun
</span> <span style=
"color: #0000ff;">edit-object
</span> (object
<span style=
"color: #228b22;">&rest
</span> args)
743 (
<span style=
"color: #a020f0;">with-active-descriptions
</span> (editable)
744 (apply #'display t object args)))
746 (
<span style=
"color: #a020f0;">let
</span> ((object (make-instance 'person)))
751 <span style=
"color: #b22222;">;;
</span><span style=
"color: #b22222;">What follows are prompts and the information i entered
757 Company name:The Tech Co-op
759 Date of birth:
1978-
07-
31
765 Email:drewc@tech.coop
767 Address:s/v Kanu, Lower Fraser River
775 <span style=
"color: #b22222;">;;
</span><span style=
"color: #b22222;">And this is what was displayed.
779 Company name:The Tech Co-op
780 Date of birth:
1978-
07-
31
783 Email:drewc@tech.coop
784 Address:s/v Kanu, Lower Fraser River
795 <div id=
"outline-container-6.2" class=
"outline-3">
796 <h3 id=
"sec-6.2">6.2 Extending the generated description
</h3>
801 We mentioned earlier that DESCRIBED-CLASS creates two descriptions :
806 (find-description 'description-for-person)
808 #
<DESCRIPTION DESCRIPTION-FOR-PERSON {D296DE1}
>
810 (find-description 'person)
812 #
<DESCRIPTION PERSON {ADFEDB1}
>
814 (description-of (make-instance 'person))
816 #
<DESCRIPTION PERSON {ADFEDB1}
>
823 The reason for this is so we can redefine the description PERSON while
824 keeping all the generated information from DESCRIPTION-FOR-PERSON.
827 In this case, we will add an attribute, PERSON-AGE, that calculates
828 a persons age based on the data in the date-of-birth slot.
847 <div id=
"outline-container-7" class=
"outline-2">
848 <h2 id=
"sec-7">7 Using Lisp-on-Lines for the Web.
</h2>
853 LoL was developed, and is primarily used, for implementing
854 data-driven web applications. As such, it comes with a host of
855 features for doing just that.
858 LoL, by default, implements its web portion on top of the wonderful
859 UnCommon Web meta-framework. The LISP-ON-LINES-UCW ASDF system
860 should be loaded, as it provides the features we're going to
879 <div id=
"postamble"><p class=
"author"> Author: Drew Crampsie
880 <a href=
"mailto:Drew Crampsie <drewc@tech.coop>"><Drew Crampsie
<drewc@tech.coop
>></a>
882 <p class=
"date"> Date:
2009/
07/
27 01:
46:
25 PM
</p>
883 <p>HTML generated by org-mode
6.05 in emacs
22<p>