|
|
last edited 8 years ago by test1 |
1 2 | ||
Editor: test1
Time: 2015/11/09 18:23:43 GMT+0 |
||
Note: |
changed: - It is possible to enter Lisp expressions directly into FriCAS (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 FriCAS wiki we can enter Lisp code in the same way that we enter FriCAS 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:: )lisp (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 FriCAS 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 = T' 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 specification: http://www.lispworks.com/documentation/HyperSpec/Front/ 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 FriCAS?
(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 FriCAS? wiki we can enter Lisp code in the same way that we enter FriCAS? 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:
)lisp (load (compile-file "tempfile.lisp"))
;;; Just a silly example (defun FOO2 (x y) (+ x y))
; compiling file "/var/aw/var/LatexWiki/5467520105124776552-25px002.lisp" (written 07 MAY 2016 12:54:25 PM):
; /var/lib/zope2.10/instance/axiom-wiki/var/LatexWiki/5467520105124776552-25px002.fasl written ; compilation finished in 0:00:00.003 Value = T
Click +lisp
to check the Lisp output for errors.
We can call the function from FriCAS? 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) )
; compiling file "/var/aw/var/LatexWiki/4849575266889566101-25px004.lisp" (written 07 MAY 2016 12:54:25 PM):
; /var/lib/zope2.10/instance/axiom-wiki/var/LatexWiki/4849575266889566101-25px004.fasl written ; compilation finished in 0:00:00.000 (FOO2 1 2) = 3 Value = T
Notice that the Value = T
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))
; compiling file "/var/aw/var/LatexWiki/7691373298349222252-25px005.lisp" (written 07 MAY 2016 12:54:25 PM):
; /var/lib/zope2.10/instance/axiom-wiki/var/LatexWiki/7691373298349222252-25px005.fasl written ; compilation finished in 0:00:00.001
>> System error: The variable FOO3 is unbound.
+lisp
shows the error message.
This is a lisp expression that generates some output.
(format t "hello,world")
; compiling file "/var/aw/var/LatexWiki/229055943891593707-25px006.lisp" (written 07 MAY 2016 12:54:25 PM):
; /var/lib/zope2.10/instance/axiom-wiki/var/LatexWiki/229055943891593707-25px006.fasl written ; compilation finished in 0:00:00.001 hello,world Value = T
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.0f0
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)))))
; compiling file "/var/aw/var/LatexWiki/8805225188305955522-25px008.lisp" (written 07 MAY 2016 12:54:25 PM):
; /var/lib/zope2.10/instance/axiom-wiki/var/LatexWiki/8805225188305955522-25px008.fasl written ; compilation finished in 0:00:00.003 Value = T
We can trace its execution.
)lisp (trace fibonacci)
Value = (FIBONACCI)
)lisp (fibonacci 5)
0: (FIBONACCI 5) 1: (FIBONACCI 4) 2: (FIBONACCI 3) 3: (FIBONACCI 2) 4: (FIBONACCI 1) 4: FIBONACCI returned 1 4: (FIBONACCI 0) 4: FIBONACCI returned 1 3: FIBONACCI returned 2 3: (FIBONACCI 1) 3: FIBONACCI returned 1 2: FIBONACCI returned 3 2: (FIBONACCI 2) 3: (FIBONACCI 1) 3: FIBONACCI returned 1 3: (FIBONACCI 0) 3: FIBONACCI returned 1 2: FIBONACCI returned 2 1: FIBONACCI returned 5 1: (FIBONACCI 3) 2: (FIBONACCI 2) 3: (FIBONACCI 1) 3: FIBONACCI returned 1 3: (FIBONACCI 0) 3: FIBONACCI returned 1 2: FIBONACCI returned 2 2: (FIBONACCI 1) 2: FIBONACCI returned 1 1: FIBONACCI returned 3 0: FIBONACCI returned 8 Value = 8
http://www.lispworks.com/documentation/HyperSpec/Front/
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))) )
; compiling file "/var/aw/var/LatexWiki/1662804482358068841-25px010.lisp" (written 07 MAY 2016 12:54:25 PM):
; /var/lib/zope2.10/instance/axiom-wiki/var/LatexWiki/1662804482358068841-25px010.fasl written ; compilation finished in 0:00:00.002 Value = T
)lisp (adder 3)
Value = #<CLOSURE (LAMBDA (X) :IN ADDER) {10049D960B}>
)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) )
; compiling file "/var/aw/var/LatexWiki/4211409212481666063-25px012.lisp" (written 07 MAY 2016 12:54:25 PM):
; /var/lib/zope2.10/instance/axiom-wiki/var/LatexWiki/4211409212481666063-25px012.fasl written ; compilation finished in 0:00:00.001 Value = T
)lisp #'increment
Value = #<FUNCTION INCREMENT>
)lisp (mapcar #'increment '(1 2 3))
Value = (2 3 4)
)lisp #'(lambda (x) (increment x))
Value = #<INTERPRETED-FUNCTION NIL {1004A3CBEB}>
)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))) )
; compiling file "/var/aw/var/LatexWiki/6034342207465796072-25px014.lisp" (written 07 MAY 2016 12:54:25 PM):
; /var/lib/zope2.10/instance/axiom-wiki/var/LatexWiki/6034342207465796072-25px014.fasl written ; compilation finished in 0:00:00.010 Value = T
)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) )
; compiling file "/var/aw/var/LatexWiki/4952192325462136804-25px016.lisp" (written 07 MAY 2016 12:54:25 PM):
; /var/lib/zope2.10/instance/axiom-wiki/var/LatexWiki/4952192325462136804-25px016.fasl written ; compilation finished in 0:00:00.010 Value = T
)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)))))
; compiling file "/var/aw/var/LatexWiki/2878124551976497830-25px018.lisp" (written 07 MAY 2016 12:54:25 PM):
; /var/lib/zope2.10/instance/axiom-wiki/var/LatexWiki/2878124551976497830-25px018.fasl written ; compilation finished in 0:00:00.003 Value = T
)lisp (curry #'printthree 'a)
Value = #<CLOSURE (LAMBDA (&REST MORE-ARGS) :IN CURRY) {1004C109BB}>
)lisp (apply (curry #'printthree 'a) '(b c))
arg1 = A,arg2 = B, arg3 = C Value = NIL
)lisp (curry #'printthree 'a 'b)
Value = #<CLOSURE (LAMBDA (&REST MORE-ARGS) :IN CURRY) {1004C17C0B}>
)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)) )
; compiling file "/var/aw/var/LatexWiki/6522788210180720678-25px020.lisp" (written 07 MAY 2016 12:54:25 PM):
; /var/lib/zope2.10/instance/axiom-wiki/var/LatexWiki/6522788210180720678-25px020.fasl written ; compilation finished in 0:00:00.007 Value = T
)lisp (uncurry (curry #'+ 1))
Value = #<CLOSURE (LAMBDA (X Y) :IN UNCURRY) {1004CBF18B}>