《说文解字》与程序设计
说文解字
《说文解字》,简称《说文》,是由东汉经学家、文字学家许慎编著的语文工具书著作。《说文解字》是中国最早的系统分析汉字字形和考究字源的语文辞书,也是世界上很早的字典之一。
以上是“说文解字”在百度百科的解释,前段时间刷知乎时,看到了W雨辰一篇介绍汉字造字法(指事,象形,形声,会意,转注,假借)的文章,其介绍简单有趣,深入浅出,读完了之后感觉汉字的造字与程序设计、尤其是面向对象的设计有许多共同之处,写一篇文章记录一下思路,感兴趣的朋友可以一起来探讨下。
说文解字的格式
说文解字是有固定一种格式的,网上有许多网站支持搜索《说文解字》,打开一个词典网,在上面搜索“老”字,弹出来的结果是这样的:
这个格式分三部分:
1. 元数据:某字,配一张图。
2. 职责:X也。
3. 实现:从XX
比如:
化:教行也。从匕从人,匕亦声。
型:铸器之法也。从土刑声。
改:更也。从攴己。
它的模型猜想图如下:
解字
庖丁解牛,解一个汉字,看看说文解字是如何诠释的:
改:更也。从攴己。
这个【改】字的解释有点意思:从,就是继承的意思;从攴,继承于攴,攴从图画上看是一根小树枝的意思。那么这个“攴己”,就像是挥舞着小树枝抽打自己
……Why?为毛要抽自己?难道是因为自己欠抽吗??
——因为[更也]。更,指更新,鞭策自己是为了改过自新。
将上述描述换成面向对象语言:
class 更;
class 攴
{
public 更 Do(object o);
}
class 改 : 攴;
var o = new 改();
var result = o.Do(new 己())
从攴,从有继承的意思。从支己,就是继承(攴)并调用函数传参(己)的意思。
这里有歧义的地方是“更也”,这个“更”不能仅仅做返回值处理,其更多的是表达了一种差量元数据(diff merge's metadata),这个差量元数据体现出了目的性:
——鞭策自己是为了更新,这是“改”的本义。
用程序设计的思路描述:
class B;
class C;
class A :B
{
public C do()
}
翻译成说文解字:
A,C也,从B。
又如:
class B;
class C;
class D;
class A :B
{
public C do()
{
this.RaiseEvent(new D());
}
}
翻译成说文解字:
A,C也,从B,D声。
顺着这个解释,说文解字有着一系列精彩的发挥:
比如前面提到的“老”字:从人毛匕,它有三个元素:从人、毛、匕(hua=化)。
按照知乎上w雨辰的解释:“人、毛、化”就是人的毛的化的意思——将人的毛看做头发,头发变化了……大概率是变白了……变白了就是老了。
这样就通过人——毛——匕的链条将“老”的意思解释清楚,这个令读者使用“意会”的方式get到字的方法,按照许老的说法:叫做《说文解字》。
这个人—毛—匕的解释,在面向对象的语言中非常常见,就是对象的属性赋值:
class 人
{
public object 毛 { get; set; }
}
var ren = new 人();
ren.毛 = 匕;
以程序的角度来看,毛是人的一个属性,匕是毛的当前状态值。相当于
{人,毛,匕} => 老
汉字造字的原理有点意思,它将【动态】的属性赋值(或者叫方法调用),连带着参数压缩成了一个【静态】的字,化动为静,在读者阅读时再通过意会的方式在读者脑子中解释执行。这种模式有点类似于反射,但类型信息又非常灵活。
这种把多级的信息集压缩到一个平面上,使其变成一个字,是汉字的一个造字原理。其展开方式来自于读者的意会:造字时将立体压缩成平面,理解时在读者脑子中将平面还原成立体。
象形,指事,形声,会意,转注,假借
谈到了设计少不了模式,类似于程序设计的原则(开闭原则、单一职责原则等),说文解字也总结了其六大模式(设计原则),分别是:象形,指事,形声,会意,转注,假借,统称为六书:
六书:
一曰指事。指事者,视而可识,察而见意。上下是也。
二曰象形。象形者,画成其物,随体诘诎,日月是也。
三日形声。形声者,以事为名,取譬相成,江河是也。
四日会意。会意者,比类合谊,以见指撝,武信是也。
五日转注。转注者,建类一首,同意相受,考老是也。
六日假借。假借者,本无其字,依声托事,令长是也。
寻找下对应关系:
一、象形:顾名思义,就是抽象,通过形状上的相似抽象出对象。
object o = new object();
二、指事:指事。这个事用来特指,好比电影里面的特写镜头,点出来说明些“特殊味道”。
比如说 本 = 木 + 一,下面的“一”代表了树木的根部,用一(横)指出来,提醒人不管长多大,都不要忘记最初的一横。
指事在面向对象语言里,多用事件或消息表述:
o.RaiseEvent();
三、形声:把两个或多个对象放在一起来衍生,
“形”:定义了边界,定义了轮廓——对象在环境中的外在。
“声”,类似波,指对象对外能发出的功能。
class A;
class B
{
private A a;
public void Do { a.do(); }
}
按照汉字的解释,一个对象调用另一个对象的方法,就是借助此一对象让另一对象发出“声音”。
汉字在这里的解释有些意思,声音无孔不入,对一个对象的方法调用,表面上看,似乎只会对被修改的对象产生影响。而汉字用声音说明,这种改变对象状态会对系统内的所有对象产生影响,只是不容易从表面看出,因为光还没有照到其它对象。
好比,一个人听了一句话,虽然表面上不动声色,可内心早已mmp的……波澜汹涌。
四、会意:使用多重继承,将两个意象并列放在一起,令人意会。
比如“信”是会意,把“人”和“言”放在一起,令人意会(……人和言放在一起是什么意思……信的意思吗?),意会出的意思就比较接近了。
class A;
class B;
class C :A, B
相比于程序设计极力避开多继承,避开菱形继承,汉字系统就是建立在多继承的基础之上,在程序设计中is-a是主体,has-a是优选;而汉字系统中has-a是主体,is-a是优选。
五、转注:类似多态,又有点像函数调用链。
老,从人毛匕——“人”,调用“毛”,再调用“匕”,这种调用更像是一种连接,如何把“人”、“毛”、“匕”用合理性的方式连接起来,直接传达出使用者的意图。
令功能本义不变,边界旋转,寻找一种可以从一个字注入到下一个字的方法。
class A
{
private B b;
public void Do()
[
b.Do();
}
}
class B
{
private C c;
public void Do()
{
c.Do();
}
}
六、假借:
按照wu雨辰的解释:
比如“美”是指味道鲜美,但是人长得漂亮怎么形容呢?比如把人和美放在一起,那就把美假借为了“美丽”的意思了,跟“美”的本义“美味”意思不同,但是有没有必要再为了这层意思再造一个字形呢?其实没必要的,把“美”的字形拿过来假借一下,大家自然就明白什么意思了,“美”每变一个情景,就多一种假借,而且这个假借还让你看起来不动声色,后来才有了一字多义。
假借有种类型推断(匿名类型)的味道,将字还原到本义(将class还原成data、甚至还原成元数据metadata),再将其适配到其他字(类型)。
假借有一种系统间通过DTO传参的味道:
struct Data;
class A
{
public Data ToDTO();
}
class B
{
public static B FromDTO(Data data);
}
A a = new A();
var data = a.ToDTO();
var b = B.FromDTO(data);
模型
回到最初的字模型,猜想一下:字=元数据(形)+职责(音)+实现(义)
其模型图:
汉字是一种象形文字,它和拼音文字相比,最大程序保留了元数据(图)。
有了元数据,系统就有了回溯的可能——当汉字无法理解(无法沟通)之时,可以还原到图上来理解,相比于拼音文字,它提供了一种回溯(Recompile)的可能性。
使用者随时可以利用元数据瓦解一个字,来获得其原始“意图”。类似于对象设计中的object.GetType(),随时可获取对象的类型数据,这个元数据是以一种更高级别的抽象(粗略的图)来提供的。使用者可以与时俱进,将元数据的图根据当前环境重编译(重解释),以更好的适应时代的变化。
汉字的系统演进了几千年(或更久),现代的编程语言几年内就会有种面目全非、令创始人都感慨的变化,而汉字系统依旧保持着旺盛的生命力,其形音义的设计理念有着精髓之处,值得令人深挖。
这种在编码的时候附带元信息的方式,在程序中可是特性、或是注释,在沟通里被称为意图,在设计上又看成背景。通常情况下,它与主信息之间呈现一种分离态。
而在汉字系统中,形音义“三位一体”,一个字的形音义必须全部确定后,它才会长久地存在下去。
汉字演进
乘坐时光,回到汉字的早期年代,观察一下汉字的演进:
举个例子: 需求。
需求由“需”和“求”两个字组成。
需字:
求字
这两个字的图片有点意思,一个是一位"湿身"的男子,一个是一只伸长了求索的手。
需:天在下雨,人被淋湿。
求:一只伸长的手。
当“需”和“求”两个字金风玉露一相逢,便交会了人间无数。
做软件的少不了“需求”,这是一个高频词语,带点文绉绉,又很压人……“这个需求能否解决?”“确认一下客户需求。”“这个需求不合理。”
从元数据(图)上来看,这个词会有哪些启示呢?
单从图上来看,需求出现了三个基本元素:雨、人、手。
缺少这三个元素的其中之一,都不能称之为“需求”,比如:
1. 如果天不下雨,那就不叫需求。
2. 如果人没被淋湿,也不叫需求。
3. 如果没伸出手,更不叫需求。
换成客户(爸爸)的解释:
1. 如果市场环境没发生变化,不叫需求,提了白提,客户不理解——(雨)。
2. 如果客户没伤到切身利益,不叫需求,说了白说,客户不痛——(人)。
3. 如果客户没主动要求,不叫需求,皇帝不急太监急,没用——(手)。
将这个解释抽象出道理:
- 如果大环境、时间不对,不叫需求——天时。
- 如果区域不对,不叫需求——地利。
- 如果客户吃瓜看热闹,不叫需求——人和。
这是一种越过词语,直接从元数据(字义)看图说话的解释,相对于词义,汉字的字义往往携带了更精髓的最初的元信息。
再举个例子:封装(面向对象高频词)。
封=+寸(圭,诸侯的玉圭,代表责任;寸,恭恭敬敬手持,代表守责任)
装+壮(衣,上身穿的叫衣,下身穿的叫裳;壮,大也)
从字面来说,封装:要有责任,守责任,上身穿的好,肩膀端得住。
这个字面分析给出了一个很有意思的观点:面向对象的封装只封“上半身”即可,要玩“下半身失踪”。也就是说,面向对象的封装要有一种“并蒂莲”,要保留通过地下(类似于指针、内存)等从下一层次访问修改的可能性。
另,“壮”说明,对象的聚合性永远呈放大趋势,其有像龙卷风一样将其它对象席卷其中的野心——每一个对象都有成为“聚合根”的冲动和向往。
汉字系统
汉字的系统设计非常灵活,一个字既可以充当另一个字的基类,又可以充当另一个的方法、甚至可以是另一个字的元数据,其合理性来自于群体认证:
一个字(对象)不是合理才能应用,而是因为应用才产生合理。
汉字的意会方式是一种元数据交流方式,意会的过程是一个先编译后执行的过程。如果把两个人比做两台电脑,在它们的网络通信中,不使用RPC调用,不使用Restful方法,而是在传输中直接传送元数据,接收方得到元数据,在其本地进行(无厘头)编译,以一种本地热重载(创建类型、JIT编译、解释执行)的方式完成沟通。
意会是一种“大数据”编译。
这种元数据通信方式可以充分的解耦,其有很高的扩展性,其本地编译的效果取决于“常识”、“经验”、“情感”,像是一种“大数据”编译,其注重的是不要丧失“不确定性”,不确定性是确定性的背景,它为确定性提供了生命力以及演化的可能性,它使得概念向本义收敛与边界扩张两个维度变化。
总结
本文讨论了《说文解字》与程序设计的关系,但牵强附会的地方很多,很多地方都是(无厘头)编译——开局一张图,内容全靠编。
伟大系统总有共通之处。
作为流传了几千年、上万年的文字系统,其内部有很深的智慧存在。
学习先贤,吸取一些经历时间(实践)证明过的设计真谛,希望程序设计和汉字设计能够借鉴、融合。
希望有风来的地方,都有阳光闪耀。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。