免费注册 查看新帖 |

Chinaunix

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

命名难,难于上青天 [复制链接]

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
171 [报告]
发表于 2012-02-16 18:57 |只看该作者
starwing83 发表于 2012-02-16 08:00
你一直在强调,一致性,不同的部分采用相同的机制来实现。是的,这就是抽象,可是你想过没有,如果不同的部分是真的非常不同呢?

从冯·诺依曼角度和现代计算机的角度,真正执行的东西,应该是个流状物,里面可能有些跳转,bc和natie都很适合这种模型,这种模型也适合优化,然而lisp不适合这种模型——lisp是个递归的模型,而不是流状的。——事实上,所有的编程语言都是递归的模型。

因此,在语言层次上来说,都一定会有一个“将递归模型转换成流式模型”的过程。lisp逃避了这个问题,宣称“递归模型是能直接执行的”(lambda演算),这可以,但是彻底断绝了优化的可能性。

关键点来了:如果一个lisp实现希望自己足够快,至少跟lua一样快,那么它就只能做一件事了:在底层,用特别不同的方法,去支持高层“看上去相同”的东西。换句话说,这种一致性是有代价的。

想象一下,本来就是完全不同的东西,现在你有选择:
  1. 既然底层是不同的机制,我也采用不同的方式(问题是C++0x选择的方式并不好——以后再说)
  2. 虽然底层不太相同,但是有相同的部分,所以可以抽象相同。

lisp选择了第二点,而大多数语言选择了第一点。其实也就是特化(专业化)和泛化(一般化)的区别了。

回到lisp,其实元编程和实际编程有一个相同的地方:都是计算。而lisp仅有一种计算:apply,因此自然可以结合在一起。而其他的语言,比如C,至少就有算术计算啦,指针计算啊,神马乱七八糟的各种计算,这就很不好办了。比如编译时肯定是没有指针的——有指针也是肯定不会让你改的,不然你写个C代码,编译的时候就能hack你的系统= =

lisp的问题在于太灵活(OW意义的:容易产生糟糕的代码;和我的意义的:把明明不该放到一起的东西放到了一起),它的问题就在于太宽泛,掩盖了不该掩盖的不一致性,凸显出实际上是虚假的“抽象”“一致性”。这就是问题。


最后关于你说的"虚假"的一致性。 我简直不敢想象这是你整理后的发言啊…… 完全有失水准…… totally wrong好吗?

lambda演算是递归的,lisp是基于lambda演算的,lisp代码也是递归定义的, right。
但这怎么推导出lisp的执行模型是递归的? wrong。 你心中的lisp的执行模型到底是怎样的?

语言层次上,C代码是不是递归定义出的树? lua是不是? python是不是?
lisp不过是把这种递归定义的树在代码里显式写出来了,其他方面能有多大区别?

haskell相距底层机器走得更远,不依然实现得很高效?
lisp的解释(interpret)语意只是为了给人解释(explain)的,不会发疯到每一个form都是一个函数调用的,不会的……

关于元编程使用一致性机制。这东西难道本来就不应该一致么?
C: 那个crc32_table,我用另一个C程序计算,输出,得到crc32_table的C代码
lisp: 在编译时完成相同的工作
难道应该有区别?

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
172 [报告]
发表于 2012-02-16 19:15 |只看该作者
本帖最后由 OwnWaterloo 于 2012-02-16 19:18 编辑

回复 161# walleeee

>> 这种我觉得应该是a bignum_mul b,至于怎么实现这样,在c中可以封装,在c++中更是可以重载。但是这里你的确说中了lisp的一个好处,一致性。就是你后面说的“lisp对算术运算都一视同仁”,所谓一切都是函数。

haskell里面很容易,a `bignum_mul` b,所以才会被普遍使用。
C++就不如haskell容易,但还是会这样做。
a bignum_mul b 在C里面怎么搞……

>> 冤枉啊,我从来没觉得方便不重要,甚至认为方便是设计软件和编写程序最重要的考虑之一。我只是说现在的语言和以前的语言的计算能力是等价的。

嗯…… 我没抓住重点。 确实是等价的。
编程语言不就是在人与机器之间沟通么。


>> 包括你前面说的元编程是否就是宏能完成的?在c++中还可以用模版来完成。如果仅仅是这样,那我并不觉得你所谓的元编程有什么让人耳目一新的地方。

可以用模板完成, 但这就是与运行时计算一个表使用的是完全不同的机制了。
lisp是通过一组很小的、更为正交与范化的概念去组合出其他语言中的各种专用的概念。
这就是不同。

>> 比如前面那个bignum_mul(a, b),我也可以用:
>> #define BIGNUM_OP(a, op, b) ((bignum_##op)((a), (b)))
>> BIGNUM_OP(a, mul, b)
>> 来稿嘛,尽管看起来没你那个好看,但是你那个到处是括号也不见得比我好到哪里去,五十步笑一百步,半径八两。

喂喂, 不对哦。
BIGNUM_OP(a,mul,b), 这已经是前缀了好哇……
已经与前面说的(arithmetic-formula a * b)一样了……
而且能力还不如它强,比如:(formula a * b + c),还可以嵌入更复杂的公式, C的宏做不到的。


>> 很久以前lisp的确有很多大型项目是lisp写的,不过那都差不都是几十年前的事情了。至于说规范,我觉得不管是什么规范,一致才是核心,但是别人不是你,你也不是别人,所以一个团队里面多少有些不一致,这个就很麻烦。

这确实很麻烦……
有些特性可能并不是团队成员故意违反规范去使用,可能他确实不知道这里违反了。
以前还发过帖,要不要搞一个强制性的禁用C++某些特性的工具,代替人肉的code review。
但对于lisp,也许只要禁止(不包含)或者替换(使用了会在编译时报错)某些宏就可以达到目的了。


>> 反观去中国的大学,费用浪费倒是小事,还浪费你很多事情去搞些莫名其妙的东西。唉,不说了,心灰意冷。
我懂

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

common language runtime? .net那一套VB.net, C++/CLI, C#, J#, F#, IronXXX?
parrot? 这上面有些什么语言我就不了解了……

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

这东西太学术了…… 看不懂……

不过确实如wiki所说,lisp早先也不全由s-exp构成。
还有car [(X . A)]这样的东西,貌似叫F-exp还是M-exp什么的……
后来才统一为(car '(X . A))……

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
175 [报告]
发表于 2012-02-16 19:41 |只看该作者
幻の上帝 发表于 2012-02-16 11:21
收拾“把明明不该放到一起的东西放到了一起”和“把明明该放到一起的东西却没放到了一起”哪个更麻烦点呢。
lisp的括号……好吧,这点确实挺反人类的。。= =
不知道这个问题是不是可以换一种词法上的处理解决。


难道你对C++也有类似的同感? 太凌乱了?

不管我怎么说C++的坏话,我可一直是C++的fans啊…… 立场先明确了……
这是带着爱意的批评。
相对于那些根本就不打算解决用户问题的语言,我都不想说它们什么了……

词法上解决么……
前面说了,lisp的notation可以1) 避免人工text->tree这一转换 2) 将结构化的text当作raw string处理 3) 增加parse,generate过程
如果避免这种notation,不知道会不会损害这一点?
而损害了这一点会不会对元编程的难度造成影响?

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
176 [报告]
发表于 2012-02-16 20:08 |只看该作者
回复 160# 幻の上帝

喂,既然来了,也帮忙看看std:: list:: size的问题嘛……

在container requirements里,size在complexity列里是Note A,后续说被标记为Note A的"should have constant complexity"。
在list章节里,说list必须满足container requirements。

上面是C++03与C++0x的许多drafts里的情况。

在后续drafts里,container requirements里,size在complexity列就被改为constant了。

如果这两者表达的是同一个意思 —— 也就是说C++03也要求是常数 —— 为什么要这么绕弯的表达?
如果两者表达的不是同一个意思 —— 也就是说C++03不要求,但C++11要求了 —— Note A里的东西又怎么解释?
目前看来两者表达的应该不是同一个意思: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49561


关于 Note A…… 要么是这段:
17.3.1.1 Summary      C++03
2 Paragraphs labelled ‘‘Note(s):’’ or ‘‘Example(s):’’ are informative, other paragraphs are normative.

