--
Lisp-cn(Lisp中文用户组)
CLUG http://lisp.org.cn
只是想改变下偶的程序设计观
Wrong wrong wrong, 你应该来上次的 lisper meetup 听我的第二个演讲的:)
> Common Lisp其实并不是传说中的函数式语言,或者更准确的说,是支持函数式的多范性编程语言,绝大多数时候,你编写的程序还是命令式的,就和用php,
> javascript编程其实差不多。好处仅仅只是语法十分简单,但同时也牺牲了不少可读性。
very wrong.
> 简单点的教程:Practical Common Lisp
> LISP系个人感觉最简单的编程语言:LOGO
>
> LISP是一个大家族,跟Common Lisp是两个概念。
>
> 如果要改变编程观念,也许以下语言可以参考,这些语言让你不得不换一种思路来编程(习惯的力量时强大的,只有当你被逼迫的时候,才能学会一种新的思路):
> Haskell -
> 流行的纯函数式编程语言,较有名的实现,如GHC。另外,如OCaml等编程语言,尽管支持多范性,但是如果不使用纯函数式编程会需要比较麻烦的方法(其实Haskell也是如此)。
> ISO Prolog - 流行的纯逻辑式编程语言,较有名的实现,如BProlog, SWI-Prolog, GNU Prolog, 等
> 当然还有很多基于其它计算模型的编程语言,只不过如上的两种类型是最常被提到的。
>
比较的方法就是真正做一些项目!然后你就明白灵活性是多么重要了。
Cheers,
--
黄 澗石 (Jianshi Huang)
http://huangjs.net/
最近非常忙,我只能稍微提一些。
1) code as data (这点你说了,但像 lisp 这般彻底的没有,专业一点叫 homoiconic programming language)
2) reflection,几乎所有编程需要的信息都可以在 runtime 里得到,bindings info (var, func,
macro, etc.),types,declarations,source code!
3) composability,基本上所有的都是 expressions
以上组成了强大的 generative programming 工具。
>> > Common
>> > Lisp其实并不是传说中的函数式语言,或者更准确的说,是支持函数式的多范性编程语言,绝大多数时候,你编写的程序还是命令式的,就和用php,
>> > javascript编程其实差不多。好处仅仅只是语法十分简单,但同时也牺牲了不少可读性。
>>
>> very wrong.
>>
当你用 javascript 的方式写 lisp 程序,可读性自然上不去。
2012/1/25 Xiaofeng Yang <n.akr....@gmail.com>:
> 我很希望能听到你的详细观点,而不是简单的一个“wrong”。
>最近非常忙,我只能稍微提一些。
>> 2012/1/25 Xiaofeng Yang <n.akr....@gmail.com>:
>> > Common Lisp也许能改变一下你的一部分编程观念,但是不算很多。就算fans沾沾自喜的宏、REPL等其实在很多常见的语言都有同类的东西。
>>
>> Wrong wrong wrong, 你应该来上次的 lisper meetup 听我的第二个演讲的:)
>>
1) code as data (这点你说了,但像 lisp 这般彻底的没有,专业一点叫 homoiconic programming language)
2) reflection,几乎所有编程需要的信息都可以在 runtime 里得到,bindings info (var, func,
macro, etc.),types,declarations,source code!
3) composability,基本上所有的都是 expressions
以上组成了强大的 generative programming 工具。
当你用 javascript 的方式写 lisp 程序,可读性自然上不去。
>> > Common
>> > Lisp其实并不是传说中的函数式语言,或者更准确的说,是支持函数式的多范性编程语言,绝大多数时候,你编写的程序还是命令式的,就和用php,
>> > javascript编程其实差不多。好处仅仅只是语法十分简单,但同时也牺牲了不少可读性。
>>
>> very wrong.
>>
- 欢迎!
- 中文已经有实效 CLISP 的图书了,,,
- 简单的,48小时学会 scheme 的也都有
- 不过,怎么学会,和教程长短没有关系,看专心与否了,,,
> --
> Lisp-cn(Lisp中文用户组)
> CLUG http://lisp.org.cn
--
人生苦短, Pythonic! 冗余不做,日子甭过!备份不做,十恶不赦!
俺: http://about.me/zoom.quiet
文字协议: http://creativecommons.org/licenses/by-sa/2.5/cn/
>> 1) code as data (这点你说了,但像 lisp 这般彻底的没有,专业一点叫 homoiconic programming
>> language)
>
>
> 怎样才算得上彻底呢?访问所有的源代码?这几乎所有的编程语言都可以轻松实现,源代码本质上就是字符串,一般存储在文件里。
>
Lisp code is not text or string! 虽然存储媒介可以是字符串!但你操作的时候,不是操作字符串。这是最根本最本质的区别。
>>
>> 2) reflection,几乎所有编程需要的信息都可以在 runtime 里得到,bindings info (var, func,
>> macro, etc.),types,declarations,source code!
>
>
> 这包含两点,一个是本身提供的反射功能,类似的功能可以在如Java等语言里面找到。
> 另外一个是,由于运行时里面包含调试器,所以所有的信息都可以在运行时找得到,前提是,必须带上调试信息进行编译,否则,同样找不到。那么,如果我的其他语言的程序里面同样也集成了一个调试器库,同样也能轻松访问到,这并不是一件很困难的事情。
>
应该有你所说的调试器库,不过请举一些非调试情况下的使用方式,至少我是不知道。
哦,对了,除了 runtime (eval-time),还有 compile-time 的 reflection -- environments。
>>
>> 3) composability,基本上所有的都是 expressions
>
>
> 我理解的你的意思应该是,一来全是表达式方式的语法,二来可以一层套一层。
> 这种在其他语言里面非常多,一个例子是F#。
> 例如,我可以在Common Lisp里面编写一个let套上另外一个let:
> (let ((x 1))
> (let ((y 2))
> (+ x y)))
> 我同样也可以在F#里面一个let套上一个let:
> let x = 1 in
> let y = 2 in
> x + y
> 如果喜欢括号和前缀表达式,那么也可以这样写:
> (let x = 1 in
> (let y = 2 in
> ((+) x y)))
>
> 其实上面都是一层套一层的很明显的形式。
>
你说的没错,任何 FP language 都很强调这点。 meta-programming 必须的。但 f# 没有1)和2),无法简单生成程序。
> 另外,任何编程语言的语法(除非是汇编等过于简单的可能除外),其语法定义本身就是一层套一层的。比如下面的简单的一个语法定义(C风格的类型定义简化版,没仔细检查,也许会有一些手误):
> type-definition ::= type-spec var-list
> type-spec ::= int | float
> var-list ::= var-list , var | var
> var ::= id
> 那么,像如下的定义:
> int a,b,c
> 其实可以理解为这样子的一层套一层:
> (type-definition (type-spec int)
> (var-list
> (var-list
> (var-list (var a)) , (var b)) , (var c))
>
问题是你能不能随意得把某个 subtree 用其他的 tree替换,而不影响 evaluation? C 里面分 statement 和
expression。在生成 statement 的地方可以用 x=x+1 也可以用 x++,但 expression 的地方只能用 x++
虽然两者做的事情一样。 if then else 和 :? 又是一个例子。
lisp 的 code 本身就是 ast 形式,3)保证了任何 unit 可以相互组合。
我的 argument 是 1 and 2 and 3,三者不可缺一!
还有一种 reflection,学术上 reflection 又称 computational reflection,其基本的组成部分是
meta-circular interpreter!
说实话 sicp 里讲了很多关键的东西,只是因为面向初学者,不能展开得太多,建议多看看 paper!
reflection 和 meta-circular interpreter 可以看 3-lisp 的 paper
2012/1/25 Xiaofeng Yang <n.akr....@gmail.com>:
Lisp code is not text or string! 虽然存储媒介可以是字符串!但你操作的时候,不是操作字符串。这是最根本最本质的区别。
>> 1) code as data (这点你说了,但像 lisp 这般彻底的没有,专业一点叫 homoiconic programming
>> language)
>
>
> 怎样才算得上彻底呢?访问所有的源代码?这几乎所有的编程语言都可以轻松实现,源代码本质上就是字符串,一般存储在文件里。
>
应该有你所说的调试器库,不过请举一些非调试情况下的使用方式,至少我是不知道。
>>
>> 2) reflection,几乎所有编程需要的信息都可以在 runtime 里得到,bindings info (var, func,
>> macro, etc.),types,declarations,source code!
>
>
> 这包含两点,一个是本身提供的反射功能,类似的功能可以在如Java等语言里面找到。
> 另外一个是,由于运行时里面包含调试器,所以所有的信息都可以在运行时找得到,前提是,必须带上调试信息进行编译,否则,同样找不到。那么,如果我的其他语言的程序里面同样也集成了一个调试器库,同样也能轻松访问到,这并不是一件很困难的事情。
>
哦,对了,除了 runtime (eval-time),还有 compile-time 的 reflection -- environments。
>>你说的没错,任何 FP language 都很强调这点。 meta-programming 必须的。但 f# 没有1)和2),无法简单生成程序。
>> 3) composability,基本上所有的都是 expressions
>
>
> 我理解的你的意思应该是,一来全是表达式方式的语法,二来可以一层套一层。
> 这种在其他语言里面非常多,一个例子是F#。
> 例如,我可以在Common Lisp里面编写一个let套上另外一个let:
> (let ((x 1))
> (let ((y 2))
> (+ x y)))
> 我同样也可以在F#里面一个let套上一个let:
> let x = 1 in
> let y = 2 in
> x + y
> 如果喜欢括号和前缀表达式,那么也可以这样写:
> (let x = 1 in
> (let y = 2 in
> ((+) x y)))
>
> 其实上面都是一层套一层的很明显的形式。
>
问题是你能不能随意得把某个 subtree 用其他的 tree替换,而不影响 evaluation? C 里面分 statement 和
> 另外,任何编程语言的语法(除非是汇编等过于简单的可能除外),其语法定义本身就是一层套一层的。比如下面的简单的一个语法定义(C风格的类型定义简化版,没仔细检查,也许会有一些手误):
> type-definition ::= type-spec var-list
> type-spec ::= int | float
> var-list ::= var-list , var | var
> var ::= id
> 那么,像如下的定义:
> int a,b,c
> 其实可以理解为这样子的一层套一层:
> (type-definition (type-spec int)
> (var-list
> (var-list
> (var-list (var a)) , (var b)) , (var c))
>
expression。在生成 statement 的地方可以用 x=x+1 也可以用 x++,但 expression 的地方只能用 x++
虽然两者做的事情一样。 if then else 和 :? 又是一个例子。
lisp 的 code 本身就是 ast 形式,3)保证了任何 unit 可以相互组合。
我的 argument 是 1 and 2 and 3,三者不可缺一!
2012/1/25 Xiaofeng Yang <n.akr....@gmail.com>:
>
> 1)和2)其实是指编译器接口。原生的编译器接口,比如F#的前辈语言OCaml就已经提供。
>
你是说 metaCaml 还是 Camlp4? Camlp4 本身问题多多,语言也不是 ocaml
>
> Common Lisp的基本语法如同C一样,不能乱套。Common Lisp的special
> operator如同C的各种statement/expression一样,都有自己的语法,不能乱写。至于其他的,如同C一样,要么是调用宏,要么是调用函数。Common
> Lisp还有个特点,它的special
> operator基本不提供多少功能,所以它的很多东西只能使用标准库里面的宏或者函数来实现,因此也给人错觉,似乎什么东西看起来都是一样的。
> 不过,如果要说Common Lisp的代码就是ast形式,从某种意义上说,它们的确是非常接近(甚至绝大多数情况下看起来是一样的)。
>
语法当然不能乱,但
“什么东西看起来都是一样的。”有太多的好处了,可以讲三天三夜。
> P.S.
> 1. x=x+1也是一个expression,它返回x+1的值。
恩,assignment 是 expression,我搞错了。
> 2. 是Common Lisp而不是Lisp,搞清楚这一点,非常重要。如果仅仅因为Common Lisp就得出“lisp 的 code 本身就是 ast
> 形式”,那就是大错特错了。
>
哪里错了?
语法当然不能乱,但不区分 statement 和 expression 是重要的一点。e.g. if
当然我不是说 lisp 是完美的。但作为程序语言毫无疑问是最灵活最便利的。
sigh。 这也能吵起来。 果然是 LispUsersAreArrogant ……开个玩笑,有时候太较真了不好……你们就互相让一让。YXF你少钻点牛角尖(this can be offensive),多注意表述自己的观点而不是攻击别人叙述中的漏洞(this can be offensive, too),HJS 你多考虑一下特殊情况(比如LOGO,比如读取宏),“最”这种主观色彩浓烈的词尽量少用(can be offensive, too)。世界不就和谐了……
----拉回正题---新手的学习当然应该是迭代式的,先拿点有lisp味儿浓厚,学习周期很短的东西来让人家看看喜欢不喜欢,有没有兴趣。喜欢就留下,不喜欢也不用勉强……* 我还是推荐上手SICP多一点。以前MIT的学生学的就是这本。你读了会觉得这就是The Lisp way of programming. 的感觉,虽然传授的语言内容相当窄。做做课后习题,收获会不小。* 楼上面提到的Practical Common Lisp当然也不错啦,最近中文版出了,蛮火的。但是缺点也就在practical上。 它就是想教你program in common lisp,思想的内容其实不多,范围也蛮窄的,不注重完整性,但是书里有不少代码给你读和模仿。如果你打算做一些简单的Lisp开发试试,那么推荐之。* 如果更喜欢scheme风格,但由于某些原因接受不了sicp,可以读读HtDP看看,内容比SICP浅,不过思想性也弱了一些。以上是有中文版的书,还有一些没有中文版,可以下到pdf:* Common Lisp : a gentle introduction to symbolic programming 有点老,于是个人感觉稍微有点misleading.但是整体来说是不错的入门书。还有课后习题。* Land of Lisp 蛮好玩的。这书比较新,我上次去美国在MIT的书店里关于lisp的书只看到这本和sicp。* ANSI Common Lisp 据说作入门也不错,我还没有来得及读这本,不好评价,惭愧惭愧。* The Little Lisper 有点老啦,但是风格很独特,而且短。不过这也是缺点……* The Little Schemer 同上。* 楼上面提到的Computer Science Logo Style 是用另一种很不一样的Lisp方言(Logo)来讲计算机科学的内容。缺点是太厚,而且因为讲的东西巨多,所以只推荐作为拓宽视野用。(好吧,这本我也只读了前两章)总之,Happy Hacking~--
Wir müssen wissen; wir werden wissen!
CrLF.0710
赞!But then I'm even more confused :)
我举一个实际的例子说明 lisp 的灵活性
最近在做一个程序分析的项目,用 haskell,需要改进 simplifier 部分,最大的问题是 equal
太慢,两棵一样的树必须从头到尾遍历一遍才能确定是否相同。
ok, 不改变源程序(或者很少)的情况下,如何改进?
symbolic computation 里有一个很有用的 technique,hash consing,即 cons
的时候比较检查是否已有一样的 cons 存在,因为 side-effect free,存在的情况下无需新的 cons。这样的好处是:1)
可以大幅度减少内存的使用(当重复 subtree 很多的情况下) 2) equal 可以用 eq 代替,equal is O(n), eq
is O(1),通常 eq 只比较 register 的值是否一致(primitive or memory address)
用 lisp 的话可以这么做,
1) 在 simplifier 模块中找出所有使用 cons 的函数(因为有 source code),如果 implementation
的 source code 也有,甚至可以自动找出被调用的标准库里的 consing 的函数(比如 mapcar,impl 无源码也可以
load 某个 cl in cl 的实现)。
2) 用 macrolet 将 cons 变成 hash-consing 的版本,将所有 consing 的辅助函数转化成 local
函数(这里 cons 的定义从 built-in function 变成 macro),在这个 environement 下重新编译
simplifier
3) 把所有的 'equal 和 #'equal 变成 'eq #'eq
于是你的 simplifier 就变成完全使用 hash-consing 的版本了。
以上例子的目的是想说明就算是很核心很底层的实现,如果整套系统完全贯彻了 1,2,3 的特性,可以很方便实现你想要的算法而
无需改变源程序!
本来就是个人观点,我真的是觉得用“最”不为过啊!
我觉得大家能理解其他人的观点才是最重要的。当然语言严谨是美德。。。
应该是
2) 用 macrolet 将 cons 变成 hash-consing 的版本,将所有 consing 的辅助函数转化成 local
函数(这里 cons 的定义从 built-in function 变成 macro),把所有的 'equal 和 #'equal 变成 'eq #'eq
3) 在这个 environement 下重新编译 simplifier
“你少钻点牛角尖”我觉得你这样想不好。这个世界上本来就没有牛角尖,你认为我钻了,那我就钻了。你已经在评价我的行为为“钻牛角尖”了,这就是你思维上的失误。你从我们用语言表达的话题转换成了对我行为的指责。像“有时候太较真了不好”这样的想法都是阻碍你深入思考的根源之一。什么钻牛角尖之类的想法,只有在中国传统的经验主义思想里面才有。经验是不可靠的。
“多注意表述自己的观点而不是攻击别人叙述中的漏洞”我不认可你这种想法。而且这种表达明显是针对人儿不是针对我们邮件的内容了。而且直接用了“攻击”这样子的词语。我希望你引用原文并且给出攻击的通用定义然后再对我的“攻击行为”作出证明。
以下的内容我还没看,先对你表达不爽。
赞同,而且很多时候 facts, "truth" 是随着理解的加深而改变的。
>>
>> "多注意表述自己的观点而不是攻击别人叙述中的漏洞"我不认可你这种想法。而且这种表达明显是针对人儿不是针对我们邮件的内容了。而且直接用了"攻击"这样子的词语。我希望你引用原文并且给出攻击的通用定义然后再对我的"攻击行为"作出证明。
>
> 我的意思是,要讨论不要辩论,因为辩论太容易跑题。比如你们说了半天,每个人罗列了不少fact,说了一会已经不知道在讨论啥了。
>
我们在讨论,
1)Lisp 哪些地方跟其他语言有本质的区别
2)因为这些区别哪些地方变得相对容易实现
>> 以下的内容我还没看,先对你表达不爽。
>
> 随便~ 我只是单纯希望结束这场在别人帖子下面的争论。对于楼里面提到的任意一个问题,开个新楼都更恰当。
>
我支持开新楼。
P.S.
就没有人讨论一下我昨天发的实例?灰常地伤心!XD
你说的token是不准确的,lisp 源代码是 sexp 形式,跟 reader 无关。以CL为例,sexp里不单单可以有 symbol,
cons, primitives, 也可以有 array, struct, clos object 等任何值。你可以想想 CL 的
reader macro,读入后可以是任何值。CL 的 evaluation model 说非 symbol 非 cons 的值的
evaluation 结果是其自身,这点很重要。
举个简单的例子
先定义一个 foo struct
CL-USER> (defstruct foo x y)
FOO
把 foo 绑定为新建的 foo object
CL-USER> (setf foo (make-foo :x 1 :y 2))
#S(FOO :X 1 :Y 2)
一般我们访问 foo 的元素时,用以下形式
CL-USER> (foo-x foo)
1
但我们也可以用以下形式
CL-USER> (foo-x (load-time-value foo))
1
和以下形式
CL-USER> (foo-x #.foo)
1
如果我们想看最后一行的实际代码,quote
CL-USER> '(foo-x #.foo)
(FOO-X #S(FOO :X 1 :Y 2))
这其实也是 pretty-print 之后的输出,想看真正的内容,我们需要用 describe
foo-x 后面那个其实是我们创建的 foo object
CL-USER> (describe (second '(foo-x #.foo)))
#S(FOO :X 1 :Y 2)
[structure-object]
Slots with :INSTANCE allocation:
X = 1
Y = 2
不少 specialization 技巧和 caching 技巧 都利用了以上特性。(可以思考一下 atom 和 constantp 的定义)
在 2012年1月25日 下午6:16,CRLF0710 <crlf...@gmail.com> 写道:
- 很欢乐的书!
> 在 2012年1月25日 下午6:16,CRLF0710 <crlf...@gmail.com> 写道:
>> 在 2012年1月14日 下午2:09,yin xu <loveu...@gmail.com>写道:
>>>
>>> 只是想改变下偶的程序设计观
>>
>>
>> 只是出于这个目的的话,读读SICP就够了,再来随便拿本CL的书看看Lisp的那些设施会被怎样使用就可以啦。个人感觉这样性价比比较高。
>>
...
Common Lisp也许能改变一下你的一部分编程观念,但是不算很多。就算fans沾沾自喜的宏、REPL等其实在很多常见的语言都有同类的东西。
Common Lisp其实并不是传说中的函数式语言,或者更准确的说,是支持函数式的多范性编程语言,绝大多数时候,你编写的程序还是命令式的,就和用php, javascript编程其实差不多。好处仅仅只是语法十分简单,但同时也牺牲了不少可读性。
简单点的教程:Practical Common Lisp
LISP系个人感觉最简单的编程语言:LOGO
LISP是一个大家族,跟Common Lisp是两个概念。
如果要改变编程观念,也许以下语言可以参考,这些语言让你不得不换一种思路来编程(习惯的力量时强大的,只有当你被逼迫的时候,才能学会一种新的思路):
Haskell - 流行的纯函数式编程语言,较有名的实现,如GHC。另外,如OCaml等编程语言,尽管支持多范性,但是如果不使用纯函数式编程会需要比较麻烦的方法(其实Haskell也是如此)。
ISO Prolog - 流行的纯逻辑式编程语言,较有名的实现,如BProlog, SWI-Prolog, GNU Prolog, 等
当然还有很多基于其它计算模型的编程语言,只不过如上的两种类型是最常被提到的。
另外,你可以加入社区群:25342018
Best regards,
Xiaofeng Yang
在 2012年1月14日 下午2:09,yin xu <loveu...@gmail.com>写道:
今天是我第一次想了解下LISP,只是想改变下偶的程序设计观~
网上找了common lisp .1000多页,坑爹不止两三天~~有没有简单点的教程~~
--
Lisp-cn(Lisp中文用户组)
CLUG http://lisp.org.cn
我很希望能听到你的详细观点,而不是简单的一个“wrong”。
Best regards,
Xiaofeng Yang
在 2012年1月25日 下午7:06,Jianshi Huang <jiansh...@gmail.com>写道:
2012/1/25 Xiaofeng Yang <n.akr....@gmail.com>:
> Common Lisp也许能改变一下你的一部分编程观念,但是不算很多。就算fans沾沾自喜的宏、REPL等其实在很多常见的语言都有同类的东西。
Wrong wrong wrong, 你应该来上次的 lisper meetup 听我的第二个演讲的:)
> Common Lisp其实并不是传说中的函数式语言,或者更准确的说,是支持函数式的多范性编程语言,绝大多数时候,你编写的程序还是命令式的,就和用php,
> javascript编程其实差不多。好处仅仅只是语法十分简单,但同时也牺牲了不少可读性。
very wrong.
> 简单点的教程:Practical Common Lisp
> LISP系个人感觉最简单的编程语言:LOGO
>
> LISP是一个大家族,跟Common Lisp是两个概念。
>
> 如果要改变编程观念,也许以下语言可以参考,这些语言让你不得不换一种思路来编程(习惯的力量时强大的,只有当你被逼迫的时候,才能学会一种新的思路):
> Haskell -
> 流行的纯函数式编程语言,较有名的实现,如GHC。另外,如OCaml等编程语言,尽管支持多范性,但是如果不使用纯函数式编程会需要比较麻烦的方法(其实Haskell也是如此)。
> ISO Prolog - 流行的纯逻辑式编程语言,较有名的实现,如BProlog, SWI-Prolog, GNU Prolog, 等
> 当然还有很多基于其它计算模型的编程语言,只不过如上的两种类型是最常被提到的。
>
比较的方法就是真正做一些项目!然后你就明白灵活性是多么重要了。
Cheers,
--
黄 澗石 (Jianshi Huang)
http://huangjs.net/