Lisp 入门
POSTED ON FEB 25, 2017
心血来潮, 想学下 Lisp 或者 Haskell, 正好发现了Build Your Own Lisp 这本书, 所以先从 Lisp 入手.基本概念
表达式要用括号 () 括起来, 括号中第一项内容为操作符, 后面的是它的操作域(操作数). 这种便是方法称为前缀表示法, 也叫波兰表示法.(+ 1 2)
(sqrt 16)
数学上, 函数用 f(x) 表示, 在 lisp 中, 也要使用前缀表示法表示:(f x) ;f(x)
(g x y) ;g(x, y)
(h (g x)) ;h(g(x))
(< 3 4) ;比较大小, 3 < 4
(and T T) ;true and true
(or NIL T) ;false or true
(or (< 3 4) (> 3 4)) ;3 < 4 or 3 > 4
表
Lisp 即所谓的 List procesor, 表处理语言. 上文中出现的括号, 都是表. 原子是不包含空格的字符, 不如上面的 +, sqrt, 操作数等等, 表里面 不见得都是原子元素, 表是可以嵌套的, 比如上面最后一个 or 操作, 就属于嵌套表.表的大小没有限制, 最简单的 () 是一个空表, 空表是 Lisp 里面既是表又 是原子的东西. 当原子讲的时候, 表示逻辑假(NIL). 上文中, 我们还遇到了 T, 这个表示逻辑真.程序和数据
编程就是写一些程序, 处理数据. 在 Lisp 中, 程序和数据都用表来表示. 但是表示程序的表, 第一项一定是一个操作符, 否则就会报错:(+ 1 2) ;正常的 lisp 程序
(1 2 3) ;这个第一项不是操作符, 会报错
表示数据的表现不需要以操作符开头, 但是, 我们需要告诉 lisp 解释器, 不要试图计算这些数据表项的值, 这里用到了 quote 操作符.(quote (1 2 3))
'(1 2 3)
上面两种写法是等价的, 下面写起来更简单, 键盘会坏的慢一些.Lisp 里面不区分大小写, 如果我们在 REPL 里面输入 '(Hello World), 我们会得到 (HELLO WORLD) 作为输出.基本操作
CAR 取表的第一项
CAR 操作符用来提取表的第一项.(car '(1 2 3)) ;输出1
(car '((1 2) 3)) ;输出(1 2)
CDR 删除表的第一项
CDR 用于删除表的第一项.(cdr '(1 2 3)) ;输出(2 3)
(cdr '((1 2) 3)) ;输出(3)
CXR 组合操作
所谓 CXR 组合操作, 就是 CAR 和 CDR 的结合使用, 灵活使用, 可以取表的第二项, 第三项…(car (cdr '(1 2 3))) ;输出2
(cadr '(1 2 3)) ; 同上, 输出2(cdr (car '((1 2) 3))) ;输出(2)
(cdar '((1 2) 3)) ; 同上, 输出(2)
类似的, 还可以组合出来CDAAR, CADDR … 一系列的操作出来. 作为初学者, 这么多括号我已经晕菜了, 难怪会有彩虹括号这种东西出现…CONS
上面的操作是用来拆分一个表的, 现在试着用 cons 来合并表.(cons (1) 2) ;输出(1 . 2)
(cons 1 (2)) ;输出(1 2)
我们說括号扩起来的语句叫做表, 这种执行运算的也叫做 S-表达式, 表表示的实际上是一个二叉树, 在 S-表达式 里面, 这种二叉树记为 (Left . Right) 如果左支是一个表, 那么, 就会记做 ((Left) . Right), 如果右支是一个表, 那么记做 (Left . (Right)), 这种右支还可以把点号省略记做(Left Right)上面的 CDR 操作会删掉表的第一项, 实际上它做的工作是取出表除了第一项之外后面 的项, 按照上面的解释, 这个操作取的实际上是这个二叉树的右子树.APPEND 合并两个表
cons 是在左右子树上进行的合并操作, append 将会在右子树上添加新的节点. 比如(append '(1 2) '(3 4)) ;输出(1 2 3 4) <=> (1 . (2 3 4))
(cons '(1 2) '(3 4)) ;输出((1 2) 3 4) <=> ((1 2) . (3 4))
LIST 函数
list 函数会将所有传递给它的参数都放到一个表里面, 然后返回它.(list '(1) 2 3 '(4 5)) ;输出 ((1) 2 3 (4 5))
再看原子
原子可以是任何数, 分数, 小数, 自然数, 负数等等. 原子可以是一个字母排列, 当然其中 可以夹杂数字和符号. 空表就是原子NIL.判断一个元素或者一个字符是不是原子, 可以使用 atom 运算符.(atom 'a) ;输出 T
(atom '(a b)) 输出: NIL
变量赋值可以使用 setq 运算符. setq 运算符的作用就是将紧接着的变量赋值, 这个赋值语句的返回值是这个变量被赋予的值.(setq a 5)
(+ a 7) ;输出 12
(cons a '(1)) ;输出 (5 1)
断言函数
断言函数包括前面遇到的 atom 函数, 以及这里将要介绍的 null 和 equal 函数.null 函数判断一个表达式是否为 NIL, 是返回 T, 否则返回 NIL.equql 函数判断两个值是否完全相等.(null ()) ;输出T
(null 'a) ;输出NIL
(null (- 1 1)) ;输出NIL
(equal 'a 'b) ;输出NIL
(equal 'a 'a) ;输出T
(equal (+ 1 2) 3) ;输出 T
定义自己的函数
defun 操作符用来定义自己的函数, 其形式为:(defun function_mame (arg1 arg2 ...)(function_body)
)
函数的返回值是 function_body 运算完成之后的那个值. 比如:(defun addition (x y)(+ x y)
)(addition 1 2)
在 REPL 输入以上代码, 将会得到加法运算结果: 3下面介绍两个系统自带函数: first, last.first 就是我们前面预见的 car 函数. cdr 对应的叫做 rest, 而这里的 last 取的是右子树(或者左子树, 如果没有右子树的话)最后一个节点.接下来我们定义一个函数, 取列表的首尾两个元素.(defun ends (l)(cons (first l) (last l))
)
条件操作符
cond 表示条件操作符.cond 操作符有些复杂, 它的形式为(cond 分支列表1 分支列表2 分支列表3 ... 分支列表N)
而其中分支列表的构成为 (条件p 值e)cond 操作符将对每一个”条件p”求值, 如果为NIL. 就接着求下一个, 如果为真, 就返回相应的”值e”, 如果没有一个真值, cond 操作符返回 nil. cond 操作 符的参数可以不止两个(cond (nil 1) (nil 2) (t 3)) ;输出3
(cond (a 1) (nil 2) (t 3)) ;输出1
利用条件操作符实现的最大值求值(defun max_number (a b)(cond ((> a b) a) (1 b))
)
上面这段代码也可以写成下面这样, 下面这段使用了 if 函数.(defun max_number (a b)(if (> a b) a b)
)
递归函数
比如要求等差数列 a(n) = a(n-1) + 2 的第 N 项. 那么, 递归函数可以定义为:(defun desq (n)(if (= n 0) 0 (+ (desq (- n 1)) 2))
)
递归函数这里 lisp 提供了一个 trace 函数来帮助查看函数调用栈.lisp> (trace desq)
lisp> (desq 4)# 我们得到了一下输出
1. Trace: (DESQ '4)
2. Trace: (DESQ '3)
3. Trace: (DESQ '2)
4. Trace: (DESQ '1)
5. Trace: (DESQ '0)
5. Trace: DESQ ==> 0
4. Trace: DESQ ==> 2
3. Trace: DESQ ==> 4
2. Trace: DESQ ==> 6
1. Trace: DESQ ==> 8
8
lisp 里面的7大公理(七个操作符)
Lisp有7个基本操作符(实际上或许可以再精简). 这7个基本操作符就像几何中的 公理一样, 任何其他函数都可以由这七大公理定义. 也就是说, 7个基本操作符包 含了 Lisp 的所有语义.这7个基本操作符是:Quote
Atom
Eq
Car
Cdr
Cons
Cond

Lisp入门(好文)相关推荐

  1. FreeMarker中文帮助手册API文档,基础入门学习文档

    FreeMarker中文帮助手册API文档,基础入门学习文档 分类: 编程技术 发布: bywei 浏览: 7 日期: 2011年5月28日 分享到: QQ空间 新浪微博 腾讯微博 人人网 什么是Fr ...

  2. python中集合运算_入门 | 一文带你了解Python集合与基本的集合运算

    原标题:入门 | 一文带你了解Python集合与基本的集合运算 选自DataCamp 作者:Michael Galarnyk 参与:Geek Ai.思源 一般我们熟悉 Python 中列表.元组及字典 ...

  3. kotlin入门学习文档

    kotlin入门学习文档 前言:本文会着重对比java和kotlin,方便Java选手理解 提前总结:kotlin在服务端应用本质上是基于Java进行的改进,底层都是由JVM翻译成底层语言,我们只需要 ...

  4. pcie中文入门学习文档资料

    网上转载的整理pcie中文入门学习文档和资料,作为备份: 目录如下: 1.前言篇:PCIe扫盲--PCIe简介:http://blog.chinaaet.com/justlxy/p/510005306 ...

  5. 人工智能,机器学习,深度学习入门好文,强烈推荐

    让我们从机器学习谈起 导读:在本篇文章中,将对机器学习做个概要的介绍.本文的目的是能让即便完全不了解机器学习的人也能了解机器学习,并且上手相关的实践.当然,本文也面对一般读者,不会对阅读有相关的前提要 ...

  6. 入门 | 一文介绍机器学习中基本的数学符号

    本文介绍了机器学习中的基本数学符号.具体来说有算数符号,包括各种乘法.指数.平方根以及对数:数列和集合符号,包括索引.累加以及集合关系.此外,本文还给出了 5 个当你在理解数学符号遇到困难时可以应急的 ...

  7. linux输入法_超强两笔输入法 入门简文

    超强两笔 超强两笔(原名超强二笔)是付东升发明的全分阴阳的二笔输入法,于2005年2月25日正式推出.超强两笔的独体字首创三码末规则.合体字首创全分阴阳规则,使拆字变得简单直观:不断优化的词库,让用户 ...

  8. Linux运维大牛带你认识真正 Linux 系统结构!超强入门技术文!

    Linux系统一般有4个主要部分:内核.shell.文件系统和应用程序.内核.shell和文件系统一起形成了基本的操作系统结构,它们使得用户可以运行程序.管理文件并使用系统. 1Linux 内核 内核 ...

  9. Linux入门参考文档(超详细)

    一.Linux简介与安装 1.1 计算机的相关概念 1. 什么是计算机 能够接收使用者输入的指令与数据,经由中央处理器的算术与逻辑单元运算处理后,以产生或存储有用的新数据.比如计算器,手机,汽车导航系 ...

最新文章

  1. ASP.NET MVC以ValueProvider为核心的值提供系统: DictionaryValueProvider
  2. 实验八 接口与实现接口的类
  3. mysql php7安装配置_centos7无网络下安装部署php7.1.33+mysql5.7.28+apache2.4.6-Go语言中文社区...
  4. 你解决的问题比你编写的代码更重要! 1
  5. Stopping ADB server failed(code -1)
  6. 研发工程规范性模型-DevSecOps
  7. 深度学习2-keras模型训练
  8. WhatsApp拟取消服务订阅年费
  9. AIR移动平台打开图片文件
  10. Vue中用到jeDate日期控件,Vue对象中的值滞后,总是滞后当前选择的值
  11. mysql 性能指标计算_干货|MySQL 性能指标及计算方法总结
  12. android自动适应横屏,Android屏幕适配(一)--自定义View屏幕适配
  13. mac电脑如何装双系统Linux,mac怎么装双系统|mac电脑安装双系统教程
  14. 李开复--生命是最严厉的导师
  15. 厉害了!北大3位硕博生搞出ChatGPT版Excel!动动嘴就能自动处理表格……免费用!...
  16. Dwr概述与入门讲解
  17. Git安装【Windows环境安装配置】详细教程
  18. Assignment 2: UDP Pinger[课后作业]
  19. 拼车 vs 乘坐公交
  20. 深度学习论文笔记(1):Overfeat-2019/03/02

热门文章

  1. vue监听滚动事件,实现滚动监听
  2. hadoop集群安装配置
  3. ip subnet-zero
  4. Kibana和logstash实时日志查询、收集与分析系统
  5. 机器学习--组合分类方法之AdaBoost算法
  6. Vue学习笔记之16-tarbar地开发思路
  7. mysql reset_mysql的reset命令
  8. python内存数据库触发器_Python内存数据库/引擎
  9. Java--对象复制
  10. 【06月18日】A股滚动市净率PB历史新低排名