免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: send_linux
打印 上一主题 下一主题

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

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
51 [报告]
发表于 2012-02-29 19:20 |只看该作者
回复 50# OwnWaterloo


    哥哥,编译的时候就一个OP_ADD,运行的时候判断类型。JIT的话,运行的时候进行跟踪,如果发现1.对象没有改过2.执行过多遍,就直接把执行过程变成native跑了……

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
52 [报告]
发表于 2012-02-29 19:35 |只看该作者
回复 49# starwing83

相差不大的结论是怎么来的?
有仅解释就与非JIT编译的lua相当的lisp,除非作者在吹牛。
http://picolisp.com/5000/!wiki?NeedForSpeed  这里有与sbcl的对比。

我说过这么多次了……  是否被优化,是否会被阻止优化, 是由你需要的灵活性决定的。
lisp的概念,至少我最欣赏的部分,是程序由语言内建的数据结构表示,于是可以像操作数据那样产生新的程序 —— 而且通常是在编译时
http://www.paulgraham.com/diff.html  也就是这里说的8. A notation for code。
code与data是可以被设计为有界限的,但它们的表示方式相同。

其余部分也很有用,而且我没看出有哪部分是阻止lisp被优化的,除了:9. The whole language always available。
lisp缺少(或者说还没发现)一种实现是有意图地将9的功能划分出明显界限, 并且仅当需要时才产生所需代价。

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
53 [报告]
发表于 2012-02-29 19:42 |只看该作者
回复 51# starwing83

你说的这种处理方式与 (+ a b) 的区别到底在哪里……

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
54 [报告]
发表于 2012-03-01 09:59 |只看该作者
回复 53# OwnWaterloo


    (+ a b)并不知道+到底是什么。比如这里:

(let ((+ (if (rand) (lambda (a b) (+ a b))
                     (lambda (a b) (- a b)))))
   (+ 2 1))

答案究竟是3还是1呢?是运行时决定的,不是3就是1,取决于(rand)的值。因此下面的(+ 1 2)就不可能翻译成OP_ADD 1 2,也不可能做constant fold,最多只能搞成:OP_CALL 1 1 2(第一个1指第一个local变量),最终的结果是一次调用(而且是不可避免的)。因为这些原因。要么lisp编译器要做所有的解析,确保可以编译成字节码的函数或者special-form完全没被修改,要么就只能保守地把所有的(op args...)翻译成OP_CALL op args...,那样基本上没法做优化了(你看,上面的constant fold就没法做了,注意lua是有constant fold的)。

除非这时不允许改变+的值,或者在某个block改变了+的时候做个标记,说明这里必须得用OP_CALL,而不是OP_ADD。而每个内建函数做这样的标记是很累人的,意味着每次赋值都必须查找。而且如果有scheme式的全局变量话,这种标记都有可能没法做到,如下:

