newLISP你也行 --- 基础知识

  #############################################################################
  # Name:newLISP你也行 --- 基础知识
  # Author:黄登(winger)
  # Project:http://code.google.com/p/newlisp-you-can-do
  # Gtalk:free.winger@gmail.com
  # Gtalk-Group:zen0code@appspot.com
  # Blog:http://my.opera.com/freewinger/blog/
  # QQ-Group:31138659
  # 大道至简 -- newLISP
  #
  # Copyright 2012 黄登(winger) All rights reserved.
  # Permission is granted to copy, distribute and/or
  # modify this document under the terms of the GNU Free Documentation License,
  # Version 1.2 or any later version published by the Free Software Foundation;
  # with no Invariant Sections, no Front-Cover Texts,and no Back-Cover Texts.
  #############################################################################
 
 
  . 启动newLISP
 
 
      若是你要启动一个交互式的newLISP(如下简称nl)程序,只要在任何一个终端内敲入
  newlisp命令就好了.
 
  C:>newlisp
  newLISP v.10.4.0 on Win32 IPv4/6 UTF-8, execute 'newlisp -h' for more inf
 
  >
 
  这是后你就能够方便的测试单条语句了,若是须要测试多条语句.能够用两种方法:
 
 
  1: [cmd][/cmd]必须单独占一行.
  >[cmd]
- (define (fibonacci n)
-     (if (< n 2)
          1
-         (+ (fibonacci (- n 1))
             (fibonacci (- n 2)))))
  [/cmd]
  >
 
  2: 第一行单独输入一个回车.
  >
- (define (fibonacci n)
-     (if (< n 2)
          1
-         (+ (fibonacci (- n 1))
             (fibonacci (- n 2)))))
 
  >(fibonacci 10)
  89
 
 
      除了命令行的nl还能够启动图形界面的newLISP-GS editor,GS是newLISP提供的一个
  图形化工具包.WIN32的启动方法在上一节有讲解,详细资料请查阅guiserver.lsp.html.
  http://newlisp.org/index.cgi?Code_Contributions.同时提供了各类编辑器的配置本
  .
 
  . 三大基本法则
 
 
  法则 1: 列表是元素的序列:
  (Rule 1: a list is a sequence of elements)
 
 
  (1 2 3 4 5)         ; 包含数字的列表
  ("the" "cat" "sat") ; 包含字符串的列表
  (x y z foo bar)     ; 包含symbol的列表
  (sin cos tan atan)  ; 包含newLISP函数的列表
  (1 2 "stitch" x sin); 混合列表
  (1 2 (1 2 3) 3 4 )  ; 一个列表内包含另外一个列表
  ((1 2) (3 4) (5 6)) ; 列表的列表
 
 
      列表是newLISP的基础结构,同时也是咱们编写代码的方式.不过如今先别急着把上面
  的数据输入命令行测试,让咱们先把剩下的2个法则看完.
 
 
  法则 2: 列表的第一个元素是特殊的:
  (Rule 2: the first element in a list is special)
 
 
      newLISP会把列表中的第一个元素做为函数,剩下的元素做为这个函数的参数.
      法则2中的例子均可以输入命令行测试.
 
 
  (+ 2 2)
 
 
      这个列表中友3个元素,函数 + 和紧接其后的 2 个数字.nl在处理完这个列表后返回
  4 (of course).
 
 
  (+ 1 2 3 4 5 6 7 8 9)
 
 
      返回45,函数 + 把列表中全部的数字都加了起来.
 
 
  (max 1 1.2 12.1 12.2 1.3 1.2 12.3)
 
 
      返回12.3,列表中最大的数字 (理论上列表无长度限制).
 
 
  (print "the sun has put his hat on")
  "the sun has put his hat on"
 
 
      print打印字符串 "the sun has put his hat on" ,同时他的返回值也是他打印的
  字符串.这样你在控制台console上就会看到重复的2行字符串.
 
 
  > (println "九黎")
  九黎
  "\190\197\192\232"
 
 
      上面是在非utf8版本上的输出, println 在打印完字符串后还会打印一个换行符.
 
  > (println "轩辕")
  轩辕
  "轩辕"
 
 
      这个是在utf8版本上的输出,utf8版本的好处就是可以正常显示非ascii的多位字节
  文字.
      print函数能够将一系列的数据打印成一条字符串:
 
 
  > (print 1 2 "buckle" "my" "shoe")
  12bucklemyshoe"shoe"
 
 
      上面的代码打印了2个数字元素和3个字符串元素.(可使用 format 让输出更清晰)
      函数 directory 能够列出指定目录下的文件.
 
 
  (directory "/");unix
  (directory "c:/");win32
 
 
      上面的命令能够打印出系统根目录下的文件列表.若是不指定任何参数,则列出当前
  目录下的全部文件.
 
 
  >(real-path);获取当前目录的绝对路径
  "C:\\Program Files\\newlisp"
  > (real-path "newlisp_manual.html");获取指定文件的绝对路径
  "C:\\Program Files\\newlisp\\newlisp_manual.html"
  >(real-path ".");
  "C:\\Program Files\\newlisp"
 
 
      read-file 函数用来读取文本文件:
 
  (read-file "/usr/share/newlisp/modules/stat.lsp");unix
  (read-file "C:\\Program Files\\newlisp\\util\\link.lsp");win32
 
      在某些状况为了让输出更美观也能够用 println 打印出结果.
 
  (println (read-file "/usr/share/newlisp/modules/stat.lsp"))
 
 
      在咱们看第三个法则前,让咱们看一个更有用的东西.
 
 
  嵌套列表
 
 
      前面咱们已经看到了很多,一个列表中出现另外一个列表的状况.你是否是有点疑惑呢?
 
 
  > (* (+ 1 2) (+ 3 4))
  21
 
 
  newLISP遇到这个列表的时候,他的处理顺序是这样的:
 
      首先他看到了第一个元素 * ,把他做为一个函数,接着他要收集剩下的元素做为参数
  .但是他遇到了另外一个列表:
 
  (+ 1 2)
 
      nl果断暂停了以前的工做,进入这个列表里,开始处理这个列表,这个列表的结果就是
  3.很简单(不懂得同窗找个地方画圈圈去--!).
      好了又回到刚才第一层列表,继续为函数 * 收集参数,这时候又遇到了一个列表:
 
  (+ 3 4)
 
      nl一样很是果断的处理完了这个列表,又获得一个结果7.
      这时候两个内部的列表都计算出告终果,他们变成了下面的样子:
 
  (* 3 7)
 
      这下nl很是满意,再也没有嵌套列表了,一切都 "和谐",多清晰啊.
      nl计算出了最后结果21,并将他们返回给咱们.
      这个过程以下:
 
 
  (* (+ 1 2) (+ 3 4))
  (* (+ 1 2) 7)
  (* 3 7)
  21
 
      从第一行的6个括号,到第四行的0个括号,nl有条不紊的完成了全部的工做.
 
      不少同窗也许开始迷惑了,这怎么和咱们平时用的语言和计算的方法不对啊,嘿嘿.其
  实最真实的编译器原型就是这样滴,而别的语言作的就是把你们平时写的表达式分解成上
  面的这种形式,再作进一步的计算.固然若是你实在不习惯这样,nl也提供了内部函数,让
  你改变语法,这样你能够把nl假装成任何你喜欢的program language.
 
      当让若是你入门之后,你会发现这才是最正常的一种方式,那些说括号bt的人,10个有
  10个是没有真正学习lisp的.
 
      不论是从语法仍是编码来讲,括号都不是什么问题.
 
      也许你会担忧若是写了好几层括号会不会迷糊了?对于这个问题个人建议是:
 
  <1> 括号层不能太多,不少人是三层之后再也不加,把多余的功能分散到别的函数去.
 
  <2> 用个好点的编辑器.win的笔记本确定是不行,太掉价了,会严重影响形象.Emacs这样
  的你们伙我就不说了,基本上N多语言都有model,很强大很和谐.VIM嘛,这个既快又小.还
  notepad++,这个不少人说好啊,不过那个语法文件我整不出来,无视我吧.scite我只用
  这个,没啥说的,夸平台,小巧,界面简单.除了我须要的功能,其余的都不加,须要强大的能
  只要编写下lua脚本就好了.如今只要正常点得编辑器,都具备括号自动匹配.在好点得还
  有自动完成,指定提示.在scite里你按Ctrl+E就会跳到前括号对应的后括号,Ctrl+Shift+
  E能够选取括号内的内容.同时配上代码折叠和context.一切都会很轻松,基本不会出现,
  混乱.而你们只是须要先熟悉下这种函数前置的编码习惯就行了.
      记住,故事永远不会只有一个版本.
      括号就像一个思想容器,你能够加入任何东西,而你须要提取思想的时候,只要给他加
  如另外一个括号.(固然你也能够当作宇宙,太极,阴阳,天地......)
 
 
 
  法则 3:引号阻止计算:
  (Quoting prevents evaluation)
 
      要阻止nl计算就用单引号括起来.
      比较下面两行:
 
 
  (+ 2 2)
  '(+ 2 2)
 
 
      第二个列表前面多了个单引号.让咱们测试看看.
 
 
  > (+ 2 2)
  4
  >'(+ 2 2)
  (+ 2 2)
  >
 
 
      第一个例子,和前面同样,nl像日常同样,把第一个参数 + 做为函数,将后面两个参数
  加起来,返回数字4.
      第二个例子,nl看到了单引号 ' ,直接就讲后面的列表做为数据返回了,根本就不计
  算了.
 
      若是说第一个例子就像一个静止的宇宙,那单引号能作得就是copy整个宇宙,并把他
  做为数据返回给你,这样你就拥有了一个不会动的宇宙.固然你宇宙还能够转动起来.
 
      在什么状况下咱们须要阻止列表的 "内部" 计算呢?
      当你存储数据到列表中的时候.
 
 
  (2012 4 1) ;  今天的年/月/日
  ("winger" "黄登") ; 某人的名字
 
 
 
      咱们不但愿 2012 或者"winger" 被当作函数.由于他们都不是真的函数,也不多是
  真的函数,函数不能用数字或者双引号开头,不然nl会提示错误.因此咱们须要用到单引号
  .
 
 
  '(2012 4 1) ; 计算成 (2012 6 1)
  '("winger" "黄登") ; 计算成 ("winger" "黄登")
 
 
      其实单引号是函数quote的缩写形式:
 
  > '(2012 4 1)
  (2012 4 1)
  > (quote (2012 4 1))
  (2012 4 1)
  > (= ' quote)
  true
 
      记住他能够阻止后面列表的 "内部" 计算.
 
 
 
  Symbols 和 引号
  (Symbols and quotes)
 
 
      什么是Symbol?
      灵魂,符文...
 
      这个东西不翻译,很差翻译,记住就行了,毕竟没几个关键字.翻译过来还别扭.
      Symbol就像一个个灵魂,一个灵魂一个装下一个宇宙,一个宇宙内又有千千万万个宇
  .灵魂的力量是强大的,世界全部的东西都能装下,而Symbol也是强大的,任何数据都能
  装下,他就像个容器.又像个标志.若是实在要类比,他和别的语言中变量很相像.
 
 
  >(define alphabet "abcdefghijklmnopqrstuvwxyz")
  "abcdefghijklmnopqrstuvwxyz"
  >(set   'alphabet "abcdefghijklmnopqrstuvwxyz");这只是set的语法要求
  "abcdefghijklmnopqrstuvwxyz"
  >(setf   alphabet "abcdefghijklmnopqrstuvwxyz")
  "abcdefghijklmnopqrstuvwxyz"
 
 
      上面三条语句干的活是同样的,建立一个symbol,并把英文字母表赋值给他.
      如今只要有语句调用, alphabet 就被自动计算成26个字母的字符串.当让你不能在
  他前面加上单引号.
 
 
  >(upper-case alphabet)
  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 
 
      由于咱们须要用到alphabet的值,因此咱们没有给他加上单引号,不然传递给
  upper-case 的就是一个symbol名了,咱们要得是symbol值.欧了没?
 
      newLISP并不像别的语言那样频繁的使用symbol来保存值.由于nl的哲学就是,代码即
  数据,数据即代码.这样的结果就是代码更短,写的更爽.
 
 
  >(println (first (upper-case alphabet)))
  "A"
 
 
      upper-case 将返回值传递给 first 函数, first 函数再将返回值传递给println ,
  打印出来.
 
      固然仍是有不少地方要用到symbol的:
  (define x (+ 2 2 ))
  (define y(+ 2 2))
 
 
 
 
  >(define x (+ 2 2 ))
  4
 
      第一行咱们没有使用单引号,nl想日常同样计算(+ 2  2) ,而后把返回值4赋值给x.
 
  >(define y '(+ 2 2))
  (+ 2 2)
 
      第二行咱们使用了单引号,这样nl就把这个list (+ 2 2) 赋值给了y(并不计算).
 
  >x
  4
 
  >y
  (+ 2 2)
 
  >'y
  y
 
      最后这个'y 就是symbol名. 而上面那个则是symbol值.
 
  . 破坏性函数
  (Destructive functions)
 
      在nl内部,有的函数会改变操做的symbol,这样的函数就就叫作破坏性函数,好比
  pushreplace .
 
  >(setf m 25)
  25
 
  >(+ m 1)
  26
 
  >m
  25 ;m没有改变仍然是25
 
  >(inc m)
  26
 
  >m
  26 ;m被改变了,inc就被称为破坏性函数,若是要用这样的函数又不想改变原来的symbol
     ;你就要这样写:(inc (copy m))
 
 
  o了吃饭去.
 
  2012-04-02 21:33:27
 
  html 彩色版本请看 http://code.google.com/p/newlisp-you-can-do                                
相关文章
相关标签/搜索