matlab lisp,LISP-12953284-51CTO博客

Lisp,最初被拼为LISP,一个历史悠久的电脑编程语言家族。最早由约翰·麦卡锡在1958年基于λ演算创造,演化至今,是历史第二悠久的高级语言,仅次于Fortran,也是第一个函数式编程语言。

其名称源自列表处理器(英语:List Processor)的缩写。LISP有很多种方言,各个实现中的语言不完全一样。LISP语言的主要现代版本包括Common Lisp, Scheme,Racket以及Clojure。1980年代盖伊·史提尔二世编写了Common Lisp试图进行标准化,这个标准被大多数解释器和编译器所接受。还有一种是编辑器Emacs所派生出来的Emacs Lisp(而Emacs正是用Lisp作为扩展语言进行功能扩展)非常流行,并创建了自己的标准。

目录

[隐藏]

1 历史2 基本介绍

2.1 Lisp的7个公理(基本操作符)

2.1.1 基本操作符1 quote2.1.2 基本操作符2 atom2.1.3 基本操作符3 eq2.1.4 基本操作符4 car2.1.5 基本操作符5 cdr2.1.6 基本操作符6 cons2.1.7 基本操作符7 cond 2.2 函数 3 语法和语义4 Scheme的Hello World程序5 Common Lisp的Hello World程序6 Clojure的Hello World程序7 Lisp的宏

7.1 简易宏示例 8 注释9 参见10 外部链接

历史

1955年至1956年间,信息处理语言被创造出来,用于人工智能处理(早期的基于符号处理的人工智能领域,以图灵测试为目标)。此领域中有研究者持有观点:“符号演算系统可以派生出智能。”[1])。它首先使用了列表 (抽象数据类型)与递归。

1958年,约翰·麦卡锡在麻省理工学院发明了Lisp这个编程语言,采用了信息处理语言的特征。1960年,他在《ACM通讯》发表论文,名为《递归函数的符号表达式以及由机器运算的方式,第一部》(Recursive Functions of Symbolic Expressions and Their Computation by Machine, Part I)。在这篇论文中,他展示了,只要通过一些简单的运算符,以及用于函数的记号,就可以创建一个具图灵完备性语言,可用于算法中。

麦卡锡最初使用M表示式(M-expression)写成代码,之后再转译成S表示式,举例来说,M表示式的函数语法,car[cons[A,B]],等同于S表示式的(car (cons A B))。然而由于S表示式具备同像性的特性(homoiconic,即程序与数据由同样的结构存储),实际应用中一般只使用S表示式。此外,他也由借用了信息处理语言中的许多概念。

约翰·麦卡锡的学生史帝芬·罗素在阅读完此论文后,认为Lisp编程语言当中的eval函数可以用机器码来实做。他在IBM 704机器上,写出了第一个LISP解释器。1962年,蒂姆·哈特(Tim Hart)与麦克·莱文(Mike Levin)在麻省理工学院,以Lisp语言,实做出第一个完整的lisp编译器。

基本介绍

LISP是第一个函数式程序语言,区别于C语言、Fortran等命令型程序语言和Java、C#、Objective-C等面向对象程序语言。

由于历史的原因,Lisp长期以来被认为主要用于人工智能领域,但Lisp并不是只为人工智能而设计,而是一种通用的程序语言。

Lisp的表达式是一个原子(atom)或表(list),原子(atom)又包含符号(symbol)与数值(number);表是由零个或多个表达式组成的序列,表达式之间用空格分隔开,放入一对括号中,如:

abc

()

(abc xyz)

(a b (c) d)

最后一个表是由四个元素构成的,其中第三个元素本身也是一个表,这种list又称为嵌套表(nested list)。

正如算数表达式1+1有值2一样,Lisp中的表达式也有值,如果表达式e得出值v,我们说e返回v。如果一个表达式是一个表,那么我们把表中的第一个元素叫做操作符,其余的元素叫做自变量。

Lisp的7个公理(基本操作符)

基本操作符1 quote

(quote x)返回x,我们简记为'x

(quote a)

上面的表达式的值是a。如果使用C语言或者Java语言的表达方式,可以说成:上面这段代码返回的值是a。

'a

这个表达式和上面的那个相同,值也是a。将quote写成 ' 只是一种语法糖。

被quote起来的单一个元素会成为symbol(例如'a)。symbol是Lisp中的一个特别概念,他在代码中看起来是个string,但并不尽然,因为symbol其实会被Lisp解释器直接指向某个存储器位置,所以当你比较'apple和'apple两个symbol是否相同时,不需要像是比较string一样一个个字元逐字比较,而是直接比较存储器位置,故速度比较快(使用eq运算符来比较,如果使用equal运算符会变成逐字比较)。当你定义一个函数,或者定义一个变量时,他们的内容其实就是指向一个symbol。

基本操作符2 atom

(atom x)当x是一个atom或者空的list时返回原子t,否则返回NIL。在Common Lisp中我们习惯用原子t表示真,而用空表 () 或NIL表示假。

> (atom 'a)

t

> (atom '(a b c))

NIL

> (atom '())

t

现在我们有了第一个需要求出自变量值的操作符,让我们来看看quote操作符的作用——通过引用(quote)一个表,我们避免它被求值(eval)。一个未被引用的表达式作为自变量,atom将其视为代码,例如:

> (atom (atom 'a))

t

这是因为(atom 'a)的结果(t)被求出,并代入(atom (atom 'a)),成为(atom t),而这个表达式的结果是t。

反之一个被引用的表仅仅被视为表

> (atom '(atom 'a))

NIL

引用看上去有些奇怪,因为你很难在其它语言中找到类似的概念,但正是这一特征构成了Lisp最为与众不同的特点:代码和数据使用相同的结构来表示,只用quote来区分它们。

基本操作符3 eq

(eq x y)当x和y指向相同的对象的时候返回t,否则返回NIL,值得注意的是在Common Lisp中,原子对象在内存中只会有一份拷贝,所以(eq 'a 'a)返回t,例如:

>(eq 'a 'a)

t

>(eq 'a 'b)

NIL

> (eq '() '())

t

> (eq '(a b c) '(a b c))

NIL

基本操作符4 car

Contents of the Address part of Register number缩写

(car x)要求x是一个表,它返回x中的第一个元素,例如:

> (car '(a b))

a

基本操作符5 cdr

(cdr x)同样要求x是一个表,它返回x中除第一个元素之外的所有元素组成的表,例如:

> (cdr '(a b c))

(b c)

基本操作符6 cons

(cons x y)返回一个cons cell(x y),如果y不是一个list,将会以dotted pair形式展现这个cons cell,例如:

>(cons 'a 'b)

(a . b)

一个cons cell的第二项如果是另一个cons cell,就表示成表的形式,例如:

(cons 'a (cons 'b 'c))

就表示成 (a b . c) 若一个cons cell第二项为空,就省略不写,例如:

(cons 'a  (cons 'b ()))

表示为 (a b) 这样,多重的cons cell就构成了表:

> (cons 'a (cons 'b (cons 'c ())))

(a b c)

基本操作符7 cond

(cond (p1 e1) ...(pn en))的求值规则如下.对“条件表达式p”依次求值直到有一个返回t.如果能找到这样的p表达式,相应的“结果表达式e”的值作为整个cond表达式的返回值.

> (cond ((eq 'a 'b) 'first)  ((atom 'a)  'second))

second

函数

七个原始操作符中,除了quote与cond,其他五个原始操作符总会对其自变量求值.我们称这样的操作符为函数.

语法和语义

Scheme的Hello World程序

(display "Hello, world!")

;; 在屏幕中打印出: Hello, world!

;; 函数定义

(define (hello)

(display "Hello, world!"))

;; 函数调用

(hello)

;; 在屏幕中打印出: Hello, world!

Common Lisp的Hello World程序

(format t "hello, world!")

;; 在屏幕中打印出: hello, world!

函数定义:

(defun hello-world ()

(format t "hello, world!"))

调用函数:

(hello-world)

;; 在屏幕中打印出: hello, world!

;; 并以NIL作为函数的返回值

Clojure的Hello World程序

(print "hello, world!")

;; 在屏幕中打印出: hello, world!

;; 函数定义:

(defn hello-world []

(print "hello, world!"))

;; 调用函数:

(hello-world)

;; 在屏幕中打印出: hello, world!

;; 并以 nil 作为函数的返回值

Lisp的宏

Lisp的语法结构使数据与程序只是一线之隔(有quote就是数据,没quote就是程序)。由于Lisp这种“数据即程序、程序即数据”的概念,使Lisp的宏(Macro)变得非常有弹性:你可以定义宏,指定它应该被编译器翻译(宏展开)成什么程序,程序和数据都可以灵活地互相转换,最后展开的代码会成为整个程序的一部分。宏的实现非常倚重quote来达成。当你定义了一个宏,宏被quote的部分会先被编译器unquote,而没有quote、或已经被unquote的部分,则会先被求值。最终编译器生成的整个程序代码才是最后运行时的代码。以下以广泛使用的Emacs Lisp为示例(以下示例亦兼容Common Lisp),解释最基本的Lisp宏。

想要创建一个list并赋予给fruit这个变量时不能这样做,因为这个list没有被quote过,会被编译器视为“程序”运行(会把"apple"这个字符串当成函数解释),而不是“数据”,因而产生错误:

> (setq fruit ("apple" "banana" "citrus"))

錯誤:"apple" 不是一個有效函數。

但这样就正确了:

> (setq fruit (quote ("apple" "banana" "citrus")))

("apple" "banana" "citrus")

;; 或者

> (setq fruit '("apple" "banana" "citrus"))

("apple" "banana" "citrus")

;; 也可以用(list...)運算子,這樣一樣可以建立list。因為list本身是個函數,本來就應該被當成程式執行而不是資料,所以不會報錯:

> (setq fruit (list "apple" "banana" "citrus"))

("apple" "banana" "citrus")

前面有提到使用'符号这个语法糖能够代替quote,但还有另外一种符号是`,意义基本上与'相同,但被`包起来的部分可以再用来unquote;而'没有这种能力。

也就是说被`给quote起来的部分是数据,但使用逗号“,”来unquote,令被quote的数据变回程序。(注意quote只有一个arg,所以arg要用list包起来)

;; 使用`來quote整個list

> `("apple" "banana" "citrus")

("apple" "banana" "citrus")

;; 使用逗號,來unquote,這樣fruit這個變量會被重新求值。

> `("apple" "banana" "citrus" ,fruit)

("apple" "banana" "citrus" ("apple" "banana" "citrus"))

;; 可以利用unquote的特性,定義一個函数,讓該函数根據輸入的參數回傳一個我們想要的list数据結構:

(defun user-profile (name email mobile)

`((name . ,name)

(email . ,email)

(mobile . ,mobile)))

(user-profile "Richard" "[email protected]" "Noooo!")

=> ((name . "Richard")

(email . "[email protected]")

(mobile . "Noooo!"))

简易宏示例

这里定义一个宏叫做nonsense,这个宏可以方便地定义更多以nonsense为开头的新函数:

(defmacro nonsense (function-name)

`(defun ,(intern (concat "nonsense-" function-name)) (input) ;intern可以將string轉成symbol

(print (concat ,function-name input))))

;; 解釋:

;; 這個宏在編譯時,`(defun  因為被quote所以不會被求值,

;; 但裡面的,(intern ...) 這一段從逗號開始,整個括號括起來的

;; s-expression部份會被求值。這時作為argument輸入的function-name

;; 就是在這時被插進macro中。其餘剩下的部份因為仍然在`(defun的quote

;; 影響之下,並不會被求值。

;; 現在宏展開完了,整個宏才被當成一般function執行。

(nonsense "apple") ;使用我們剛剛定義的 nonsense 這個macro來定義新的f函数

=> nonsense-apple  ;成功定義出了新的函数叫做 nonsense-apple

(nonsense "banana") ;再使用一次宏來定義新的函数叫做 nonsense-banana

=> nonsense-banana  ;成功定義了新的函数。

(nonsense-apple " is good")        ;使用剛剛定義出的新函数

=> "apple is good"

(nonsense-banana " I love to eat")    ;使用另一個剛剛定義函数

=> "banana I love to eat"

注释

^ 徐宥,《LISP语言是怎么来的–LISP和AI的青梅竹马A》 《LISP语言是怎么来的–LISP和AI的青梅竹马B》

参见

您可以在

维基教科书中查找此百科条目的相关电子教程:

Lisp入门

Common LispSchemeSICPClojure

外部链接

Lisp中文社区John McCarthy的主页Paul Graham's The Roots of LispRacket官网

[隐藏]

查  论  编

编程语言分类

按平台

.NET框架平台语言

C++/CLI C# F# IronPython IronRuby J# Visual C# VB.NET Small Basic

Java虚拟机上的语言

Java Jython JRuby JScheme Groovy Kawa Scala Clojure

按家族

C/C++语言

C C++ Turbo C++ Borland C++ C++ Builder - C++/CLI Visual C++组件扩展 Objective-C Visual C++

BASIC语言

有行号

BASIC BASICA GW-BASIC ETBASIC GVBASIC

无行号

QBASIC QuickBASIC True BASIC Turbo BASIC PowerBASIC FreeBasic DarkBASIC Visual Basic Gambas VB.NETVBScript VBA REALbasic Small Basic

Pascal/Delphi语言

Pascal Turbo Pascal Object Pascal Free Pascal Delphi Lazarus

按范式

声明式

函数式

Lisp家族

LISP Scheme Common Lisp Clojure Racket

ML家族

ML Standard ML OCaml F#

Haskell Scala Erlang Clean Miranda Logo

逻辑式

Prolog

命令式

结构化

过程式

BASIC Fortran C Pascal Go

面向对象

Smalltalk Java C# Objective-C C++ Eiffel Python Ruby

非结构化

COBOL

元编程

泛型/模板

C++ D Eiffel

反射化

ECMAScript Java Perl PHP Python R Ruby

脚本语言

Lua Perl PHP Python Ruby ASP JSP Tcl/Tk VBScript AppleScript AAuto(基于Lua)

ECMAScript派生语言

ActionScript DMDScript ECMAScript JavaScript JScript TypeScript

Shell语言

sh bash sed awk PowerShell csh tcsh ksh zsh

专业工具语言

科学与统计计算

FORTRAN MATLAB Scilab GNU Octave R S-Plus Mathematica Maple Julia

GPU用着色器语言

Cg GLSL HLSL

数据库相关编程语言

xBase

Clipper Visual FoxPro    SQL

PL/SQL T-SQL SQL/PSM    LINQ XQuery

标记语言

SGML家族

XML家族

XML SVG XML Schema XSLT XHTML MathML XAML SSML

SGML HTML

Curl

工业与辅助设计

AutoCAD

其它

汇编语言 ALGOL APL/J Ada Falcon Forth Io MUMPS PL/I PostScript REXX SAC Self Simula 易语言 Swift语言

你可能感兴趣的:(matlab,lisp)