3.6. Functions


A Lush function is an unnamed object which defines how to evaluate a list whose first element evaluates to this function. Functions are usually stored in the value field of a symbol usually referred to as the function name.

There are thus two equivalent ways to define a function named square which computes the square of its argument:

(setq square (lambda(x) (* x x)))

or

(de square(x) (* x x))

The evaluation of the list (lambda...) returns a function that setq stores into symbol square . The function de is a shorthand for this manipulation.

A function behaves as any atom does. Its class however defines how to evaluate a list whose first element evaluation returns that function. The evaluation of a list whose first element is a symbol, the value of which is a function, thus simply calls that function. The evaluation of the following list then returns 25

 (square 5)

But the evaluation of the following list also returns 25

 ((lambda(x) (* x x)) 5)

There are several kinds of functions in Lush; briefly described hereafter:



3.6.0. Argument List


A formal argument list is associated to each each Lush function (i.e. DE, DF, DM or DMD) This argument list defines which symbols will be bound to the actual argument of the function, while evaluating its body.

Valid formal argument lists may be a single symbol, a list of symbols, or something more complex like (a b (c d) . f) , or (a b &optional c d) .

If the formal argument list is a single symbol, it will be bound to the list of arguments when the function is called.

If the formal argument list is a list, its ``car'' will be matched against the ``car'' of the actual arguments, and its ``cdr'' will be matched against the ``cdr'' of the actual arguments.

Example:

? (de surface((x1 y1) (x2 y2) )
       (* (- x1 x1) (- y2 y2)) )
= surface
? (surface '(4 5) '(8 10))
= 40

Moreover, two symbols &optional and &rest in argument lists have a special meaning, similar to the Common Lisp conventions.

Only symbols and lists composed of a symbol and a default value may follow the &optional symbol in the formal argument list. These symbols are optional arguments. If they are omitted, they are bound to their default value, or the empty list.

Example:

? (de printline(s &optional (indent 0) (terminate "."))
       (tab indent)
       (printf "%s%s\n" s terminate) )
= printline
? (printline "hello")
hello.
= ()
? (printline "hello" 6)
      hello.
= ()
? (printline "hello" 6 "@")
      hello@
= ()

Finally, the formal argument list may be terminated by &rest followed by another symbol. The list of all remaining actual arguments will be bound to that symbol.



3.6.1. Defining a Function




3.6.1.0. (de symb args . body)
[DY]


See: Argument List.


Creates a new function which evaluates its arguments (DE) and stores this function into the value field of symbol symb .

A valid argument list args may be a single symbol, a list of symbols or something more complex like (a b (c d) . f) . A valid function body body is a list of Lush expressions which are evaluated whenever the function is called.

Whenever a DE function is called,

Example:

? (de square (x) (* x x)) 
= square 
? (square 9) 
= 81 
? (de first-arg l
         (car l) )
= first-arg
? (first-arg 'a 'b)
= a
? (first-arg 'prems 'deuse 'troise 'quatrz)
= prems



3.6.1.1. (df symb args . body)
[DY]


See: Argument List.
See: (dm symb args . body )


Creates a new function which does not evaluates its arguments (DF) and stores this function into the value field of symbol symb .

A valid argument list args may be a single symbol, a list of symbols or something more complex like (a b (c d) . f) . A valid function body body is a list of Lush expressions which are evaluated whenever the function is called.

Whenever a DF function is called,

Example: Defining a control structure

? (df ifn(cond no . yes)
      (if (not (eval cond))
          (eval no)
        (apply progn yes)) )
= ifn
? (ifn (= 2 3) 1 2))
= 2

Such a definition causes problems if some subexpression depend on a the value of a symbol named like a function argument.

? (ifn (= 2 3) cond 2)
= (= 2 3)

The previous expression should indeed return the value of symbol cond in the current context rather than the value of symbol cond in the context of function ifn .

This problem is alleviated by using ``macro functions''.



3.6.1.2. (dm symb args . body)
[DY]


See: Argument List.


Creates a macro-function (DM) and stores it into the value field of symbol symb . The body of a DM function actually computes the expression which will be evaluated in the calling context. This expression can be found with the function macro-expand .

A valid argument list args may be a single symbol, a list of symbols or something more complex like (a b (c d) . f) . A valid function body body is a list of Lush expressions which are evaluated whenever the function is called.

Whenever a DM function is called,

Example:

? (dm ifn(fname cond . rest) 
      (list 'if (list 'not cond) . rest) )
= ifn
? (ifn (= 2 3) "yes" "no")
= "yes"
? (setq cond "yes")
= "yes"
? (ifn (= 2 3) cond)
= "yes"



