3.6. Functions |
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 |
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] |
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] |
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] |
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] |
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) |
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] |
There are three kinds of macro-characters:
Caret macro-character may also be abbreviated by typing the
corresponding control character (if this control character exists and is
not intercepted by the operating system). If you are running WinLush,
the fastest method consists in typing
Ctrl+Shift+Letter . It is always possible however to type the
caret followed by the character.
Hash macro characters are useful for conditionally reading certain pieces of code.
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] |
Example:
? ((lambda (x) (* x x) ) (+ 4 5)) = 81
3.6.1.7. (flambda args . body) |
[DY] |
Example:
? ((flambda (x) (print x) ) (+ 4 5)) (+ 4 5) = (+ 4 5)
3.6.1.8. (mlambda args . body) |
[DY] |
3.6.1.9. (funcdef n) |
[DX] |
Example:
? (funcdef caddr) = (lambda (l) (car (cddr l)) )
3.6.1.10. (pretty f) |
[DM] (sysenv.lsh) |
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) |
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) |
3.6.1.13. (defmacro name args ...body...) |
[DM] (sysenv.lsh) |