310 likes | 389 Views
Artificial Intelligence and Lisp Lecture 11 Programming in Lisp, II LiU Course TDDC65 Autumn Semester, 2010 http://www.ida.liu.se/ext/TDDC65/. Course literature list on course website. The full list of course literature is now on the webpage Page counts:
E N D
Artificial Intelligence and LispLecture 11Programming in Lisp, IILiU Course TDDC65Autumn Semester, 2010http://www.ida.liu.se/ext/TDDC65/
Course literature list on course website • The full list of course literature is now on the webpage • Page counts: • Introductory material: 19 + 38 + 22 = 79 pages • Primary lecture notes on systems and languages: • 22 + 12 + 50 = 84 pages • Lisp note for the labs + Lisp on-line tutorial (from SFU) • Primary lecture notes on knowledge representation: • 14 + 26 + 20 + 17 = 77 pages • Summary and synthesis (to follow before November 30) • Technical background, additional reading (not on exam)
Amendments to Lisp literature reference • We are using case-sensitive input to read • System prompt looks slightly different • For tracing a function foo, do :trace foo • For backtrace from error, do :zoom • Disregard compilation, we run interpretively • Ignore library references, of course
Core Lisp Functions (Required for Exam) • car, cdr, caar, cadr, ... • cons, equal, null, quote, ' • symbolp, stringp, listp, numberp • <, <=, >, >=, +, -, *, / • and, or, not (also generalized) • if, cond, let* • defun • get, put, setf, setq • rplaca, rplacd, eq, progn • read, print • eval, funcall, function, #'
Some Other Useful Lisp Functions • dolist, dotimes, case • 1+, 1-, eql, length • random • open ... :direction input/output/probe • generalized read, readline, close • string, intern • princ-to-string, read-from-string • Exam can contain list of functions that may be needed for doing the Lisp problems, such as these above, but the functions on the previous slide will not be given in this way.
Coding Example: Operating-System Commands • Motivation: • Invoke operating-system services from Lisp dialog • Apply action facilities (scripting, precondition checking, planning, failure detection and correction, etc) to os commands in a uniform fashion • Integrate directory information with information within the Lisp application at hand, for example, knowledge about what information is in particular files, with information about the properties of that information
Interfaces of the New Program • The programmer has to relate to three "systems": • 1. The application environment that the program is to serve. In this case, the operating system at hand. • 2. The software environment where the software (programs and data, and things in-between such as scripts) are to be stored and administrated. • 3. The software environment where the software is to be executed. • For items (2) and (3), consider first the elementary Lisp environment, and then the Leonardo environment as an example of an environment with many facilities.
Programming 'Modes' • The following are some major modes of work: • Introductory mode: Find your place and establish the place of the forthcoming software. • Exploration of the interface to the application. Find out how it can be accessed, and make tentative design of how things are to be represented on the Lisp side. • Exploration of the interface to your execution environment (if non-elementary) and how it may be used for the present application. • Decide, design and implement nontrivial facilities within the Lisp framework. Major cases: 1. A specific algorithm; 2. An interpreter for an embedded language.
Introductory mode: Find your place • file lispos.bat under Windows: • start C:\Progra~1\acl80\mlisp.exe -L lispos-top.cl • file lispos-top.cl in same directory: • (princ "Start loading LISPOS")(terpri) • (defun myrev (s)(myrev2 s nil)) • (defun myrev2 (s a) • (if (null s) a • (myrev2 (cdr s)(cons (car s) a))) )
Typical things to do • In introductory mode: Decide where to locate the code; define a very simple introductory function; load and run. • In mode for exploring interface to application: Decide on an operation that relates to the application environment, for acquiring or imposing information. Find out about the necessary interface. Implement a very simple version of the operation. Refine. • Same mode, continued: then decide about the persistent Lisp-side representation of the acquired or imposed information. Implement, test, refine. • Same mode, while doing the above: also implement work facilitating functions whenever appropriate. • Example: directory command (= ls in Linux)
Version 2 • (princ "Start loading LISPOS")(terpri) • (defun dirfun1 (s) • (mapcar #'(lambda (x) • (princ-to-string x)) • (directory s) )) • (princ "Finished loading LISPOS")(terpri)
Version 3 • (princ "Start loading LISPOS")(terpri) • (defun dirfun1 (s) • (mapcar #'(lambda (x) • (princ-to-string x)) • (directory s) )) • (defun dirfun2 (s) • (cons (subseq s 0 3) • (mapcar #'(lambda (x) • (subseq (princ-to-string x) 3) ) • (directory s) ))) • (princ "Finished loading LISPOS")(terpri)
Versions 4 - 8 • See the .cl files for versions 4 to 8. • Notice bottom-up working style of first doing something very simple, then testing it, gradually refining it to become more complex.
Implementing in Leonardo Environment(as one example) • Each function definition is made a Leonardo entity • Use properties for: • - Documentation stubs (generate documentation pdf) • - Standardized phrases (also for multiple languages) • - Comments of various kinds • Use Leonardo knowledgeblock facility for assigning a structure to a larger system, e.g. 'requires' and 'mustload' attributes of entityfiles • Organize version management using Leonardo entityfile structure; version manager as separate agent
Implementing Interpreters • Recall: Decide, design and implement nontrivial facilities within the Lisp framework. Major cases: 1. A specific algorithm; 2. An interpreter for an embedded language. • We shall consider the second case. • Operations on files shall include: • - send to printer • - count number of words (if text file) • - convert to html with same name, extension html • - convert to pdf with same name, extension pdf • - concatenate two files (for both .txt, .html and .pdf) • - be prepared for many other specific operations • - allow conditional and loop commands for the above
Tentative Lispos Scripting Language • (print foo) where foo is a file • (repeat f fooset (print f)) • (filedir path) • (charsize foo) • (editdate foo) • (txt2html foo) • (txt2pdf foo) • (html2txt foo) • (script op1 op2 ... opn) • (defscript name (script ...))
Thinking about Scripting Language • (print foo), (txt2html foo), ... • (repeat f fooset (print f)) • (filedir path) • (script op1 op2 ... opn) • (defscript name (script ...)) • What is relation between foo and path? • Need interpreter that can call itself recursively (at least once...) • Interpreter needs to carry variable(s) along • Need for evaluation of terms, for example for fooset • Need for interface to Lisp (or write directly in Lisp?)
Separate Scripting Language vs Write in Lisp • +Separate: May enable more compact and/or convenient notation • +Separate: Better control of "errors" by user • +Separate: Less easy to penetrate by adverse users • +DirectlyInLisp: Seamless integration with any Lisp code • +DirectlyInLisp: Performance (sometimes)
Tentative Top Level • (defun lispos (scr vbl val) • (case (car scr) • (print ...) • (script (dolist (x (cdr scr)) • (lispos x vbl val) )) • (repeat (dolist (j (losev (caddr scr))) • (lispos (cadddr scr) • (cadr scr) j ))) • (t [... error handling ...] ))) • (defun lispex (scr) (lispos scr nil nil))
Tentative Top Level • (defun lispos (scr vbl val) • (case (car scr) • (print (send-to-printer • (evarg (cadr scr) vbl val) )) • ... )) • (defun evarg (arg vbl val) • (if (equal arg vbl) val • (if (stringp arg) arg • (if (symbolp arg) (get arg 'path) • (case (car arg) ... )))))
Using 'cond' instead of 'if' • (defun evarg (arg vbl val) • (if (equal arg vbl) val • (if (stringp arg) arg • (if (symbolp arg) (get arg 'path) • (case (car arg) ... ))))) • Rewrite better as follows: • (defun evarg (arg vbl val) • (cond ((equal arg vbl) val) • ((stringp arg) arg) • ((symbolp arg)(get arg 'path)) • ... ))
Using Attached Functions • (defun lispos (scr vbl val) • (case (car scr) • (print ...) • (script (dolist (x (cdr scr)) • (lispos x vbl val) )) ...)) • (defun lispos (scr vbl val) • (funcall (get (car scr) 'lisposdef) • (cdr scr) vbl val )) • (setf (get 'print 'lisposdef) • #'(lambda (args vbl val) • (send-to-printer • (evarg (cadr scr) vbl val) )))
Joint Argument Evaluation • (defun lispos (scr vbl val) • (funcall (get (car scr) 'lisposdef) • (cdr scr) vbl val )) • (setf (get 'print 'lisposdef) • #'(lambda (args vbl val) (send-to-printer • (evarg (cadr scr) vbl val) ))) • (defun lispos (scr vbl val) • (funcall (get (car scr) 'lisposdef) • (evarglist (cdr scr) vbl val) )) • (setf (get 'print 'lisposdef) • #'(lambda (args vbl val) • (send-to-printer args vbl val) ))
Joint Argument Evaluation • (defun lispos (scr vbl val) • (funcall (get (car scr) 'lisposdef) • (evarglist (cdr scr) vbl val) )) • (setf (get 'print 'lisposdef) • #'(lambda (args vbl val) • (send-to-printer args vbl val) )) • (defun evarglist (lst vbl val) • (if (null lst) nil • (cons (evarg (car lst) vbl val) • (evarglist (cdr lst) vbl val) )))
Compiling Scripts • (defun lispos (scr vbl val) • (case (car scr) • (print (send-to-pr (cadr scr) vbl val)) • (script (dolist (x (cdr scr)) • (lispos x vbl val) )) ...)) • Now consider conversion: • (lispos '(script (print "file1")(print "file2")) • nil nil ) • (progn (send-to-pr "file1" nil nil) • (send-to-pr "file2" nil nil) ) • Latter version can be compiled. • How can this conversion be automated?
Partial Application - Example • (defun foo (x y)(cons (car x)(cdr y))) • (foo '(a b c) '(g h i)) evaluates to (a h i) • (funcall 'foo '(a b c) '(g h i)) same • (funcall #'(lambda (x y)(cons (car x)(cdr y))) • '(a b c) '(g h i) ) same • (funcall #'(lambda (x y)(cons (car x)(cdr y))) • '(a b c) z ) requires value of z • (partapply #'(lambda (x y)(cons (car x)(cdr y))) • '(a b c) ) evaluates to • #'(lambda (z)(cons 'a z))
Partial Evaluation and Application • (partapply fn a) takes a function fn of two arguments and returns a function of one argument • (funcall fn '(a b c) '(c d e)) = • (funcall (partapply fn '(a b c)) '(c d e)) • Notice that the function lispos took three arguments: • (lispos script vbl val) • but actually better to write as • (lispos script (list (list vbl val))) • to allow for several variables • Therefore quite feasible to compile lispos scripts to Lisp (or define partial application for functions of 3 arguments)
Script Compilation Sequence • Convert from use of attached functions to use of case-expressions • Partial evaluation with respect to the resulting script • Compilation of Lisp code to lower level (machine language or pseudocode)
Defining Lisp in Lisp • (defun apply (fn args)(cond • ((symbolp fn)(apply (fndef fn) args)) • ((equal (car fn) 'lambda) • (eval (caddr fn)(bind (cadr fn) args))) • ... etc )) • (defun eval (form bind)(cond • ((symbolp form)(lookup form bind)) • ((stringp form) form) • ((equal (car form) 'quote)(cadr form)) ... • (t (apply (car form)(evlis (cdr form) bind))) • ))
Defining (Partial) Application for Lisp • (defun apply (fn args)(cond • ((symbolp fn)(apply (fndef fn) args)) • ((equal (car fn) 'lambda) • (eval (caddr fn)(bind (cadr fn) args))) • ... etc )) • The definition of partapply follows the same pattern - straightforward to generalize
Autogenerating Partial Application for Lisp • (defun apply (fn args)(cond • ((symbolp fn)(apply (fndef fn) args)) • ((equal (car fn) 'lambda) • (eval (caddr fn)(bind (cadr fn) args))) • ... etc )) • The definition of partapply follows the same pattern - straightforward to generalize • But - apply is itself a function of two arguments. Can one apply partapply on it? • (funcall fn '(a b c) '(c d e)) = • (funcall (partapply fn '(a b c)) '(c d e))