(define (foo a b) (+ a b))
(if (rand) (set! + (lambda (a b) (add a b))
           (set! + (lambda (a b) (sub a b)))
注意我这里故意把set!写里面,这意味着任意一个位置的自由变量(scheme默认是全局变量)改变都可能导致整个程序的状态改变。如果是这种情况就很不好判断了。

惟一的办法就是不允许修改这些值,那其实和lua(以及lua ast)没啥差别了。lua照样可以生成lua代码,而且根本不难。lisp除了语法和编译器支持以外,看不出什么优势。操作程序表只是在提取信息而不是构造程序方面有优势。然而只要有了ast,连这种优势也没了。

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
55 [报告]
发表于 2012-03-01 10:02 |只看该作者
回复 52# OwnWaterloo


    说到灵活性,你能假设没有人会有需求去改变+么?也许有也许没有,照你的理论这个就得支持,不然就是“限制程序员”,我的意思是,这里面的确需要有个度。如果说只要“有可能”会用到的都要支持,那语言就很难在语义和实现上取得平衡了。

论坛徽章:
46
15-16赛季CBA联赛之四川
日期:2018-03-27 11:59:132015年亚洲杯之沙特阿拉伯
日期:2015-04-11 17:31:45天蝎座
日期:2015-03-25 16:56:49双鱼座
日期:2015-03-25 16:56:30摩羯座
日期:2015-03-25 16:56:09巳蛇
日期:2015-03-25 16:55:30卯兔
日期:2015-03-25 16:54:29子鼠
日期:2015-03-25 16:53:59申猴
日期:2015-03-25 16:53:29寅虎
日期:2015-03-25 16:52:29羊年新春福章
日期:2015-03-25 16:51:212015亚冠之布里斯班狮吼
日期:2015-07-13 10:44:56
56 [报告]
发表于 2012-03-01 10:33 |只看该作者
starwing83 发表于 2012-03-01 09:59
回复 53# OwnWaterloo


common lisp 是限制修改内置函数,racket 是通过 syntax 抽象来判断是否是原始的 +,比如你用 let 那个完全没问题,不过用了 set! 那就没办法了,很多优化都不能用了

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
57 [报告]
发表于 2012-03-01 10:42 |只看该作者
回复 54# starwing83

前面那一堆,除了const fold,还是没说出与lua的差别。

>> (define (foo a b) (+ a b))
lua里面 function(a,b) return a+b end
也只是固定了一个OP_ADD而已,也就只是知道它对两个number会数字+, 对有元表的看元表定义。 具体会做什么依然不清楚。
(defun foo (a b) (funcall #'+ a b))
(define foo (let ((+ +)) (lambda (a b) (+ a b))))
取出+的定义,对两个number(fixnum/bignum/real...)会数字+, 对其他无定义。 +的function cell不再影响foo函数。


>> 惟一的办法就是不允许修改这些值,那其实和lua(以及lua ast)没啥差别了。
这段,连着后面那楼
>>     说到灵活性,你能假设没有人会有需求去改变+么?也许有也许没有,照你的理论这个就得支持,不然就是“限制程序员”,我的意思是,这里面的确需要有个度。如果说只要“有可能”会用到的都要支持,那语言就很难在语义和实现上取得平衡了。

一起回复了。
有差别,而且你怎么想不到呢……  支持了又不是说所有地方就必须都有这种灵活性……
你这等于是在说: C/C++支持指针运算,支持类型转换,没有限制程序员, 所以是不安全的。 但其实良好的C/C++程序里这些不安定因素只在很小范围内。
那个cl反汇编的例子, 没说add以外的函数中的+的行为全都被固定了啊, 也没说不允许const fold啊, 只是那个例子没有掩饰而已。

你怎么和327一样呢……  要么C,要么C++了就必须全private……  不是的,private也是在你需要时才用的。


>> 惟一的办法就是不允许修改这些值,那其实和lua(以及lua ast)没啥差别了。
lua有办法让foo函数告知编译器: 我这函数就用内建+了, a,b就只支持整数了, 给我优化到addl?

>> lua照样可以生成lua代码,而且根本不难。lisp除了语法和编译器支持以外,看不出什么优势。操作程序表只是在提取信息而不是构造程序方面有优势。然而只要有了ast,连这种优势也没了。

什么叫这种优势也没了?这也不是第一次与你说这个了: 能获得ast的语言早就有了, 为什么在元编程(code transformation)方面依然没超过lisp?
lua的宏,等它出来之后再说好吗?这只是说lua有这个能力, 并不能肯定lua能够很容易的使用这个能力。
上面的,什么使得lisp不同,貌似是第8点,特有的代码记法。 代码中写的样子就是读的样子,已经被人肉parse过了。
不仅仅是能够获得, 而且是在代码文本中能够清晰看见。  这就是被人诟病的lisp难看的语法的优势。


论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
58 [报告]
发表于 2012-03-01 10:46 |只看该作者
回复 56# zhlong8


    是啊,我也说了这样可以啊,可是处理起来复杂哈,而且还有情况是没法优化的。所以lisp实现才要么慢要么大,根本找不到一个平衡的嘛~我就是这个意思。

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
59 [报告]
发表于 2012-03-01 10:58 |只看该作者
回复 57# OwnWaterloo


    你怎么就完全不了解我的意思呢????

我一直在围绕语言设计和实现这个角度在说话,根本就没说程序员用不用。一点一点说:

1. 我说惟一的办法是不允许修改,我不是怕程序员改坏了,我是说不这样就会导致优化复杂,是实现问题!!!你曲高和寡,得不到一个好的实现!这种没有优秀实现的语言又怎么可能流行起来呢?js做html5流行起来不也是v8带起来的么?包括node.js都是在v8基础上做的,没v8哪来的node.js???

2. 我不是说要禁止程序员做什么做什么,我是说如果给予完全的灵活性,比如规定语言里面所有的东西都是可以改的,那么实现会遇到大量的困难!除非你打算做一个玩具。否则你必须得限定一个东西是不变的。我一直是在从语言实现上谈论这个设计问题,你扯程序员用不用干嘛?我承认规则范化有好处,问题是如果泛过头了,泛到了实现都困难的时候,你随便编译一个hello world都是一个5M的exe你怎么搞??

好,继续说+的问题。

这里的问题是:我知道+的语义是固定的,我可以用一个特定的方式处理它,这个方式可以是很复杂的(根据类型来的),但是至少是特定的,好,假设是123号功能吧。123号功能可能是个很大很大的函数,这不要紧,但是在我看到+的时候,我就知道我要调用123号功能,这时我可以写死:OP_123,这样就直接查表了(查表和执行包括判断类型都是运行时的事情)。

然而,如果+是能改的,那么我就根本不知道这个时刻的+是不是真的对应123号功能了,它可能已经被修改成456号功能了,也可能被修改成一个自定义字节码函数了,那么我怎么去写死呢?我没法写死,我只能说:查看+的值,然后根据选项去调用这个值,假设这个“查看且跳转”的功能是3号,那么我就只能写:OP_3 a 了,而a是OP_123,我才能再去执行123号功能。

注意lisp里面所有的东西都是可以改的,那么其实我的字节码就只有一个了,就是3号,因为我根本不知道哪个东西是固定功能!我只能把固定功能写成独立的函数,然后让3号功能去根据变量的值去调用这些固定的函数。据lua邮件列表的说法,这两种不同的调用方法去调用同一个函数,其效率可以相差一个数量级!

这就是我的意思。lisp的所有东西都是可以改的会导致优化困难,甚至难以优化。我不是说为了安全去禁止程序员咋样咋样,我是说让程序员这样做本身的实现都是非常困难的!甚至实现出来这样的功能,程序员又不用,却要带上几M的运行时环境去支持这种可能一辈子都用不着的功能,是非常浪费的,这就是我的意思。

如果是这样,干脆限制一些东西以方便实现,C就是这么干的。

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
60 [报告]
发表于 2012-03-01 10:58 |只看该作者
回复 58# starwing83

我了个去……  你是不是老是纠缠lisp实现……    去试试gambit……
以前我只关注cl,因为想写些非toy的东西,但连模块机制都没有的标准scheme根本不可能……

其实scheme与lua比实现大小就不公平, scheme支持任意精度(就这东西做好了就比lua大了), 支持continuation, 比lua大很正常。
cl就更不公平了……
其他lisp很多都被OO教坏了, 看的兴趣都没有……


先看gambit老版本,3的,也许才符合你的胃口……  也别吐槽生成的C代码了……  它们都将C作为可移植的汇编用……
guile(scheme)是有虚拟机的, 不过貌似移植性不好, 不知道Windows原生支持出来了没……  但LuaJIT的移植性又很好么? 将C当可移植汇编才是王道……
还有以前提到的chicken?还是chibi?是它么?是哪被你吐槽了?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP