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,这样的函数就就叫做破坏性函数,比如
  push 和 replace .
 
  >(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
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

转载于:https://my.oschina.net/darkcode/blog/60381

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值