OwnWaterloo 发表于 2012-03-01 18:56

回复 80# starwing83

>> chicken就是……可是生成的C代码就有十几M,编译出来的exe(不是字节码)基础的就有5M+……
这货貌似是用continuation passing style实现的。
任何语言这么写都会很乱,不知道haskell会如何……貌似它也是这么实现的……,C肯定更乱……

至于大,我想还是前面提到的,没能去掉不用的runtime。

>> 很小的实现通常直接执行cons,不会涉及字节码
sbcl(windows, 不依赖外部编译器, 10M), ecl(10M), gcl(40+M,带gcc!), gambit(7m), plt(racket,mz的关系很混乱,我记不清了…… 200M,但貌似带了许多库) 它与都是产生本地代码。
clisp(30-M,很多库)/guile(Windows下没有……)是虚拟机。
全都比python小。

别和lua比, lua是个裸的好吗……它那标准库能做个啥……


>> 而为了能够应用字节码,通常一些函数是不让动的


http://en.wikipedia.org/wiki/Common_Lisp#Variable_capture_and_shadowing
Common Lisp solves the problem of the shadowing of standard operators and functions by forbidding their redefinition. Because it redefines the standard operator DO, the preceding is actually a fragment of non-conforming Common Lisp, which allows implementations to diagnose and reject it.

http://en.wikipedia.org/wiki/Scheme_(programming_language)#Redefinition_of_standard_procedures
In Scheme, procedures are bound to variables. At R5RS the language standard formally mandated that programs may change the variable bindings of built-in procedures, effectively redefining them.

In R6RS every binding, including the standard ones, belongs to some library, and all exported bindings are immutable. (R6RS sec 7.1) Because of this, redefinition of standard procedures by mutation is forbidden.


>> 这就是由lisp本身简单的概念造成的。
我也不是第一次说了……这种简单概念是用来解释(explain)lisp,虽然有一些实现直接就用来解释(interpret)了……

自己看上面引用的,以及用用前面提到的那些小的实现吧……
我是不太喜欢用它们,与lua的理由一样,干不了活。 如果有什么严肃认真的东西要做也许才会去考虑这些小的实现。


>> 我记得我举过一个例子...
你那个例子我没看得很懂。 如果考虑了缓式求值呢?
产生所有解与在这些解上剪枝, 如果是严格求值, 就必须写在一起。
而缓式求值就可以将这两个过程解耦, 并希望能达到严格求值中手写的相当的效率。 至于是否能达到我也没信心……

我的意思是说,技术发展虽然缓慢,但还是在发展。
gc被认为很浪费, 现在不也习以为常了?
词法作用域曾经被认为不可能高效实现 ——多少牛人都曾经有过这样的判断 —— 但他们也都错了。

还有至少写on lisp那个人,还有实现p啥啥lisp那个人,根本不把运行时效率当回事……
on lisp那个说: 每一代人都会做上一代人看来很浪费的事。
他实现的那个arc…… 他自己都承认一开始只是勉强能用(用clisp实现的解释器,clisp自己又在虚拟机上)。 不知道现在arc是不是只有list of char没有string……
也许这些家伙觉得现在的lisp已经比原来快得多了, 还优化个毛啊……



我说……要不去别的版块闹?连同上面的zhlong8同学……不过CU木有lisp只有个functional版块就是了……
这可是ruby版…… 主题是某本书的试读……   这赤果果的歪楼不科学啊……

starwing83 发表于 2012-03-02 00:23

回复 81# OwnWaterloo


    python的不带库的裸实现就2m,这很有意义好不好?方便嵌入式。

有没有不带库裸实现一兆以内的速度可以接受(c的50倍左右)的实现?

OwnWaterloo 发表于 2012-03-02 00:38

回复 82# starwing83

java都还搞嵌入式呢……

给你说过啊……邮件没收到么……
ecl(common lisp), gambit(scheme)。具体小到什么程度的话,其实我也分不清哪些文件去掉才算是裸的……
它们各自的一个dll文件,应该是运行时依赖,只有1.3M左右。
都是编译到C+解释器,前者自然还需要一个外挂编译器……

pitonas 发表于 2012-03-02 16:18

一直在听人说Ruby如何如何好,
呃,但不幸的是我一直都没能阅读Ruby语言参考手册,
阅读完样章我个人的感受是

我个人感觉,Ruby的代码非常优美雅致,编写代码更精练。
Ruby语言是更高的层次的编程语言。

starwing83 发表于 2012-03-03 14:34

本帖最后由 starwing83 于 2012-03-03 14:43 编辑

回复 83# OwnWaterloo


    一个源代码有58M,一个源代码有9M,另外,他们是纯C么?有没有带汇编?

看看这个吧:http://etherplex.org/archives/150

一个理想的函数式编程语言是这样的,我只要把我的需求(我的转换)描述出来,执行的快不快是定了的事情,那是编译器的优化。因为我描述的是”做什么“,而不是“怎么做”。怎么做是编译器的事情。

然而现在的编译器未必能达到这个地步。

starwing83 发表于 2012-03-03 14:59

回复 81# OwnWaterloo


    最后说两个问题吧。

一个是,你一直说这是用来解释lisp的运行的。好吧,我说明白点,如果lisp是完全自由的,那么它唯一的运行方法,就是这种解释!也就是说,根本就不存在其他的方式能执行lisp!

存在其他方式的前提,是限制不允许修改某些函数,这些你也看见了。

第二个是,Lua的模块已经很多很多了,从科学计算到GUI,从高性能网络到图形识别。我觉得已经非常非常多了,你要的无非是个“官方认可”的名分而已。而这个是不大可能的。退一万步说,你可以用luarocks,类似于python的easy-install的东西。自动下载编译,处理依赖关系。

那个例子我还是举个例子吧,不算说明,只是告诉你到底是什么意思。

假设我有个问题:有五个物体ABCDE,现在求这五个物体任意选出几个的组合,要求所有的组合情况。

一种方法是DFS,也就是A选择,在A选择的情况下遍历BCDE,然后A不选择的情况下遍历BCDE,最后递归能输出所有的结果。这是标准做法,但是得写递归函数,写起来没那么简单:

dfs = coroutine.wrap(Y(function(self, t, n)
if n > #t then coroutine.yield(t) return end
t = nil
self(t, n + 1)
t = true
end))

另有一个可能比这个更简单,更好理解的方法是这样的:
result = coroutine.wrap(function(n)
for i = 1, 2^n do
    coroutine.yield(bit32.totable(i, n))
end
end)

很简单,从1遍历到2^N,每个bit代表一个物品选或者不选。比如1是00001,则只有E被选择,而2是00010,只有D被选择,等等以此来推。

明显第二个算法更快(常数因子,或者系数上),而且写法更简单,那么为什么大家都采用第一种方式呢?

很简单:因为第二种方式看似优雅,却失去所有的潜力:他太完美了,完美到已经无法继续完美下去了。他太适合这个场景以至于无法胜任其他的任何工作了。

比如,我加一个限制条件:最多只允许选择3个。

那么第一种实现里, 我们就能剪枝:如果发现已经选了三个,就不再递归下去了。而第二种里,我们仍然得遍历完所有的选项!没有任何条件可讲。

Lisp就是我说的第二种方式。他很适合“解释lambda演算”这样的工作,而且他太简洁了,太完美了,完美到无法适应实际的计算机。为了让他适应,只能让他不完美(规定特殊规则)。这就是Lisp最大的问题。

另:你说缓式求值可以解耦列举解和剪枝?可是剪枝的原理就是”满足条件后不再深入下面“,本质上是用条件限制了深度或者广度的深度/广度优先遍历。剪枝的一个重要前提就是遍历是有序的,而第二种方式的遍历绝对不是有序的。你举个例子,ABCDE五个元素,最多只选三个,求所有的组合情况,这个题如何用第二种方式加缓式求值来达到剪枝的目的?
   

OwnWaterloo 发表于 2012-03-03 15:29

回复 85# starwing83

那个文章里的500 times longer我想应该指的是运行时间,而不是产生的C代码长度。
我用gambit3编译(产生的exe大小10k),并运行,没能得到结果就自己中断了,发现停在bignum相关的一个函数里。

C用int,scheme用bignum,你觉得这公平么?
以前我还经常举一个用C++但不开优化,而且在cygwin上运行,得出C++比Java慢的例子……

