| 1 | ||
|
Editor: page
Time: 2007/09/12 02:27:33 GMT-7 |
||
| Note: | ||
changed: - It is possible to enter Lisp expressions directly into Axiom (including function definitions) using the ')lisp' command, but this is rather awkward for long Lisp programs. \begin{axiom} )lisp (defun foo1 (x y) (+ x y)) )lisp (foo1 2 3) \end{axiom} On the Axiom wiki we can enter Lisp code in the same way that we enter Axiom code. For example:: !\begin{lisp} (defun FOO2 (x y) (+ x y)) \end{lisp} The text between the !\begin{lisp} ... \end{lisp} is saved in a temporary file (e.g. 'tempfile.lisp'). It is then compiled and loaded into Lisp via the command:: )list (load (compile-file "tempfile.lisp")) \begin{lisp} ;;; Just a silly example (defun FOO2 (x y) (+ x y)) \end{lisp} Click '+lisp' to check the Lisp output for errors. We can call the function from Axiom like this: \begin{axiom} FOO2(3,4)$Lisp \end{axiom} Or we can call the function from Lisp like this: \begin{lisp} (format t "(FOO2 1 2) = ~a~%" (FOO2 1 2) ) \end{lisp} Notice that the 'Value = 40' is the result of the (load ...) function call, not the value of the 'FOO2' function. In the case of an error: \begin{lisp} (defunny FOO3 (x y) (+ x y)) \end{lisp} '+lisp' shows the error message. This is a lisp expression that generates some output. \begin{lisp} (format t "hello, world") \end{lisp} Lisp Tutorial 1 http://www.cs.sfu.ca/CC/310/pwfong/Lisp/1/tutorial1.html Common LISP reads in an expression, evaluates it, and then prints out the result. For example, if you want to compute the value of '(2 * cos(0) * (4 + 6))', you type in: \begin{axiom} )lisp (* 2 (cos 0) (+ 4 6)) \end{axiom} Here is a more complex recursive function. \begin{lisp} (defun fibonacci (N) "Compute the N'th Fibonacci number." (if (or (zerop N) (= N 1)) 1 (+ (fibonacci (- N 1)) (fibonacci (- N 2))))) \end{lisp} We can trace its execution. \begin{axiom} )lisp (trace fibonacci) )lisp (fibonacci 5) \end{axiom} Lisp Links & Notes (advanced) http://www.cs.ucla.edu/classes/winter04/cs161/l1/lispLinks.html by Michael G. Dyer http://www.cs.ucla.edu/classes/winter04/cs161/l1 lambda, closures, apply, funcall, and mapcar One thing to note here is that the word "thunk" is often used as a synonym for "closure". A closure is defined as a double whose two elements are a pointer to code and a pointer to an environment. In the adder example below, the reason we need the "environment pointer" is that we need a way to remember what n was bound to at the time that (adder 3) was created. This particular "adder" example comes from the "CL Cookbook":http://cl-cookbook.sourceforge.net \begin{lisp} (defun adder (n) (function (lambda (x) (+ x n))) ) \end{lisp} \begin{axiom} )lisp (adder 3) )lisp (apply (adder 3) '(4)) )lisp (funcall (adder 3) 4) )lisp (mapcar (adder 3) '(1 2 3 4)) \end{axiom} There are two slightly different ways of using mapcar. One is by passing it a lambda block, which is created by simply prepending the #' in front of the function name. The other is to pass it a closure: \begin{lisp} (defun increment (i) (+ i 1) ) \end{lisp} \begin{axiom} )lisp #'increment )lisp (mapcar #'increment '(1 2 3)) )lisp #'(lambda (x) (increment x)) )lisp (mapcar #'(lambda (x) (increment x)) '(1 2 3)) \end{axiom} compose Let's take a look at a "higher-order" function, which means that it takes functions as arguments. The compose function is the same as in mathematics. f(g(x)) = compose(f,g)(x) \begin{lisp} (defun increment (i) (+ i 1) ) (defun square (z) (* z z) ) (defun compose (f g) #'(lambda (x) (funcall f (funcall g x))) ) \end{lisp} \begin{axiom} )lisp (funcall (compose #'increment #'square) 3) \end{axiom} curry and uncurry \begin{lisp} (defun printthree (arg1 arg2 arg3) (format *query-io* "arg1 = ~A, arg2 = ~A, arg3 = ~A~%" arg1 arg2 arg3) ) \end{lisp} \begin{axiom} )lisp (printthree 3 4 4) \end{axiom} \begin{lisp} (defun curry (function &rest args) (function (lambda (&rest more-args) (apply function (append args more-args))))) \end{lisp} \begin{axiom} )lisp (curry #'printthree 'a) )lisp (apply (curry #'printthree 'a) '(b c)) )lisp (curry #'printthree 'a 'b) )lisp (apply (curry #'printthree 'a 'b) '(c)) \end{axiom} \begin{lisp} (defun uncurry (f) #'(lambda (x y) (funcall (funcall f x) y)) ) (defun uncurry (f) #'(lambda (x y) (funcall (funcall f x) y)) ) \end{lisp} \begin{axiom} )lisp (uncurry (curry #'+ 1)) \end{axiom}
It is possible to enter Lisp expressions directly into Axiom
(including function definitions) using the )lisp command,
but this is rather awkward for long Lisp programs.
)lisp (defun foo1 (x y) (+ x y))
Value = FOO1
)lisp (foo1 2 3)
Value = 5
On the Axiom wiki we can enter Lisp code in the same way that we enter Axiom code. For example:
\begin{lisp}
(defun FOO2 (x y)
(+ x y))
\end{lisp}
The text between the \begin{lisp} ... \end{lisp} is saved in a
temporary file (e.g. tempfile.lisp). It is then compiled and
loaded into Lisp via the command:
)list (load (compile-file "tempfile.lisp"))
;;; Just a silly example (defun FOO2 (x y) (+ x y))
Value = 304
Click +lisp to check the Lisp output for errors.
We can call the function from Axiom like this:
FOO2(3,4)$Lisp
| (1) |
Or we can call the function from Lisp like this:
(format t "(FOO2 1 2) = ~a~%" (FOO2 1 2) )
(FOO2 1 2) = 3 Value = 88
Notice that the Value = 40 is the result of the (load ...)
function call, not the value of the FOO2 function.
In the case of an error:
(defunny FOO3 (x y) (+ x y))
>> System error: The function DEFUNNY is undefined.
+lisp shows the error message.
This is a lisp expression that generates some output.
(format t "hello, world")
hello, world Value = 88
http://www.cs.sfu.ca/CC/310/pwfong/Lisp/1/tutorial1.html
Common LISP reads in an expression, evaluates it, and then
prints out the result. For example, if you want to compute the
value of (2 * cos(0) * (4 + 6)), you type in:
)lisp (* 2 (cos 0) (+ 4 6))
Value = 20.0
Here is a more complex recursive function.
(defun fibonacci (N)
"Compute the N'th Fibonacci number."
(if (or (zerop N) (= N 1))
1
(+ (fibonacci (- N 1)) (fibonacci (- N 2)))))
Value = 600
We can trace its execution.
)lisp (trace fibonacci)
Value = (FIBONACCI)
)lisp (fibonacci 5)
1> (FIBONACCI 5) 2> (FIBONACCI 4) 3> (FIBONACCI 3) 4> (FIBONACCI 2) 5> (FIBONACCI 1) <5 (FIBONACCI 1) 5> (FIBONACCI 0) <5 (FIBONACCI 1) <4 (FIBONACCI 2) 4> (FIBONACCI 1) <4 (FIBONACCI 1) <3 (FIBONACCI 3) 3> (FIBONACCI 2) 4> (FIBONACCI 1) <4 (FIBONACCI 1) 4> (FIBONACCI 0) <4 (FIBONACCI 1) <3 (FIBONACCI 2) <2 (FIBONACCI 5) 2> (FIBONACCI 3) 3> (FIBONACCI 2) 4> (FIBONACCI 1) <4 (FIBONACCI 1) 4> (FIBONACCI 0) <4 (FIBONACCI 1) <3 (FIBONACCI 2) 3> (FIBONACCI 1) <3 (FIBONACCI 1) <2 (FIBONACCI 3) <1 (FIBONACCI 8) Value = 8
http://www.cs.ucla.edu/classes/winter04/cs161/l1/lispLinks.html
by Michael G. Dyer http://www.cs.ucla.edu/classes/winter04/cs161/l1
One thing to note here is that the word "thunk" is often used as a synonym for "closure".
A closure is defined as a double whose two elements are a pointer to code and a pointer to an environment. In the adder example below, the reason we need the "environment pointer" is that we need a way to remember what n was bound to at the time that (adder 3) was created.
This particular "adder" example comes from the CL Cookbook
(defun adder (n) (function (lambda (x) (+ x n))) )
Value = 536
)lisp (adder 3)
Value = #<compiled-closure 0000000001efbea0>
)lisp (apply (adder 3) '(4))
Value = 7
)lisp (funcall (adder 3) 4)
Value = 7
)lisp (mapcar (adder 3) '(1 2 3 4))
Value = (4 5 6 7)
There are two slightly different ways of using mapcar. One is by passing it a lambda block, which is created by simply prepending the #' in front of the function name. The other is to pass it a closure:
(defun increment (i) (+ i 1) )
Value = 304
)lisp #'increment
Value = #<compiled-function INCREMENT>
)lisp (mapcar #'increment '(1 2 3))
Value = (2 3 4)
)lisp #'(lambda (x) (increment x))
Value = (LAMBDA-CLOSURE () () () (X) (INCREMENT X))
)lisp (mapcar #'(lambda (x) (increment x)) '(1 2 3))
Value = (2 3 4)
Let's take a look at a "higher-order" function, which means that it takes functions as arguments. The compose function is the same as in mathematics. f(g(x)) = compose(f,g)(x)
(defun increment (i) (+ i 1) )
(defun square (z) (* z z) )
(defun compose (f g) #'(lambda (x) (funcall f (funcall g x))) )
Value = 1048
)lisp (funcall (compose #'increment #'square) 3)
Value = 10
curry and uncurry
(defun printthree (arg1 arg2 arg3) (format *query-io* "arg1 = ~A, arg2 = ~A, arg3 = ~A~%" arg1 arg2 arg3) )
Value = 320
)lisp (printthree 3 4 4)
arg1 = 3, arg2 = 4, arg3 = 4 Value = NIL
(defun curry (function &rest args) (function (lambda (&rest more-args) (apply function (append args more-args)))))
Value = 744
)lisp (curry #'printthree 'a)
Value = #<compiled-closure 0000000001f25240>
)lisp (apply (curry #'printthree 'a) '(b c))
arg1 = A, arg2 = B, arg3 = C Value = NIL
)lisp (curry #'printthree 'a 'b)
Value = #<compiled-closure 0000000001f25120>
)lisp (apply (curry #'printthree 'a 'b) '(c))
arg1 = A, arg2 = B, arg3 = C Value = NIL
(defun uncurry (f) #'(lambda (x y) (funcall (funcall f x) y)) )
(defun uncurry (f) #'(lambda (x y) (funcall (funcall f x) y)) )
Warning: UNCURRY has a duplicate definition in this file Value = 1088
)lisp (uncurry (curry #'+ 1))
Value = #<compiled-closure 0000000001f347e0>