3.6.1.3. (macro-expand macrocall)
[DY]


See: (dm symb args . body )
Returns the ``expansion'' of a call to a DM function.

Example:

? (dm ifn(fname cond . rest) 
      (list 'if (list 'not cond) . rest) )
= ifn
? (macro-expand (ifn (= 2 3) "yes" "no"))
= (if (not (= 2 3)) "yes" "no")



3.6.1.4. (dmd symb args . body)
[DM] (sysenv.lsh)


See: Argument List.
See: (dm symb args . body )


Creates a DMD function and stores it into symbol symb . DMD functions display two differences with DM functions:

A valid argument list args may be a single symbol, a list of symbols or something more complex like (a b (c d) . f) . A valid function body body is a list of Lush expressions which are evaluated whenever the function is called.

Whenever a DMD function is called,

Example:

? (dmd ifn(cond . rest)
       (list 'if (list 'not cond) . rest) )
= ifn
? (de if-test(n)
       (ifn (= n 2) "yes" "no") )
= if-test
? (if-test 2)
= "no"
? (pretty if-test)
(de if-test(n)
   (if (not (= n 2)) "yes" "no") )
= (if-test)



3.6.1.5. (dmc symb . body)
[DY]


Defines a macro-character symb . A macro-character is not really functions, since it interacts only with the Lisp reader.

There are three kinds of macro-characters:

Since the reader performs special actions whenever it encounters a macro-character, it is advisable to surround the name of symbol symb with vertical bars | .

Examples:

The macro character ' which expands into a call to function quote is defined as :

(dmc |'| (list 'quote (read)))

The macro character ^P which expands into a call to function pretty is defined as :

(dmc |^P| (list 'pretty (read)))

The following macro-character #! could be used to signal debug instructions that will be not read if variable ndebug is set.

(dmc |#!| (let ((inst (read))) (when (not ndebug) inst)))


3.6.1.6. (lambda args . body)
[DY]


See: Argument List.
See: (de symb args . body )


Returns a function which evaluates its arguments (DE). This function operates like function de but does not store the function in a particuler symbol.

Example:

? ((lambda (x)
     (* x x) ) (+ 4 5))
= 81



3.6.1.7. (flambda args . body)
[DY]


See: Argument List.
See: (df symb args . body )


Returns a function which does not evaluates its arguments (DF). This function operates like function df but does not store the function in a particuler symbol.

Example:

? ((flambda (x)
     (print x) ) (+ 4 5))
(+ 4 5)
= (+ 4 5)



3.6.1.8. (mlambda args . body)
[DY]


See: Argument List.
See: (dm symb args . body )


Returns a macro-function (DM). This function operates like function dm but does not store the function in a particuler symbol.



3.6.1.9. (funcdef n)
[DX]


Returns a list which defines the function n . This works for DEs, DFs, DMs and other interpreted functions, but returns nil for DH, DX, DY, and other compiled or intrinsic functions.

Example:

? (funcdef caddr)
= (lambda (l)
    (car (cddr l)) )



3.6.1.10. (pretty f)
[DM] (sysenv.lsh)


Display a nicely indented definition of function f .

Actually, pretty sends a pretty message to f . Each class defines how an instance of that class will be displayed. In particular, functions are displayed by printing an indented version of the definition of the functions f1 to fn.

Example

? (pretty caddr)
(de caddr (l)
  (car (cddr l)) )
= t



3.6.1.11. ^P function
[DMC] (sysenv.lsh)


See: (pretty f )
This macro character expands into a call of function pretty .

Example:

? ^Paddpath
(de addpath (dir)
  (setq dir (concat_fname dir))
  (let ((oldpath (path))
        (newpath (list dir)) )
    (while oldpath
      (when (<> dir (car oldpath))
        (setq newpath (nconc1 newpath (car oldpath))) )
      (setq oldpath (cdr oldpath)) )
    (apply path newpath) ) )
= ()



3.6.1.12. (defun name args ...body...)
[DM] (sysenv.lsh)


See: (de symb args . body )
See: (defmacro name args ... body ...)
See: (defvar name [ val ])


Function defun defines a global DE function named name . Whereas function de defines symbol name in the current scope, function defun defines symbol name in the global scope.



3.6.1.13. (defmacro name args ...body...)
[DM] (sysenv.lsh)


See: (de symb args . body )
See: (defun name args ... body ...)
See: (defvar name [ val ])


Function defun defines a global DM function named name . Whereas function dm defines symbol name in the current scope, function defun defines symbol name in the global scope. The argument list args only matches the arguments of the macro. It should not contain a symbol for matching the function name itself.