.. Kenneth Lee 版权所有 2016-2020
:Authors: Kenneth Lee :Version: 1.0
关于自然语言编程的方向问题
这一篇插进来讨论一位读者私信来谈到的自然语言编程设计的问题。
我们说名可名非常名,是说,名字描述的仅仅是对象的一个(组)属性,永远都是不精确 的,编程语言也不可能跳出这个限制。我拿着一本书给你,说“这是书”,这里并没有说多 长时间,也没有说是否包括我的手,没有说什么其他和这个东西的相似度是多少才也叫书 。通过名称来交流,无论如何都是有很大的范围的允许的偏差度的。如果我们双方接受这 个偏差度,这个交流就能建立起来。所以,名虽然“非常(恒)名”,但还是“可名”的。
当然一般编程语言比自然语言更精确,因为编程语言收缩了名称空间的范围。
比如自然语言画一个圆,表述是这样的:
“给爷画个圆”
“靠,不要这么大,小一点,再小,哎对了,哎呀,过了,对对对,就这么大”
“不要用蓝色的,用红的,哎,对头——就是这种红”
用编程语言表述是这样的:::
import drawing
c = Circle(r=3, color=Drawing.red)
c.draw();
为什么后面这句话可以这么这么准确和简练?——奥妙就在Python的语言规范定义和这个 import上面,它们对表述的范围进行了更精确的细化。这种细化以更多的描述为基础的。
其实这个没有任何神奇的地方,自然语言也有这个能力的,读者应该注意到,几乎所有的 专业领域,都有行话,行话就是在特定的语境之下对语言的化简(我们把这个语义稍细化 一下:我把化简称为“行话”,把加密称为“黑话”)。行话要求交流的双方有共识,你常去 港式茶餐厅,你就可以点一个“冻柠走冰”,你不是常去,你就只能老老实实点“冻柠檬水, 请不要放冰块”。所有语言,只要在一个场合中不断使用,就会被优化,就会产生行话。编 程语言不过是一种行话。
其实,我们大部分的语言,都是为了让机器去适应人,但编程语言,现在还是在让人去适 应机器。前两天去听我们编译器部门的技术主任来讲最近一些新的语言发展方向,发现现 在的很多语言发展其实是陷入歧途的,更多关注在性能优化(比如对异常处理框架的一再 改写,对接口继承实现的后数据绑定等),并行优化(比如OpenMP的那些扩展语法),这 位主任自己在讲的时候都一再晕菜了,我相信他的技术能力,但他同时描述了几种语言, 这些语言又越来越偏离了自然语言的语言习惯,这样他肯定是很容易乱的。
我其实想说的是,这些优化,肯定不是编程语言的主流发展方向,编程语言的主流发展方 向是和人的思维一致,而不是偏离,如果有什么地方和人类不一样,那个东西就不应该是 编程语言,而应该是机器语言。 当然,我们要不断优化我们怎么说才能说清楚我们的要求 ,表述方式是要优化的,但它最终必须贴近自然语言的行话,而不是越来越接近机器。
所以,我认为,无论是自然语言编程,还是编程语言发展,其实都要向“行话”靠拢,行话 的特点如下:
不是一方向另一方妥协,而是双方向对方靠拢。不要尝试完全用自然语言去要求计算机 ,也不要太强求计算完全理解自然语言,因为语言的优化和“行业”息息相关
分行业来实现"行话"
我用一个例子来大概描述一下这种理念是怎么样的,还是用上面那个画圆的例子(我预期 读者基本上懂Python,Java一类的语言):::
localhost $ hanghua_python --debug
> import 小张
老板,您好
>少废话
(debug: 断句['少废话'], 主语:(auto, 你), 谓语:(少废话))
老板,我听不懂
> def alias 废话=你.verbose
(debug: alias 废话 defined in the current context)
> def 少(filter=prefix_on(废话): v(废话)=1
(debug: function 少 defined in the current context, filter=prefix for 废话)
> current_name_space.add_definition.addto('小张.lib')
> exit();
localhost $ huanghua_pyhon --debug
> import 小张
老板,您好
> 少废话
(debug: 断句['少', '废话'], 主语:(auto, 你), 谓语:(少), 宾语:废话)
收到
> 以后都少废话
(debug: 断句['以后', '都‘, '少', '废话'], 状语:(以后,都), 主语:(auto, 你), 谓语:(少), 宾语:废话)
(debug: 小张.verbose.static=true)
> 收到
> 给爷画个圆
(debug: 断句['给', '爷’, '画', '个', '圆‘], 忽略:’给', '爷', 主语:(auto, 你), 谓语:(画), 宾语:个,圆)
(debug: Circle(r=3, color=red).draw(), instance_id=0x1134)
> 蓝色的
(debug: 断句..., 主语:(auto, 你(忽略), Circle(instace 0x1134)), 谓语:(auto set_attr), 宾语:蓝色的)
(debug: Circle.find_instance(0x1134).set_stoke_color('blue'), curr_stoke_color=blue)
>浅一点
(debug: 断句...)
(debug: current_stoke_color.set(curr_stoke_color.get_color()-10), Circle.find_instance(0x1134).set_stoke_color(current_stoke_color))
> 不错
(debug: 断句)
(debug: ignored)
> 以后圆都这样画
(debug...)
> current_name_space.add_definition.addto('小张.lib')
> exit()
localhost $ huanghua_python
> import 小甜甜
老板,你来啦,怎么这么多天都没有来看人家了嘛
>心肝宝贝,我这不是来了么
……
大概就是这个意思,自然语言编程最终就是向这个方向走,自然语义不是不可识别的,只 是实现的余地大而已,自然语言断句其实没有任何难度,只是通常会多义,这时,让人向 计算机妥协就可以了,多义断句就多问几次,或者自动选一个,错了就改,这样人和计算 机打磨一段时间后,就可以会形成行话,这种习惯,把它保存在特定的名称空间中,在需 要的时候import到当前的名称空间中,就可以形成一个很大的资源池,未来我们就有可能 实现让所有人都编程序这样的目标了。因为当基本计算机语义被自然语义覆盖的之后,编 程就可以不仅是程序员的事情了。我原来还实现了一段时间这个东西,后来接了一个新项 目,比较有趣,等过几年我搞定手上这个项目,我就出来弄这么个开源项目玩:)
(顺便插一句,对于语义的缝这个问题,特别推荐看看《哈利波特》,里面所有的迷题, 几乎都是找”话缝“,告诉你”正确“的表达背后隐藏的真相。我觉得做自然语言理解的人, 都值得看看罗琳的书,无论是哈利波特还是后来的布谷鸟的呼唤,蚕等,都是这个套路)
其实,这里也说明了,为什么我们要在软件定义的时候,要让所有的函数名,变量名,使 用它的自然语言含义,为什么我在很多地方都强调,编程要基于语义来编程,而不是基于 实际运行效果来运行。因为一旦你的程序离开了自然语义,你的程序就进入机器的语言空 间了,人是罩不住庞大的机器语言空间的,一旦kill从杀死变成了发信号(一个两个是没 有问题),wait()表示打印,sleep()表示清空缓冲区,你就算你的程序运行得一切正常, 你以为你还能掌控(升级)你的程序?