17.5.1.2 Summary      C++0x
2 Paragraphs labeled “Note(s):” or “Example(s):” are informative, other paragraphs are normative.

要么就是英文里shall与should真的有很大区别么…… 英文苦手……

论坛徽章:
0
177 [报告]
发表于 2012-02-16 21:18 |只看该作者
回复 175# OwnWaterloo


    慢慢欣赏啊,有空再看吧。

论坛徽章:
0
178 [报告]
发表于 2012-02-16 21:31 |只看该作者
回复 174# OwnWaterloo


    总归就是提供一个中间的执行器,这样就可以集中力量优化这里。其实实现根本就不是什么问题,也没太大的难度,问题是大家都要遵守这个标准才行。一致才要紧

论坛徽章:
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
179 [报告]
发表于 2012-02-17 00:28 |只看该作者
OwnWaterloo 发表于 2012-02-16 18:57
最后关于你说的"虚假"的一致性。 我简直不敢想象这是你整理后的发言啊…… 完全有失水准…… totally w ...


你没理解重点。我说的很明白,所有语言都是递归模型,所以所有语言(高效的实现)都必须要有一个翻译模型:将递归模型做成平面的指令流模型。这种翻译在其他语言里面都是掩藏了的,不碰的。而在lisp里,它被公开化了,而且是被一种很不协调的方式公开化(宣称执行的是form,实际是翻译后的字节码),导致你如果要写宏,必须先生成form(实际上是个cons),然后将其变成代码。如果你要简单性,你不得不:

1. text->cons
2. cons->bc
3. eval(bc)

而lua只需要:

1. text->bc
2. eval(bc)

当然lisp暴露了第一个流程是有用的——就比如lua源代码里面没有ast,而lisp实际上相当于先到ast再到bc,这个ast本质上就是宣称的执行的东西了。而实际上这个被修改的,可以被执行的东西如果是在编译时——那无所谓u,但是如果在运行时,当所有的form都成了bc时,你还宣称可以改bc——lisp是倾向于这点的——那就成了不折不扣的虚假的抽象了——为了它你得带一整套编译器!必须的(注意lua是可以取消掉编译器的)

也就是说,要么废弃掉运行时能修改form的特点,要么就保留form的cons内容并随时准备cons->bc编译器。这难道不是一种虚假的一致性造成的实现复杂度么?

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
180 [报告]
发表于 2012-02-17 00:48 |只看该作者
starwing83 发表于 2012-02-17 00:28
而lua只需要:

1. text->bc
2. eval(bc)

这只是lua这样实现。
你再多找几个语言跳过tree,不是text->tree->bytecode/native code的看看?
lisp不过是将tree暴露出来,语言对程序员是公开而非隐藏的。

而且,one pass是牺牲了产生的代码质量来换取产生速度的 <- 没仔细研究过,直觉。


starwing83 发表于 2012-02-17 00:28
当然lisp暴露了第一个流程是有用的——就比如lua源代码里面没有ast,而lisp实际上相当于先到ast再到bc,这个ast本质上就是宣称的执行的东西了。而实际上这个被修改的,可以被执行的东西如果是在编译时——那无所谓u,但是如果在运行时,当所有的form都成了bc时,你还宣称可以改bc——lisp是倾向于这点的——那就成了不折不扣的虚假的抽象了——为了它你得带一整套编译器!必须的(注意lua是可以取消掉编译器的)

也就是说,要么废弃掉运行时能修改form的特点,要么就保留form的cons内容并随时准备cons->bc编译器。这难道不是一种虚假的一致性造成的实现复杂度么?

"但是如果在运行时,当所有的form都成了bc时,你还宣称可以改bc——lisp是倾向于这点的"的观点是如何得到的?
这东西没法改的好吗……

在lua代码里用了loadstring或者loadfile的情况下依然可以取消编译器?
所以问题不是带不带编译器,而是你是否需要运行时loadstring/eval的功能。
此处复杂度的等级是完全一样的,都必须带编译器。
区别是lua的编译器小,lisp的编译器大(就先假设它大吧,我不知道有没有小的只产生bc的编译器)。


当你需要这样的功能时,可以以一致的方式完成,这就是一致性的体现。由此带来的复杂度谁都没法避免。虚假从何说起?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP