免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: send_linux

《ruby元编程》有奖试读中!(获奖名单已公布) [复制链接]

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
发表于 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/Com ... pture_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)[4] 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版…… 主题是某本书的试读……   这赤果果的歪楼不科学啊……

论坛徽章:
4
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:11
发表于 2012-03-02 00:23 |显示全部楼层
回复 81# OwnWaterloo


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

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

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
发表于 2012-03-02 00:38 |显示全部楼层
回复 82# starwing83

java都还搞嵌入式呢……

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

论坛徽章:
5
丑牛
日期:2014-01-21 08:26:26卯兔
日期:2014-03-11 06:37:43天秤座
日期:2014-03-25 08:52:52寅虎
日期:2014-04-19 11:39:48午马
日期:2014-08-06 03:56:58
发表于 2012-03-02 16:18 |显示全部楼层
一直在听人说Ruby如何如何好,
呃,但不幸的是我一直都没能阅读Ruby语言参考手册,
阅读完样章我个人的感受是

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

论坛徽章:
4
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:11
发表于 2012-03-03 14:34 |显示全部楼层
本帖最后由 starwing83 于 2012-03-03 14:43 编辑

回复 83# OwnWaterloo


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

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

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

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

论坛徽章:
4
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:11
发表于 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[n] = nil
  self(t, n + 1)
  t[n] = 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五个元素,最多只选三个,求所有的组合情况,这个题如何用第二种方式加缓式求值来达到剪枝的目的?
   
  

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
发表于 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差了。

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
发表于 2012-03-03 15:32 |显示全部楼层
回复 87# OwnWaterloo

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

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
发表于 2012-03-03 15:57 |显示全部楼层
回复 86# starwing83


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

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

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


而且我还觉得它们有些地方还不够自由。
比如我认为 set! defun 应该是一个普通函数, 第一个参数应该可以被求值。
例如emacs lisp:

  1. (let ((x 12) (y 26))
  2.   (set (if (= 0 (% (random) 2)) 'x 'y) 86)
  3.   (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等等相比,依然很少,质量参差不齐,文档也缺乏。
没办法,用的人少

论坛徽章:
4
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:11
发表于 2012-03-03 16:17 |显示全部楼层
回复 89# OwnWaterloo


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

我想问问:要这样的自由有啥好处么?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP