Lisp
文章平均质量分 76
tinyid
Java/Python
Hadoop/Spark/Presto/Kafka/Druid
numpy/matplotlib/pandas/scipy
展开
-
Lisp.自下而上的编程
一个程序的函数元素不能太大是一个长期存在的编程风格原则。如果程序的某些组件增长到读难以理解的成都,它就变成一大堆的复杂东西,它们隐藏错误就像一个大城市隐藏逃亡者一样简单。这样的软件将很难读、很难测试、很难杀臭虫。遵循这个原则,一个大的程序必须被分成很多片,一个程序越大翻译 2011-09-15 18:48:07 · 1337 阅读 · 0 评论 -
Lisp.结构(Structure)
一个结构(structure)可以看成是一个加强版的向量(vector)。假设你需要写一个程序来跟踪许多长方体。你可能会考虑将它们表示成一个具有三个元素的向量:高,宽和长。如果你使用诸如如下的函数,而不是使用原始的svrefs,将使你的程序更加易读:[1]> (defun block-height (b) (svref b 0))BLOCK-HEIGHT你可以将一个结构看成是一个特殊翻译 2012-10-17 15:06:47 · 3026 阅读 · 0 评论 -
Lisp.编译(Compilation)
Common Lisp 函数可以单独被编译,也可以通过编译一个文件的形式被编译。如果你仅仅是在toplevel中键入了一个defun表达式,[1]> (defun foo (x) (+ x 1))FOO很多实现都会创建一个解释的函数。你可以通过将一个函数作为参数传递给compiled-function-p来判断它是不是已经被编译了:[2]> (compiled-function-p翻译 2012-10-31 21:51:06 · 2343 阅读 · 0 评论 -
Lisp.字符串和字符
字符串是字符的向量。我们把常量字符串看成是一系列被双引号包括的字符,一个单独的字符c被表示为#\c。通常(但不是必须的),每个字符都会有一个相关的整数,这个整数就是ASCII码。在多数的实现中,函数char-code返回与一个字符相关的数字,code-char返回对应数字的字符。函数char=(大于等于),char>(大于)和char/=(不同)用来比较字符。它们像数字比较翻译 2012-10-15 21:51:09 · 9434 阅读 · 0 评论 -
Lisp.中止(Aborts)
你可以使用return从一个block中的任何一点退出。有事我们想要做更极端的事情,并且在几个函数调用之间转移控制。我们通过catch和throw来完成这样的事情。一个catch表达式接收一个标签(tag),这个标签可以是任意的种类的对象,之后跟着一个表达式的主体(body)。【译注】:不由想到了“现代”编程语言中的try...catch...(defun super () (翻译 2012-10-22 18:38:07 · 1974 阅读 · 0 评论 -
Lisp.全局函数
之前的fboundp函数能够告诉我们一个给定的符号是不是已经是一个函数的名字。如果一个符号是一个函数的名字,symbol-function会返回这个函数:[1]> (fboundp '+)T[2]> (symbol-function '+)#通过设置某些名字的symbol-function到一个函数,[5]> (setf (symbol-function 'add2)翻译 2012-10-24 10:07:31 · 1708 阅读 · 0 评论 -
Lisp.闭包
一个函数可以作为一个表达式的值返回,就像其它对象一样。这里有一个接受一个参数的函数,返回对应参数类型的合并函数:(defun combiner (x) (typecase x (number #'+) (list #'append) (t #'list)))在这个函数之上,我们弄了一个通用的合并函数:(defun combine (&rest args)翻译 2012-10-25 11:55:11 · 2631 阅读 · 0 评论 -
Lisp.使用递归(Using Recursion)
相比于其它语言,在Lisp中递归扮演着更加重要的角色。这其中可能有三个主要的原因:1. 函数式编程。递归算法引入副作用的可能性看上去比较小。2. 递归数据结构。Lisp的隐式指针使得创建递归定义的数据结构变得简单。最普遍的就是列表:一个列表或者是nil,或者是一个cdr为列表的cons。3. 优雅。Lisp程序员非常关心他们的程序是否漂亮,而递归算法通常比它们的迭代版本更加优雅。...翻译 2012-11-05 14:31:04 · 2848 阅读 · 0 评论 -
Lisp.多值(Multiple values)
有人曾经说过,为了强调函数式编程语言的重要性,都要说每个Lisp表达式都返回一个值。现在事情没有那么简单了;在Common Lisp中,一个表达式可以返回0个或多个值。返回值的最大个数根据实现的不同而不同。多值允许函数计算并返回几个东西,并且不需要建立一个结构来保存它们。比如,内置的函数get-decoded-time返回当前的时间,这个时间用9个值来表示:秒,分钟,小时,日期,月,日翻译 2012-10-22 16:05:49 · 3362 阅读 · 0 评论 -
Lisp.类与实例(Classes and Instances)
我们需要两个步骤来创建结构(structures):首先调用defstruct来规划出结构的形式,然后使用类似make-point的函数来创建它们。创建实例也需要类似的两步。首先我们使用defclass定义一个类:(defclass circle () (radius center))这个定义是说circle的每个实例将会有两个槽(slots,就像结构中的字段-field),分别叫翻译 2012-11-27 11:19:19 · 1726 阅读 · 0 评论 -
Lisp.槽属性(Slot Properties)
defclass的第三个参数必须是一个槽定义的列表。最简单的槽定义,就像前一篇文章所看到的,就是一个标识名字的符号(symbol)。通常情况下,一个槽可以定义为一个列表,这个列表是由名字,和它所带有的一个或多个属性组成。属性以关键字参数的形式给出。通过定义一个槽的 :accessor ,我们就隐式地创建了一个引用那个槽的函数,这样就无需调用slot-value了。如果我们把circle翻译 2012-11-28 11:08:45 · 1667 阅读 · 0 评论 -
Lisp.理解递归
学习递归的学生有时会被鼓励在纸上跟踪递归函数的所有调用。这种练习可能会有误导:程序员定义一个递归函数的时候,通常不会考虑因为调用它而产生的所有调用。如果有人非得以这一的方式来考虑程序,那么递归就是令人烦恼的,这可没有什么帮助。递归的好处是它的精确性,它让我们以从更加抽象的方式来观察算法。你可以不用考虑调用函数时所产生的所有的调用,就能判断出一个递归函数是否是正确的。要探明一个递归函数是翻译 2012-10-14 22:35:32 · 2313 阅读 · 0 评论 -
Lisp.集合
列表是一种表示小集合的好方式。列表中的每一个元素是它所代表的集合中的一个成员:[1]> (member 'b '(a b c))(B C)当member返回真的时候,它不是简单地返回t,而是返回以它找的元素为首的列表的一部分。逻辑上,一个cons可以代表t,并且使用这种方式函数能够返回更多的信息。默认地,member通过eql来比对对象。你可以通过一种叫做关键字参数(翻译 2012-10-14 23:18:37 · 1482 阅读 · 0 评论 -
Lisp.可扩展的软件
Lisp风格的编程是随着软件复杂度的增长而增长的。高端用户现在要求程序做那么多的事情,以至于我们不能满足他们所有的需求。他们自己也不能完全满足他们自己的需求。但是如果我们不能给他们满足他们完全需求的软件,我们可以给他们可扩展的软件。我们将我们的软件从一个单一的程序编程一个编程语言翻译 2011-09-15 18:48:38 · 688 阅读 · 0 评论 -
Lisp.为什么使用Lisp
这些新的可能性并不是来自于一个新的神奇元素。在这个方面,Lisp就像是一个架构。到底是哪块楔形的石头(拱石)来管控这个架构呢?这个问题本身就是错误的;它们都在做。像一个架构,Lisp是一个连锁特征的集合。我们可以列出其中的一些特征——动态存储分配和垃圾回收,运行时类型,作为对象的翻译 2011-09-15 18:49:28 · 945 阅读 · 0 评论 -
Lisp.函数
函数是Lisp程序的构建块。它们也是Lisp的构建块。在多数的语言中+操作符和用户自定义函数是非常不同的。但是在Lisp中有一个单一模型,函数应用,来描述一个程序所要做的全部计算。Lisp的+操作符是一个函数,和你自己定义的函数一样。事实上,除了一小部分叫做特殊形式的翻译 2011-09-15 18:49:49 · 912 阅读 · 0 评论 -
Lisp.函数作为数据
两样东西使得Lisp函数不同。第一,上面提到的,Lisp自身就是一个函数的集合。这意味着我们可以向Lisp中加入我们自己的操作符。另外一个我们需要知道的关于函数的东西是它们是Lisp对象。Lisp提供了其它语言中能找到的多数的数据类型。我们知道整形和浮点型数字,字符串翻译 2011-09-15 18:50:14 · 957 阅读 · 0 评论 -
Lisp.定义函数
多数人通过defun来学习怎样定义函数。下面的表达式定义了一个叫做double的函数,这个函数返回它参数的两倍。[1]> (defun double (x) (* x 2))DOUBLE将这些传递给Lisp之后,我们可以在其它函数中调用double,或者直接在最高翻译 2011-09-15 18:50:45 · 1059 阅读 · 0 评论 -
Lisp.扩展Lisp
有两种方式来给Lisp添加新的操作符:函数和宏。在Lisp中,你定义的函数和内置的那些有一样的状态。如果你想要一个mapcar的变体,你可以自己定义一个,并像使用mapcar一样使用它。比如,如果你想要一个函数应用于1到10的变量后返回的一列值,你可以创建一个新的列表并将它传递给翻译 2011-09-15 18:49:05 · 1079 阅读 · 0 评论 -
Lisp.函数参数
将函数看做数据意味着,我们可以将它们作为参数传递给其它函数。这种能力是Lisp自下而上编程非常重要的一部分。一个允许函数作为数据对象的语言必须提供一些调用它们的方式。在Lisp中,这个函数就是apply。通常,我们向apply传递两个参数来调用它:一个函数,和这个函数翻译 2011-09-16 17:05:01 · 2832 阅读 · 0 评论 -
Lisp.可扩展的语言
不久前,如果你问LISP是用来做什么的,许多人将回答:“做人工智能的”。事实上,Lisp和AI的关系仅仅是一个历史的巧合。John Mcarthy发明了LISP,他也提出了了“人工智能”的概念。他的学生和同事都用LISP来写程序,然后LISP就被称为一门AI语言。这条线在20世纪翻译 2011-09-15 18:47:08 · 933 阅读 · 0 评论 -
Lisp.演进设计
因为Lisp给你自己定义你自己操作符的自由,你可以把它铸造成适合你需求的语言。如果你正在写一个文本编辑器,你可以将Lisp转化成一个写编辑器的语言。如果你正在写一个CAD程序,你可以将Lisp转化成写CAD程序的语言。如果你不知道你在写什么类型的程序,使用Lisp也是安全的尝试。翻译 2011-09-15 18:47:38 · 716 阅读 · 0 评论 -
Lisp.作为属性的函数
函数是Lisp对象的事实允许我们写出在运行时被扩展的程序。假设我们想要写一个函数,这个函数接受动物的类型作为参数并做一些对应的操作。在大多数语言中,要做到这点就是用case语句,我们在Lisp中也可以这样做:(defun behave (animal)(case anim翻译 2011-09-20 17:09:07 · 1326 阅读 · 0 评论 -
Lisp.超类(Superclasses)
defclass的第二个参数是一个超类的列表。一个类会继承它的所有超类的槽的并集。所以,如果我们想要定义一个screen-circle类,并且它是circle和graphic的子类,[2]> (defclass graphic () ((color :accessor graphic-color :initarg :color) (visible :accessor graphic-翻译 2012-11-29 13:31:30 · 1782 阅读 · 0 评论