• Aucun résultat trouvé

IDL and GDL Syntax

Dans le document Basic Lisp Techniques (Page 64-68)

4.3.1 Defpart

Defpartis the basic Macro for defining Classes in IDL and GDL. The original meaning of “part”

refers to physical geometric parts, but here the meaning is extended to include any kind of Functional Object2. A part definition (Defpart) maps directly into a Lisp Class definition.

1ICAD is not to be confused with AutoCAD, a completely different product from a different company. And ICAD/IDL is not to be confused with CORBA’s Interface Definition Language, which is also known as “IDL.”

2AFunctional Object in this context refers to an entity which accepts someInputs and computes someOutputs, with the Outputs being uniquely determined based on a given set of Inputs.

4.3. IDL AND GDL SYNTAX 57 ThedefpartMacro takes three basic arguments:

• a name, which is a Symbol.

• a mixin-list, which is a List of Symbols naming other Defparts from which the current part will inherit characteristics.

• a specification-plist, which is spliced in (i.e. doesn’t have its own surrounding parentheses) after the Mixin-list, and describes the Object model by specifying Methods, contained Objects (aggregates), etc. The Specification-plist typically makes up the bulk of the Defpart.

Here are descriptions of the most common keywords making up the Specification-plist:

Inputs specify information to be passed into the Object instance when it is created.

Attributes are really cached Methods, with expressions to compute and return a value.

Parts specify other Instances to be “contained” within this instance.

Methods are (uncached) Methods “of” the Defpart, and can also take other non-specialized argu-ments, just like a normal Function.

Figure 4.1 shows a simple example, which contains two Inputs, :first-name and:last-name, and a single Attribute,:greeting. As you can see, adefpartis analogous in some ways to adefun,

(defpart hello ()

:inputs (:first-name :last-name) :attributes

(:greeting (format nil "Hello, ~a ~a!!" (the :first-name) (the :last-name))))

Figure 4.1: Example of Simple Defpart

where the Inputs are like arguments to the Function, and the Attributes are like return-values. But seen another way, each Attribute in adefpartis like a Function in its own right.

The referencing Macro “the” shadows CL’s “the” (which is a seldom-used type declaration operator). “The” in IDL and GDL is a Macro which is used toreferencethe value of other Messages within the same Defpart or within contained Defparts. In the above example, we are using “the”

to refer to the values of the Messages (Inputs) named:first-name and:last-name.

4.3.2 Making Instances and Sending Messages

Once we have defined a Defpart such as the example above, we can use the constructor Func-tion make-part in order to create an instance of it. This Function is very similar to the CLOS make-instanceFunction. Here we create an instance ofhellowith specified values for:first-name and:last-name(the required Inputs), and assign this instance as the value of the Symbolmypart:

GDL-USER(16): (setq mypart

(make-part ’hello :first-name "John"

:last-name "Doe"))

#<HELLO @ #x218f39c2>

58 CHAPTER 4. CL AS A CASE TOOL As you can see, the return value is an Instance of Classhello. Now that we have an Instance, we can use the Macrothe-object to send Messages to this Instance:

GDL-USER(17): (the-object mypart :greeting)

"Hello, John Doe!!"

The-objectis similar tothe, but as its first argument you must give an expression which evaluates to a part Instance. The, by contrast, assumes that the part instance is the lexical variable self, which is automatically set within the lexical context of a Defpart.

For convenience, you can also set self manually at the CL Command Prompt, and use the instead of the-objectfor referencing:

GDL-USER(18): (setq self

(make-part ’hello :first-name "John"

:last-name "Doe"))

#<HELLO @ #x218f406a>

GDL-USER(19): (the :greeting)

"Hello, John Doe!!"

In actual fact,(the ...) simply expands into(the-object self ...).

4.3.3 Parts

The “Parts” keyword specifies a List of “contained” Instances, where each instance is considered to be a “child” part of the current part. Each child Part is of a specified Type, which itself must be defined as a Defpart before the child part can be instantiated.

Inputs to each instance are specified as a Plist of Keywords and Value expressions, spliced in after the part’s name and type specification, which must match the Inputs protocol of the Defpart being instantiated. Figure 4.2 shows an example of a Defpart which contains some Parts. In this

(defpart city () :attributes

(:total-water-usage (+ (the :hotel :water-usage) (the :bank :water-usage))) :parts

((:hotel :type ’hotel :size :large) (:bank :type ’bank

:size :medium)))

Figure 4.2: Defpart Containing Child Parts

example, hotel and bank are presumed to be already (or soon) defined as Defparts themselves, which each answer the:water-usageMessage. Thereference chains:

4.3. IDL AND GDL SYNTAX 59 (the :hotel :water-usage)

and

(the :bank :water-usage)

provide the mechanism to access Messages within the child part Instances.

These child parts become instantiated on demand, meaning that the first time these instances or any of their Messages are referenced, the actual instance will be createdand cached for future reference.

4.3.4 Quantified Parts

Parts may bequantified, to specify, in effect, an Array or List of part Instances. The most common type of Quantification is called:seriesquantification. See Figure 4.3 for an example of a Defpart

(defparameter *presidents-data*

’((:name

"Carter"

:term 1976) (:name "Reagan"

:term 1980) (:name "Bush"

:term 1988) (:name "Clinton"

:term 1992)))

(defpart presidents-container () :optional-inputs

(:data *presidents-data*) :parts

((:presidents :type ’president

:quantify (:series (length (the :data))) :parameters (the :data))))

Figure 4.3: Sample Data and Defpart to Contain U.S. Presidents

which contains a quantified set of Instances representing U.S. presidents. Each member of the quan-tified set is fed inputs from a List of Plists, which simulates a relational database table (essentially a “List of Rows”).

Note the following from this example:

• in order to quantify a Part, the additional Input keyword :quantify is added, with a List consisting of the keyword:seriesfollowed by an expression which must evaluate to a Number.

• The special Parts keyword :parameters allows you to pass a List of Plists directly as the Inputs to a quantified set of child parts. This will also work for passing a single Plist into a non-quantified Part.

60 CHAPTER 4. CL AS A CASE TOOL

• The Keyword :optional-inputs is used, which is a hybrid of :attributes and :inputs, allowing a default expression as with :attributes, but allowing a value to be passed in on instantiation or from the parent, as with:inputs. A passed-in value will override the Default Expression.

Dans le document Basic Lisp Techniques (Page 64-68)

Documents relatifs