1.
C: void foo(){ bar1(); bar2(); }
lisp: (defun foo()
(函数体))
因此很自然地在“函数体”部分填入bar1, bar2
(defun bar1() (format t "bar1"))
(defun bar2() (format t "bar2"))
(defun foo()
((bar1) (bar2)))
很不幸这是错误的,对于list语句而且,"()"中第一个标识符必须是一个函数,比如(+ 1 2)(除非你使用'(1 2 3)这种稍后求值形式,第一个标识符不需要是一个函数).
而这里((bar1) (bar2))第一个标识符是(bar1)求值后的结果,也就是format t "bar1"语句的结果,也就是nil,根本不是一个函数,因此是错误的。
我们应该把“函数体"前面的括号去掉.
as follows:
(defun foo()
(bar1)
(bar2))
lisp基本上模糊了代码和数据....
2. lisp版的字符串转数字函数parse-integer
(parse-integer "7") => 7
(parse-integer "x7") =>debug error..
(parse-integer "x7" :junk-allowed t)=>nil
(parse-integer "7x" :junk-allowed t) = 7
第一个字符开始是数字的,则会解析正确
最后两个式子中,:junk-allowed t 是plist的手法,junk-allowed(垃圾-允许)
空格不影响结果
(parse-inteer " 73x73 " :junk-allowed t) => 73
3.lisp的循环,使用loop宏来实现
(loop
(format t "1~%")
(format t "2~%"))
拼命地打印
1
2
1
2
....
4. 使用了中文的括号,导致编译错误,找了半天:( ,恰好也说明我解决问题的能力不强,编译器明明告诉我,encoding problem,但是我看了下代码,觉得没有任何中文字符,应该不会出现错误,结果...
5. list in a box中的SLIME还是挺有用的,比如你想看看with-open-file macro是怎么使用的,你可以敲下"(with-open-file ",SLIME就在Emacs的下方列出了这个Macro的定义,可惜这个定义我还是有些看不懂 :( ,比如&rest是指什么意思?
6.read-line是读入字符,而read是读入lisp代码
7.到目前为止实现这个简易型db的代码,一个感觉,代码很ugly :)
(defvar *db* nil)
(defun add-record(cd) (push cd *db*))
(defun make-cd(title name rating ripped)
(list :title title :name name :rating rating :ripped ripped))
(defun prompt-read(prompt)
(format *query-io* "~a: " prompt)
(force-output *query-io*)
(read-line *query-io*))
(defun prompt-for-cd ()
(make-cd
(prompt-read "title")
(prompt-read "name")
(or (parse-integer (prompt-read "rating") :junk-allowed t) 0)
(y-or-n-p "ripped [y/n] :")))
(defun add-cds ()
(loop (add-record (prompt-for-cd))
(if (not (y-or-n-p "Another: ")) (return))))
(defun save-db(filename)
(with-open-file (myfile filename :direction :output :if-exist :supersede)
(with-standard-io-syntax (print *db* myfile))))
(defun load-db(filename)
(with-open-file (myfile filename)
(with-standard-io-syntax (setf *db* (read myfile)))))
8.(remove-if-not #'evenp '(1 2 3 4))中,#'的意思是:The funny notation #' is shorthand for “Get me the function with the following name.” Without the #', Lisp would treat evenp as the name of a variable and look up the value of the variable, not the function.
那为什么用这么怪的名字呢?我想,撇号已经被拿来用来区分一个数据与代码,从而使有撇号的列表或者原子稍后求值,所以干脆就在撇号前加了个标识 :)
9.lisp有个地方的语法我觉得和lisp本身的语法有些自相矛盾,(defun foo (arg1 arg2) (+ 1 2)),这里foo后面的参数列表(arg1 arg2),如果按照lisp的语法,如果是数据的话应该是'(arg1 arg2),或者换另外一种方式来说,(arg1 arg2)中arg1是一个函数..
总结:
仔细阅读了第三章,然后又巨艰难地浏览第四章,最后又扫了接下来几张关于一些基本语法的章节。lisp总算入门了。但是依然无法运用它来写程序,接下来的计划是阅读例子的章节,这几个例子的章节就当作是实战,在实战中巩固学习lisp知识。
学到的教训:
挑重要的看,人的精力是有限的,不要死看书,挑重点,不用一行一行的死读书,多运用资源和工具,这样才比较又效率。多思考,多动手,多比较(比如查阅其他书籍类似主题的内容进行比较)等等。
C: void foo(){ bar1(); bar2(); }
lisp: (defun foo()
(函数体))
因此很自然地在“函数体”部分填入bar1, bar2
(defun bar1() (format t "bar1"))
(defun bar2() (format t "bar2"))
(defun foo()
((bar1) (bar2)))
很不幸这是错误的,对于list语句而且,"()"中第一个标识符必须是一个函数,比如(+ 1 2)(除非你使用'(1 2 3)这种稍后求值形式,第一个标识符不需要是一个函数).
而这里((bar1) (bar2))第一个标识符是(bar1)求值后的结果,也就是format t "bar1"语句的结果,也就是nil,根本不是一个函数,因此是错误的。
我们应该把“函数体"前面的括号去掉.
as follows:
(defun foo()
(bar1)
(bar2))
lisp基本上模糊了代码和数据....
2. lisp版的字符串转数字函数parse-integer
(parse-integer "7") => 7
(parse-integer "x7") =>debug error..
(parse-integer "x7" :junk-allowed t)=>nil
(parse-integer "7x" :junk-allowed t) = 7
第一个字符开始是数字的,则会解析正确
最后两个式子中,:junk-allowed t 是plist的手法,junk-allowed(垃圾-允许)
空格不影响结果
(parse-inteer " 73x73 " :junk-allowed t) => 73
3.lisp的循环,使用loop宏来实现
(loop
(format t "1~%")
(format t "2~%"))
拼命地打印
1
2
1
2
....
4. 使用了中文的括号,导致编译错误,找了半天:( ,恰好也说明我解决问题的能力不强,编译器明明告诉我,encoding problem,但是我看了下代码,觉得没有任何中文字符,应该不会出现错误,结果...
5. list in a box中的SLIME还是挺有用的,比如你想看看with-open-file macro是怎么使用的,你可以敲下"(with-open-file ",SLIME就在Emacs的下方列出了这个Macro的定义,可惜这个定义我还是有些看不懂 :( ,比如&rest是指什么意思?
6.read-line是读入字符,而read是读入lisp代码
7.到目前为止实现这个简易型db的代码,一个感觉,代码很ugly :)
(defvar *db* nil)
(defun add-record(cd) (push cd *db*))
(defun make-cd(title name rating ripped)
(list :title title :name name :rating rating :ripped ripped))
(defun prompt-read(prompt)
(format *query-io* "~a: " prompt)
(force-output *query-io*)
(read-line *query-io*))
(defun prompt-for-cd ()
(make-cd
(prompt-read "title")
(prompt-read "name")
(or (parse-integer (prompt-read "rating") :junk-allowed t) 0)
(y-or-n-p "ripped [y/n] :")))
(defun add-cds ()
(loop (add-record (prompt-for-cd))
(if (not (y-or-n-p "Another: ")) (return))))
(defun save-db(filename)
(with-open-file (myfile filename :direction :output :if-exist :supersede)
(with-standard-io-syntax (print *db* myfile))))
(defun load-db(filename)
(with-open-file (myfile filename)
(with-standard-io-syntax (setf *db* (read myfile)))))
8.(remove-if-not #'evenp '(1 2 3 4))中,#'的意思是:The funny notation #' is shorthand for “Get me the function with the following name.” Without the #', Lisp would treat evenp as the name of a variable and look up the value of the variable, not the function.
那为什么用这么怪的名字呢?我想,撇号已经被拿来用来区分一个数据与代码,从而使有撇号的列表或者原子稍后求值,所以干脆就在撇号前加了个标识 :)
9.lisp有个地方的语法我觉得和lisp本身的语法有些自相矛盾,(defun foo (arg1 arg2) (+ 1 2)),这里foo后面的参数列表(arg1 arg2),如果按照lisp的语法,如果是数据的话应该是'(arg1 arg2),或者换另外一种方式来说,(arg1 arg2)中arg1是一个函数..
总结:
仔细阅读了第三章,然后又巨艰难地浏览第四章,最后又扫了接下来几张关于一些基本语法的章节。lisp总算入门了。但是依然无法运用它来写程序,接下来的计划是阅读例子的章节,这几个例子的章节就当作是实战,在实战中巩固学习lisp知识。
学到的教训:
挑重要的看,人的精力是有限的,不要死看书,挑重点,不用一行一行的死读书,多运用资源和工具,这样才比较又效率。多思考,多动手,多比较(比如查阅其他书籍类似主题的内容进行比较)等等。