无论什么语言,即使是C++、甚至是C,当不了解该语言或者该语言的某个实现时很容易产生低效代码。这很正常。
我还经常写一些被你吐槽的lua代码,因为你知道某一行代码会产生什么样的代价。
但这不等于lua就一定低效、lua就没有workaround的写法、lua就永远不会做那些很明显的优化。

记得你说过5.2有一项什么新优化来着,可以避免重复产生函数 —— 这会不会导致lua的体积增加?
在某种程度上,可以说lua的小体积是因为放弃了一些优化以及功能(比如它的"正则")换来的。
这种权衡对lua来说没错,但你不能将这种权衡应用到所有语言与实现中。

回到gambit。
gambit与其他scheme的效率比较: http://www.iro.umontreal.ca/~gambit/bench.html
我想这个比那篇文章的作者更有说服力。
至少这文章的作者比你给出的那个文章的作者更了解scheme与scheme的各种实现。
而不是连manual都不看,就只知道说gambit(scheme)很慢,i don't know why的家伙。

另外,你给出的那篇文章,你看最后一个回复。
里面用的bigloo , 运行时间0m1.913s与C版本的0m1.570s相差并不大。
bigloo也出现在我给的那个bench里, 它与gambit是里面提到的最快的两种scheme实现了。


总之,bench不是件很容易做对的事情,不是随便写个toy program就能说谁比谁快。




>>  一个源代码有58M,一个源代码有9M,另外,他们是纯C么?有没有带汇编?
他俩产生的binary就只有我前面说的那么大, 源代码多大真的有这么重要?
lua是纯C么? dlopen/LoadLibrary什么的。lua没用汇编?操作浮点数格式那还不就是将C当作高级汇编用?LuaJIT呢?
你的评价标准有问题,你会将语言/实现的所有方面都与lua比, 只要有一方面比lua差, 它就比lua差了。

OwnWaterloo 发表于 2012-03-03 15:32

回复 87# OwnWaterloo

补一句, gambit与ecl产生的C代码是portable C。
不一定完全是纯的, 也许会使用某些C编译器的扩展。
但一定是在有纯C实现的方式之后, 将扩展作为可选优化措施。

OwnWaterloo 发表于 2012-03-03 15:57

回复 86# starwing83


>> 一个是,你一直说这是用来解释lisp的运行的。好吧,我说明白点,如果lisp是完全自由的,那么它唯一的运行方法,就是这种解释!也就是说,根本就不存在其他的方式能执行lisp!
>> 存在其他方式的前提,是限制不允许修改某些函数,这些你也看见了。

你怎么还是327的思路……   一些地方允许修改以获得灵活性, 另一些地方不允许修改以获得效率, 可以吗?
完全自由不等于说处处都要使用这种自由, 那叫强迫, 不叫自由。 而是当你需要时就能够有这种能力。

r6rs已经在往这些方面做出努力了,让一个模块的行为不会因为外界影响而改变。


而且我还觉得它们有些地方还不够自由。
比如我认为 set! defun 应该是一个普通函数, 第一个参数应该可以被求值。
例如emacs lisp:
(let ((x 12) (y 26))
(set (if (= 0 (% (random) 2)) 'x 'y) 86)
(list x y))
也许是x或者y被修改,结果要么为(12 86) 要么为(86 26)。
但不需要这种灵活性时 (set 'x "12") 编译器应该能分析出(quote x)运行时得到的值一定是x, 意义与 (set! x "12") 相同。




>> 第二个是,Lua的模块已经很多很多了,从科学计算到GUI,从高性能网络到图形识别。我觉得已经非常非常多了,你要的无非是个“官方认可”的名分而已。而这个是不大可能的。退一万步说,你可以用luarocks,类似于python的easy-install的东西。自动下载编译,处理依赖关系。

cl也有quicklisp,而且还有各种不同cl实现之间通信的协议,叫什么我忘了……
haskell也有cabal。
而且都是官方的。

但与python/java/c等等相比,依然很少,质量参差不齐,文档也缺乏。
没办法,用的人少。

starwing83 发表于 2012-03-03 16:17

回复 89# OwnWaterloo


    准备怎么限制?(unsafe)么?不觉得有点难看么= =

我想问问:要这样的自由有啥好处么?
页: 1 2 3 4 5 6 7 8 [9] 10 11
查看完整版本: 《ruby元编程》有奖试读中!(获奖名单已公布)