Kapitel 6

Lisp III: Funktionen und Kontrollstrukturen


6.1 Evaluation

The basic unit of evaluation in LISP is an expression. An expression is a sentence in Lisp and it can be a value, a symbol, or a list. It is the basic unit which the LISP interpreter evaluates in one step.

What is a lambda expression?

A lambda expression has a list of parameters, and a body which consists of a sequence of expressions. The list of parameters defines the environment in which the expressions are to be evaluated. Lambda calculus, introduced by Alonzo Church in 1941, led to the development of LISP and functional programming. A lambda expression, explained below, is similar to the defun construct introduced in Kapitel 4. It is useful when you need to use a procedure in only one or very few places in a program and you do not want to define a special procedure by a unique name.

Every LISP expression that you enter from the keyboard is evaluated, and the result of evaluation process is returned. The AutoLisp environment also has a LISP interpreter- sometimes called an evaluator, and it works as follows:

Although this process may look complicated, it is possible to define an interpreter for the LISP language in LISP itself!

6.2 Functions and Special Forms

(lambda ....)
lambda is a special form. None of its arguments are evaluated. It returns a lambda expression which can be applied to a number of arguments.
(defun ...)
defun is a special form. None of its argument are evaluated. It assigns a lambda expression to its first argument.
(defun a (x)(+ x x)) is equivalent to:
(setq a (lambda (x)(+ x x))) in AutoLISP.
(eval )
eval is a function, it applies an extra evaluation to and returns the result.
(eval 2) --> 2
(eval +(+ 1 2)) -->
(quote )
quote is a special form, it is an evaluation blocker and returns without any evaluation.
'
A quote character followed by is an abbreviation of (quote ).
(setq a 2) --> 2
(eval +a) -->
(eval (eval +a)) -->
(eval +(+ a 4)) -->
(eval (list ++ +a 4)) -->
(setq )
setq is a special form. The first argument should be a symbol which will not be evaluated and is assigned with the value of the second argument.
(set )
set is a function. The value of the second argument is assigned to the result of the evaluation of the first argument.
(setq a +b) --> B
(set a 3) -->
!a -->
!b -->
(apply )
apply is a function. It applies a function to the and returns the result of the application.
(apply ++ +(1 2 3 4)) --> 10
(apply +* +(1 2 3 4)) -->
(apply +max +(2 4 3 8)) -->
(mapcar ....)
mapcar is a function. It applies a function to each element in the list(s) and returns a list of the results of every application.
(mapcar +numberp +(a 3 b 2 4 c)) --> (nil T nil T T nil)
(mapcar +- +(2 4 6 8) +(1 3 5 7)) -->
(mapcar +car +((x1 y1)(x2 y2)(x3 y3))) -->
(mapcar +(lambda (x)(* 2 x)) +(1 2 3 4)) -->
Further Examples:
    (defun average (alist)
      (/ (apply ++ alist) (length alist))

    --> AVERAGE

    (average +(2 4 6 8)) -->

    (defun dotproduct (v1 v2)
      (apply ++ (mapcar +* v1 v2))

    ) -->

    (dotproduct +(1 2 3) +(2 3 4)) -->
Notice that with argument passing conventions, you can develop and write general purpose LISP functions and reuse them later on.

6.3 Conditionals

6.3.1 if-then-else

In the examples presented so far, expressions are evaluated as they are passed to the interpreter. A series of expressions can be evaluated one after another one as in case of functions. This is a purely sequential control. In situations when we need to perform different actions depending on the context, a conditional control structure is needed. In LISP this can be expressed as if-then-else construct.

    (if some_logical_expression_is true
      then_do_something
    )
If there are only two choices, this form can be extended to:
    (if some_logical_expression_is true
      then_do_something
      else_do_something_else
    )
Example: Condition- If a user enters 0 then quit the program, else print a message.
    (defun test1_if (user_input)
      (if (= user_input 0)
        (princ "Do THEN action- QUIT the program!")
        (princ "Do ELSE action."))
    )
    (test1_if 0) -->
    (test1_if 999) -->
If more than one expressions are to be specified in either THEN or ELSE part, following form using progn is needed:
    (defun test2_if (user_input)
      (if (= user_input 0)
        (progn
          (princ "Do THEN action 1.")
          (princ "Do THEN action 2."))
          (princ "Do ELSE action."))
      )
    (test2_if 0) -->
    (test2_if 12) -->
Alternately, you can write a separate function instead of using progn and insert the function call in its place.

6.3.2 cond

If there are a number of conditions and corresponding actions which need to be expressed, a more useful form of conditional construct is cond:
    (cond ((if_condition1_is_true then_do_action1)
      (if_condition2_is_true then_do_action2)
        .....
        (t then_do_action))
The LISP interpreter evaluates the condition part of each statement one after another. If only an expression is found to be true, its then part is evaluated. Note the last condition which uses only t; it means if no other condition in previous statements evaluated as true, only then do this action. It is a good practise to include such t condition.
    (defun test_cond (user_input)
      (cond ((= user_input 0)
          (princ "Zero"))
        ((= user_input 1)
          (princ "One."))
        ((= user_input 2)
          (princ "Two."))
        (t (princ "Everything else!")))
    )
    (test_cond -1) -->
    (test_cond 2) -->
    (test_cond 0) -->

6.4 Uebung 6

In this exercise, you will make use of conditional expressions to write a small interactive program. In order to get you started, a sample program is provided in which you will also see how to use three AutoLisp functions: getint, getreal, getpoint. These functions allow you to get input from a user which may be an integer or a floating-point number entered from the keyboard, or a point which may be entered as (x y z) coordinates from the keyboard or picked directly on screen with the mouse.

Your task is to write a program which does the following. It prompts the user to input four points using which a building outline is drawn. A user should be able to specify height for the building. Further, your program prompts the user for selection of a roof type where the choices are signified by an integer 1, 2 or 3. These choices correspond to the roof types shown in the following figure. In order to draw the gable or hip roofs, you will need to prompt the user for the height of the roof. Assume any other variable you may need for the geometry of the roof. The fourth roof type, Mansard, is optional.

You should write small functions first, testing various parts of what your program needs to do. Once you have them working properly, combine them into a final version.

In order to get started on your program, copy the file 06_name.lsp from directory /homes2/prog/ausgabe into your account. Load it into AutoCad and evaluate each function to see what it does. Then modify and add functions that you need for this exercise. Save your final version as 06_name.lsp and submit it by copying it in directory /homes2/prog/ausgabe.


To the next chapter

Prog Content Vorwort ..1.. ..2.. ..3.. ..4.. ..5.. ..6.. ..7.. ..8.. ..9.. ..10.. ..11.. ..12.. ..13.. Appendix


@ by Architektur und CAAD 1994.......... The Teacher Team