作者归档:s

大饼谬论

节选自Paul Graham《Hackers and Painters》

谈到财富总额的时候,财富经常被形容为一个大饼。政治家说:“你无法把饼做的更大。”如果指的是某个家庭银行上的金钱数量或者政府某年的税收,这样收是对的。确实无法把饼做的更大,你分到的越多,别人就分到的越少。

小时候我就对这一点深信不疑:如果富人拿走了所有的钱,那么其他人就变得更穷的。许多成年人至今都是类似看法的信徒。每当有人提到x%的人口占有了y%的财富,他的言下之意往往就包含了这种错误的观点。如果你打算创业,那么不管你是否意识到了,你都是在着手推翻这种大饼谬论。

这里令人混淆的地方就是金钱尤其抽线含义的一面。金钱不是财富,而只是用来转移财富所有权的东西。所以,虽然在某些特定的情况下(比如某个家庭某月的收入),你能用来与他人交换的金钱数量是固定不变的,但是大多数情况下,世界上可供交换的不是一个恒定不变的量。人类历史上的财富一直在不停增长和毁灭(总体上看是净增长)。

假如你有一辆老爷车,你可以不去管它,在家中悠闲度日,也可以自己动手把它修葺一新。这样做的话,你就创造了财富。世界上因为多了一辆修葺一新的车,财富就变得多了一点,对你尤其如此。

通过修理一辆老爷车,你使得自己更富有。与此同时,你也并没有使得任何人变得更贫穷。所以,这里明显是一个不变的大饼。事实上,当这样观察的时候,你会很好奇,为什么有人会觉得大饼的无法增大。

孩子在不知不觉中就懂得了这个道理。如果一个小孩想赠送另一个小孩一件礼物,但是又没有钱,他就会自己动手做。只不过一般情况下小孩子的动手能力不足,相比店里买来的礼物,他们自己做出来的东西从上显达比较粗糙。说实话,我们自己为父母做的松松垮垮的烟灰缸恐怕就很难在市场上卖出去。

字符集与编码方案详细说明

1 文字处理的最朴实场景 – 显示

以文字处理的朴素场景“显示”为例,我们反向推导一下怎么将某个文字在显示器上显示出来。

  • 对显示器来说,它并不知道自己显示的是什么。比如要显示文字“5”,应该给它文字“5”对应的位图数据;
  • 所以,我们首先得从一个地方得到“5”的位图;
  • 可以理解,“5”的位图不是凭空产生的,它必须是预先定义好的一个图片、或一组曲线……其它可显示的文字也应该有各自的绘图数据,这个存储着很多字符的绘图数据的东西,可能在很久以前是一个叫 “汉卡”的硬件、也可能在现在是一个“字体“文件;
  • 如果汉卡或某字体文件中定义了6万个字符,应该怎么找到文字“5”对应的绘图数据呢?
  • 这里出现了一个查询需求。无论是汉卡还是字体文件,它内部必须有一套索引体系,以便调用者查询到某个文字的绘图数据;这套索引实际是一套键值对集合,其中“键”对应要找的字符,“值”对应绘图数据;

到这个地方,整个逻辑就清晰了:

Q:一个信息化系统中,可以显示哪些文字?

A:本系统支持的字符集

Q:在汉卡或字体文件中查询文字的“键”是什么呢?

A:依据本系统中的文字编码方案

Q:各个信息化系统对同一文字,比如大家对“5”的编码方案相同吗?

A:各不相同。但未来的趋势是走向相同

2 字符集

2.1 字符

字符是人类可以理解的最小语言单位,泛指自然语言里所有的文字或符号。在电脑及电信(下文统称信息化)领域,字符是一个信息单位。它大约对应自然语言里的一个单位、符号,或是一个汉字、假名、韩文字,或是一个英文、一个其他西方语言的字母。或是一个音节里的一个音位、类音位……

此外,在信息化领域,还有一个“控制字符”的概念。控制字符并不对应到自然语言中的某个特定符号,而是对应到语言中用来处理文句的概念(类似排版)。如控制打印机的“换行符”、“Tab符”。

所以,我们讲的字符,可分为“可打印字符”和“控制字符”两类。

2.2 字符集

因为字符是人类的主观理解,所以其范围过度宽泛。在电脑及电信领域进行信息化处理时,任何一个子系统需要处理的字符范围都只能是一个有限集。所以标准化组织(国际或国家标准)或国家级行政单位会针对 “需要支持哪些字符”而设定一些规范。这些规定内“字符”的集合就叫字符集。

需要强调的是,字符集规范发布时会为每个字符都指定一个编号,这个编号的本质是一种排序。此编号数值与实际的字符编码数值并不完全一致。虽然大多数信息化系统中ASCII字符的编号正好是编码值。

2.3 编码方案

用什么数值来表示某个字符,是一种规范约定,这种约定即是“编码方案”。一个完整的编码方案,包含两个必须因素:①单个字符的的数据长度;②编码数值与文字的转换方法,这个转换方法可能包含一个编码转换表(代码页)。

2.3.1 早期的代码页方案

由于固定长度数据类型的取值范围是固定的,任何编码方案都是在用有限的整数取值范围去对应不同的字符集。为了支持更多的世界语言, IBM和微软都使用了代码页的概念,在不同语言的系统中使用不同的代码页处理文字。

对于欧洲和西亚语系,可以使用8位整数去对应他们的字符集。一般使用低7位的128个编码空间对应ASCII字符。然后,利用高8位去对应语言内的其它字符。如Windows简体中文系统中使用代码页CP936,繁体中文系统中使用代码页CP950。所以代码页是个字符映射表,早期的Windows系统会带着一个“字符映射表”程序。

各种代码页上的字节流含义是互不相同的。并且,IBM(OEM/IBM PC)的代码页与微软(ANSI)的代码页,即便语言相同,也是互不通用的。一个OEM上的字节流如果想正确的显示在Windows系统中,需要显示指定OME代码页。或显示转换OEM字节流为ANSI字节流,这时需要用到Windows系统的API: OemToChar()。

2.3.2 包含一切的万国码

代码页处理字符的局限显而易见,相同的数据使用不同的代码时,获得了不一样的字符。比如0xB9F1在简体中文CP936里是“国”,在CP950繁体中文里是“弊”。

所以,业界需要一个统一的“字符定义码”去包含世界上所有的字符,这样就可以在同一系统内支持世界语言。

这便是Unicode码,也被称为万国码、单一码、统一码。它是一个包含所有语言、所有字符的排序表,任意一个字符都有一个与之对应的排序号,这个排序号即是字符的Unicode码。Unicode码是一个连续的整数,目前已定义了0x00000-0xfffff区间的用途。①Unicode每隔0xffff区间,也叫1个平面,总共16个平面。

Unicode已被ISO作为国际标准采纳于通用字符集,即 ISO/IEC 10646,Unicode兼容ISO/IEC 10646且完整对应各个版本标准。

3 常见的国家标准字符集

3.1 GB2312

GB/T 2312[注 1],GB/T 2312–80 或 GB/T 2312–1980 是中华人民共和国国家标准简体中文字符集,全称《信息交换用汉字编码字符集·基本集》,通常简称GB(“国标”汉语拼音首字母),又称GB0,由中国国家标准总局于1980年发布,1981年5月1日实施。GB/T 2312编码通行于中国大陆;新加坡等地也采用此编码。中国大陆几乎所有的中文系统和国际化的软件都支持GB/T 2312。

GB/T 2312标准共收录6763个汉字,其中一级汉字3755个,二级汉字3008个;同时收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个字符。

3.2 BIG5

大五码(英语:Big5,又称为五大码)是使用繁体中文(正体中文)社群中最常用的电脑汉字字符集标准,共收录13,060个汉字。

“大五码”(Big5)是由台湾财团法人信息产业策进会为五大中文套装软件所设计的中文共通内码,在1983年12月完成公告,隔年3月,信息产业策进会与台湾13家厂商签定“16位个人电脑套装软件合作开发(BIG-5)项目(五大中文套装软件)”,因为此中文内码是为台湾自行制作开发之“五大中文套装软件”所设计的,所以就称为Big5中文内码。五大中文套装软件虽然并没有如预期的取代国外的套装软件,但随着采用Big5码的国乔中文系统及倚天中文系统先后在台湾市场获得成功,使得Big5码深远地影响繁体中文电脑内码,直至今日。“五大码”的英文名称“Big5”后来被人按英文字序译回中文,以致现在有“五大码”和“大五码”两个中文名称。

3.3 GB13000

GB 13000,中华人民共和国国家标准的国家标准代码之一,全称 GB 13000.1-93《信息技术 通用多八位编码字符集(UCS)第一部分:体系结构与基本多文种平面》。此标准等同采用国际标准化组织 ISO/IEC 10646.1:1993《信息技术 通用多八位编码字符集(UCS)第一部分:体系结构与基本多文种平面》。即“GB 13000.1-93”等同于Unicode 1.1版本。

GB 13000.1-93的字符集包含20,902个汉字,附录是GBK。

2010年1月10日发布的GB 13000-2010取代了GB 13000.1-93,于2010年11月1日实施。是ISO/IEC 10646:2003《信息技术 通用多八位编码字符集(UCS)》等同采用。由中国标准出版社出版,16开1476页。

3.4 GBK

全名为《汉字内码扩展规范(GBK)》1.0版,由中华人民共和国全国信息技术标准化技术委员会1995年12月1日制订,国家技术监督局标准化司和电子工业部科技与质量监督司1995年12月15日联合以《技术标函[1995]229号》文件的形式公布。

GBK的K为“扩展”的汉语拼音(kuòzhǎn)第一个声母。

GBK共收录21886个汉字和图形符号,其中汉字(包括部首和构件)21003个,图形符号883个。

GBK 只为“技术规范指导性文件”,不属于国家标准。国家质量技术监督局于2000年3月17日推出了GB 18030-2000标准,以取代GBK。GB 18030-2000除保留全部GBK编码汉字,在第二字节把能使用范围再度进行扩展,增加了大约一百个汉字及四字节编码空间,但是将GBK作为子集全部保留。

3.5 GB18030

GB 18030,全称《信息技术 中文编码字符集》,是中华人民共和国国家标准所规定的变长多字节字符集。其对GB 2312-1980完全向后兼容,与GBK基本向后兼容,并支持Unicode(GB 13000)的所有码位。GB 18030共收录汉字70,244个。

GB 18030不是一个汉字规范,不定义汉字的写法。中国大陆在此方面的规定由《通用规范汉字表》管理。

3.6 通用规范汉字表

《通用规范汉字表》是《中华人民共和国国家通用语言文字法》的配套规范,是现代记录汉语的通用规范字集,体现着现代通用汉字在字量、字级和字形等方面的规范。2013年6月5日,国务院发出关于公布《通用规范汉字表》的通知,国务院同意教育部、国家语言文字工作委员会组织制定的《通用规范汉字表》,并予公布。《通用规范汉字表》公布后,社会一般应用领域的汉字使用以《通用规范汉字表》为准,原有相关字表停止使用。 该表共收录汉字8105个。

3.7 CJK中日韩统一表意文字

3.7.1 简介

中日韩统一表意文字(英语:CJK Unified Ideographs),也称统一汉字、统汉码(英语:Unihan),目的是要把分别来自中文、日文、韩文、越南文、壮文、琉球文中起源相同、本义相同、形状一样或稍异的表意文字,在ISO 10646及Unicode标准赋予相同编码。

所谓“起源相同、本义相同”、主要是汉字,包括繁体字、简化字、日本汉字(漢字/かんじ)、韩国汉字(漢字/한자)、琉球汉字(漢字/ハンジ)、越南的喃字(𡨸喃/Chữ Nôm)与儒字(𡨸儒/Chữ Nho)、方块壮字(𭨡倱/sawgun)。

3.7.2 历史版本

 Unicode码位版本及数量 
1993.5U+4E00–U+9FFF1.0 20902“〇”(码位U+3007),被当成数字放入了符号和标点区
1999U+3400–U+4DFFExt-A 6582 
2001U+20000–U+2A6FFExt-B 42,711 
2005U+9FA6–U+9FBBExt-B-修订1 22 
2009U+2A700–U+2B734Ext-C 4149 
2010U+2B740–U+2B81FExt-D 224  2012增加1个汉字:U+9FCC
2015U+2B820–U+2CEAF U+9FCD–U+9FD5Ext-E 5776 
2017U+2CEB0–U+2EBEF U+9FD6–U+9FEAExt-F 7488+142018增加5个汉字U+9FEB–U+9FE
  2020U+30000–U+3134A U+9FF0–U+9FFC U+4DB6–U+4DBF U+2A6D7–U+2A6DDExt-G 4939+13+10+6
U+31400–U+33D1F预计放置小篆,U+33E00–U+355FF预计放置甲骨文,相关提案已经提交。按路线图,该平面还会收录金文、简帛文、陶文、鸟虫书等

4 软件开发中的一些问题

4.1 如何读取一个文本文件

读取文本文件的过程是一个将字节流转换为字符串的解码过程。所以必须约定好文本文件中的字符串用什么格式存储。

在Windows系统中,一般使用BOM来指定文本文件的编码方式。即在文本文件的最开头使用一组特定的BOM字节流来指定本文件的文本编码方式。常见的BOM有以下几种。

编码类型BOM(十六进制)BOM (十进制)
UTF-8EF BB BF239 187 191
UTF-16 (BE)FE FF254 255
UTF-16 (LE)FF FE255 254
UTF-32 (BE)00 00 FE FF0 0 254 255
UTF-32 (LE)FF FE 00 00255 254 0 0
UTF-72B 2F 7643 47 118
UTF-1F7 64 4C247 100 76
UTF-EBCDICDD 73 66 73221 115 102 115
SCSU0E FE FF14 254 255
BOCU-1FB EE 28251 238 40
GB-1803084 31 95 33132 49 149 51

在Linux、Apple等系统中,一般不使用BOM,在存储时默认以UTF8存储。读取文本文件时,默认以UTF8方式识别。如果UTF8识别报错,会再尝试以本地语言代码页识别文本。

4.2 源代码中的字符串

在VisualStudio系列软件中,早期的代码文件默认以ANSI方式编码。后来默认以UTF16-LE BOM编码。所以读写源代码文件时,按如下优先级一次识别①识别BOM→②识别为本地代码页。

在跨平台开发中,如果源代码保存为UTF8编码且源文件中包含非ASCII字符时,VisualStudio编译会报无法识别的字符错误。要解决这个问题,可以使用/source-charset:utf-8指定源代码文件的默认编码响应方式。

同样,在GCC系列软件中,默认以UTF8方式编码。早期的GCC可能无法识别BOM头,导致编译报错无法识别的字符。

4.3 内存中的字符串

需要注意的是,VisualStudio开发环境中既区分了源代码的文件编码,又区分了字符串在内存中的编码。对于一个多字节字符串的双引号定义方式,如:const char* text = “大家好”;开发者需要特别关注到此时text中的字符串编码是本地语言的代码页编码。即使文件使用UTF8保存,且指定了/source-charset:utf-8。

也就是说,VisualStudio总是默认以本地语言代码页处理文本。而在GCC环境中,则总是以UTF8方式处理。

需要对最近做一个反思

1 积累了很多对现在团队的偏见,导致负面情绪越来越越多,加之外部环境的催化。这个负面情况让我无法在公开场合的交流中保持足够冷静。

2 从鸡汤文章中看到,好的管理不应该多做,应该把事分给大家,大家才能成长。这是对当前项目放手的主要原因。相比前一个项目,我做好了绝大部分的框架和疑难攻坚,但大家可能真的没啥成长。另一个原因,我确实想看看“Delay”一次它能咋地……

3 高估了团队实力,提测质量及问题题的修复速度都在我意料之外。

4 低估了错误在团队中的传播速度,也不知道别的团队是什么样子。


↓ ↓ ↓ ↓

1 不要被未确定的东西影响,尤其是想象中的好东西

2 任性了点,应该放手+把控,不能任性

3 不能乐观

4 不能乐观

转:论无用知识的有用性

译:论无用知识的有用性 The Usefulness of Useless Knowledge (douban.com)

在这个深陷非理性仇恨的世界里,文明受到仇恨的威胁。狂热分子们忙着扩散病痛、散布丑恶、四处蔓延各种折磨四处;现实生活中的人们,却忙着将自己与深处其中的滚滚怒潮或完全或部分的隔开,转而投身美的教化、知识的积累、医病救人和减轻折磨。这难道不是一件奇怪的事吗?长久以来,对这个世界,我们觉得哀伤与困惑——诗人、艺术家、科学家们却对一些东西熟视无睹——若将它们处理得当,本是有可能控制住那些疼痛、丑恶和折磨的。学术和精神生活看似一无所用,却能让沉陷其中的人获得别处无法给与的满足。本文将论述的是,对这些“无用”满足感的追求,究竟成就了多少了做梦也想象不出的“用处”。

总有人说,这是一个物质时代,这个时代关注物质商品和机遇更广泛的散布。一些人自己没做错事,却被剥夺应有机会和资源,遂发出正当的呼喊。这让越来越多的学生将研究重心从父辈关注的问题转向同样重要和紧迫的社会、经济、政治问题。对于这一趋势我并无异议。我们正身处唯一一个能够被感官证实的世界,如果它没有变的更好、更公平,人们只能世世代代默默走向坟墓,哀伤和苦涩。我曾呼吁多年,学校须对学生们即将奔赴并在其中度过一生的现实世界了解的更真切更具体。现在我常想,呼吁是不是不够强?这个世界若排空仅提供精神价值的“无用”的东西,是不是就有充分的机会赋予充实的生命?换句话说,我们对于“用”的概念是不是太窄,窄到不足以去理解神游于天地之间、具备多种可能性的人类精神?

这个问题可以从两个角度来看:科学角度和人文或精神角度。首先是科学角度。我想起多年前与乔治•伊士曼(George Eastman)一次关于“用”的谈话。伊士曼先生是一位智慧、富有远见的谦谦君子,对音乐和美术兼具不俗的品味。他告诉我将花费大笔财产用于促进“有用科目”(useful subject)的教学。我试着问他,谁是他心中最有用的科学家?他不假思索的答:“马可尼(Marconi)”。我不怕惊到他,说:“无论我们从广播获得怎样的快乐,无论无线电和广播为人类生活带来了什么,马可尼的贡献都是几乎可以忽略不计的。”

我至今难忘伊士曼先生当时的震惊。他请我给出解释。我是这样说的:
“伊士曼先生,我们总会有一个马可尼。无线电领域的任何一次成就,就算是奠基性的成就,都可以属于任何人,克拉克•麦克斯韦(Clerk Maxwell)教授 1865 年提出电磁场内深奥难懂的运算,并于 1873 年在一篇论文中复制了他的抽象等式。在英国科学协会的另一次会议中, 来自牛津大学的史密斯教授(H.J.S Smith)宣称:‘没有哪个数学家能在翻阅这些卷册的时候不意识到,这其中包含着一个理论,该理论曾极大的丰富了纯数学的方法和资源。’此后十五年间,麦克斯韦的理论成就不断得到科学发现的补充和完善。到了 1887 年和 1888 年,尚有一个未解难题——无线电信号的载体电磁波的探测和演示——终被柏林亥姆赫兹实验室(Helmholtz Library)的海因里希•赫兹(Heinrich Hertz)攻克。麦克斯韦和赫兹都不曾关心自己做的研究有何“用处”,这是不可能闯进他们脑子的东西,他们没有实际目标。从法律角度上说,马可尼无疑是无线电的发明者,但马可尼究竟发明了什么呢?不过是一些后期的技术细节,其中有一大部分是一种被称为检波器的装置,现在都没人用了。”

赫兹和麦克斯韦可能不能发明具体的东西,但他们“无用”的理论工作一旦被某个聪明的工程师捕获,立即创造出全新的通讯和娱乐工具,这个贡献相对微弱的人收获名望、挣个盆满钵满。谁才是有用的人?不是马可尼,恰恰是麦克斯韦和赫兹。赫兹和麦克斯韦才是天才,不考虑“用处”的天才。马可尼是聪明的发明人,除了用处什么也不考虑。

赫兹这个名字让伊士曼先生想到赫兹电波,我说要想赫兹和麦克斯韦究竟做了些什么,该问问罗切斯特大学的物理学家们。但有一点是值得确信的,赫兹 和麦克斯韦的工作从未虑及“用处”。在整个科学史上,绝大多数真正伟大、被后人公认为对人类有益的发现都源于不被“用处”驱动的科学家,满足好奇心是他们唯一的渴望。
“好奇心?”伊士曼先生问。
“是的,”我说,“好奇心有可能引发有用的东西,也可能引发不了。好奇心是现代思维的一个典型层面。它可不是新东西。好奇心可追溯到伽利略、培根、牛顿,它是绝不曾被阻滞的。” 教育机构应致力于培养好奇心,越是少受到即时“用处”的不良影响,好奇心就越有可能为人类福祉做贡献,与此同样重要的是,好奇心将满足学术兴趣,这是每一位当代科学工作者都应保持的极其重要的激情。

二.

十九世后期,赫兹在亥姆赫兹实验室的角落里默默工作,多年来,他的真正成就任凭数学家、科学家评说。现在,我们生活在一个没了电就荒凉一片的世界里。若是被问起什么是最直接、影响最广泛的发明,我们会不约而同的说:电。但究竟是谁先做出了奠基性的发现,才让我们迎来电力的百年发展呢?

问题的答案很有意思。法拉第(Michael Faraday)的父亲是名铁匠;法拉第原本是个装订实习工。1812 年,法拉第二十一岁,一个朋友领他去了英国皇家协会,在那里法拉第聆听了四场汉弗莱•戴维爵士(Sir Humphrey Davy)化学物质方面的演讲,他做了笔记并向戴维递交了笔记的复本。1813 年,法拉第成为戴维实验室的助手,研究化学问题。两年后,法拉第陪同戴维访问欧陆。 1825 年,三十四岁的法拉第成为英国皇家协会实验室主任,一待就是四十四年。
法拉第的兴趣很快从化学转向电和磁,并为此奉献余生。这一领域重要、艰难的工作已由奥斯特(Oersted)、安培(Ampere)和沃拉斯顿(Wollaston)完成。法拉第攻克了上述诸位留下的未解问题,截止 1841 年,法拉第已成功实现电流感应。四年后,法拉第迎来事业的第二个辉煌时期,他发现了磁场对激光的影响。日后,这些早期发现都非常“有用”,有了电,现代生活的负担大大减轻,各类机会越来越多。在科研生涯后半段,法拉第科研成就的实际效果远比不上前半段。这对法拉第来说有什么不同吗?毫无不同。在法拉第无以伦比的科学生涯中,他从不曾过问过“用处”。他着迷的是揭开宇宙之谜——化学之谜、物理之谜。法拉第的视野内,“用处”不曾露头。任何有关“用处”的迷信都可能箍住法拉第汲汲不休的好奇心。最终,“用处”还是实现了,尽管人们从不曾用它来评判法拉第一生的科学追求。

面对今日世界的大气候,是时候强调一个事实了:在使战争变得更具毁灭性、更恐怖的过程中,科学的作用是科学活动无意识、无预期的副产品。瑞利勋爵(Lord Rayleigh)在近期一份报告中详细指出,正是人类的愚蠢,而非科学家的初衷,导致了现代战争中化学药剂的毁灭性运用。碳化合物的化学研究产生过大量有益的成果,硝酸对于苯、甘油、纤维素等物质的作用得到明确,这不仅促进了苯胺染料产业的发展,还创造出硝化甘油,产生了好和坏的作用。不久后诺贝尔(Alfred Nobel)转向同样的专题,研究得出,将硝化甘油与其他物质混合,可产出固体爆炸物,如炸药等,人们从此可以安全的使用炸药。炸药促成了采矿业的突飞猛进,对铁路隧道的挖掘贡献巨大,如穿越阿尔卑斯山和其他山脉的隧道。与此同时,炸药被政客和士兵滥用。炸药的罪恶当然不能算在科学家头上,就像不能因为地震或洪水而责怪科学家。约两千年前,普林尼(Pliny)在维苏威火山爆发时吸入二氧化硫,失去生命。氯不是为了战争目的才被科学家分离出来,芥子气也一样。这些物质本可只服务于合理用途,但一旦飞机变得更好,那些心中了毒、脑子变了质的人们就觉得飞机作为一项无辜的发明、一项长久以来不问世事的科学研究的成果,应该用作毁灭性工具,尽管这一想法科研人员做梦也没想到过,也从未有人致力于此。

在高等数学领域,我们可以找到大量这样的例子。十八、十九世纪最晦涩的数学研究是“非欧几里得几何学”。它的发明者高斯(Gauss),被同代人誉为最杰出的数学家,却在长达四分之一个世纪的时间里,不敢发表有关“非欧几里得几何学”的研究成果。假若没有高斯在哥廷根的研究,相对论本身及其丰富的实用价值只怕全都是泡影。
和“非欧几里得几何学”一样,“群论”(group theory)也是一种抽象、不可用的数学理论,人们受好奇心的趋势,像做游戏一样推动这个理论走上一条奇异的道路。“群论”现已成为光谱学(spectroscopy)量子理论的基础。日常生活中,我们也会用到“数论”,却常常对它一无所知。
概率论微积分是有志将赌博合理化的数学家发现的。微积分未能实现初衷,却为各种类型的保险提供了科学根据,十九世纪物理学的大量研究亦以此为基础。

下面这段话引自近期的《自然》杂志:
“爱因斯坦教授的才智的地位达到新高——这位博学的数学物理学家十五年前的数学研究现正帮助解决温度计上绝对零度附近氦的流动性问题。在美国化学协会召开分子间作用大会之前,现正在杜克大学做访问学者的来自巴黎大学F•伦敦(F. London)教授,将“理想”气体这一概念归功于爱因斯坦教授,这一概念曾出现在他 1924 年和 1925 年出版的论文中。
爱因斯坦1925 年的报告无关相对论,讨论的是些当时看来毫无“用处”的论题。论文描述了一种“理想”气体在温度计下限出现的简并现象。由于人们知道所有气体都会在一定温度凝结为液体,爱因斯坦的这一研究并未在十五年前引起同行的注意。
然而,近期发现的液氦的流动性使得爱因斯坦的这一边缘发现产生新的“用处”。多数液体在温度下降时会增强粘度、流动变缓。“比一月的糖浆还冷”这一词组正是外行人士对粘性的正确理解。
液氦却是个让人费解的例外。在三角点温度,即比绝对零度仅高出 2.19 度时,液氦的流动却比在温度更高时快。液氦之于液体就像星云之于气体。液氮还有其他奇怪的性状,如超强的导热能力。在三角点,液氦的导热性比室温条件下铜的导热性高出五百倍。有了这些异常属性,液氦成为物理学家和化学家面前的一个大谜团。
伦敦 教授指出,对于液氦性状的最佳阐释是将其作为一种玻色-爱因斯坦(Bose-Einstein)“理想”气体——应用爱因斯坦1924-25 年间的数学研究,再加上一些金属电导的概念。做个简单的类比就是,像描述电导时金属内到处乱跑的电子那样去描述液氦神奇的流动性。”

让我们从另一个角度看问题。在医疗和公共健康领域,细菌学占据领导型地位达半个世纪之久。这又是个怎样的故事呢?自 1870 年普法战争以降,德国政府成立了伟大的斯特拉斯堡大学。解剖学的首位教授是瓦尔代尔(Wilhelm von Waldeyer), 后来成为柏林大学解剖学教授。在回忆录中,他写道,在斯特拉斯堡大学的第一个学期,有个十七岁的学生,名叫保罗•欧立希(Paul Ehrlich),此人身材矮小、毫不起眼、沉默寡言。解剖学的常规课程包括解剖和显微镜观察组织。欧立希很少关注解剖课,然而,如瓦尔代尔写道的那样:
“我很早就注意到欧立希伏案数小时,沉浸在显微镜观察之中。渐渐地,他的桌子上满是每次观察的着色记录。有一天,我看到他在桌前工作,就走向前去,问他在用桌上彩虹色带做什么。这个刚进校不到一学期、本应学习解剖学常规课程的学生抬头看看我,大言不惭的说:‘Ich probiere.’这句话可直译为:‘我在试’或‘我在犯傻。’我说;‘很好。继续犯傻吧。’不久我发现,无需任何教育或引导,我已在欧立希身上找到了一种非同寻常的品质。”
瓦尔代尔很明智,对欧立希不管不问,后者勉勉强强的学习医学课程,并最终拿到学位,而这也多半是因为,老师们很清楚,医学学位不会被欧立希用于行医。果然,欧立希去了布雷斯劳(Breslau),师从孔海姆(Cohnheim)教授——我院韦尔奇博士(Welch)的老师、约翰霍普金斯医学院的创立者。在我看来,欧立希从未考虑过“用处”这个问题。他只是感兴趣,觉得好奇,始终如一的犯着傻。固然他的犯傻自深处受到直觉的引领,但那是一种纯科学、而非功利的动因。结果呢?科赫(Koch)和他的同事们创立了一门新学科——细菌学。欧立希的实验由一位学生应用于实践——威格特(Weigert)通过将细菌着色、对它们进行区分。欧立希发展了用染料对血涂片进行涂色,为现代人理解血细胞形态学——红细胞和白细胞——奠定了基础。岁月流转,全世界的医院都在应用欧立希的技术进行血液检查。当年在瓦尔代尔的解剖室中犯傻的欧立希,是这项重要医疗技术的头号功臣。

我该举个工业界的例子,随便举一个吧,因为实在太多了。来自匹兹堡的卡内基理工学院的Berl 教授这样写道:
“现代人造纤维产业的创始人是法国人夏尔多内(Count Chardonnet)。大家都知道,他将沾了硝酸溶液的棉布放入醇醚,再将粘性溶剂通过毛细血管注入水中,使之凝结成硝酸纤维素纤维。聚合之后,他将这种纤维置于空气中,绕在线筒上。某天夏尔多内到他位贝桑松(Besancon)的法国工厂视察,本应聚合硝酸纤维素纤维的水突然停止运转。工人们这才发现无水纺丝比有水纺丝效果更好。也就是在这一天,干式纺丝诞生,日后得到最广泛的应用。

三.
.
我并不是说实验室里的东西终将产生令人始料未及的用途,也不是说只有最终的“用处“才是考量科学研究合理性的标准。“用”是我呼吁破除的概念,我呼吁人类精神的解放。奇思妙想倘若无害,就应自由驰骋,尽管这可能要花不少钱。但远远比钱重要的是,粉碎禁锢人类思想的锁链,给思想探险的自由。凭着这份自由,哈尔(Hale)、卢瑟福(Rutherford)、爱因斯坦(Einstein)等科学家披荆斩棘、向着宇宙最深处不断探寻,凭着这份自由,紧锁在原子内部无穷无尽的能量得到释放。卢瑟福和波尔(Bohr)、密立根(Millikan)等科学家跟随好奇心的趋势,研究原子构造,并从中得到足以改造人类生活的力量。但最终这些实际用途是研究之初不可预知的,卢瑟福、爱因斯坦、密立根、波尔等科学巨匠的成就也远非“用处”能够证明。

没有哪个教育行政管理者可能预见得到上述以及其他科学家会研究什么。我再次重申,他们看似浪费大量人力物力,实则不然。发展细菌学耗费的人力物力与从巴斯德(Pasteur)、科赫(Koch)、欧立希(Ehrlich)、史密斯•西奥博尔德(Theobald•Smith)等科学家的研究成果中产生的巨大收益相比,简直一粟见于沧海。可是如果手中的研究会产生何种“用处”的顾虑潜入他们的头脑,成果定难如此丰硕。这些科学家、细菌学家是伟大的艺术家啊!他们在实验室里追随与生俱来的好奇心,任自由的精神在实验室里扩散。

“用处”已成为统摄工程学院、法学院等研究机构的唯一动机,对此我无意指手画脚。现在越来越常见的是情况是头尾倒置——工业界或实验室里遇到了问题,激发理论探索,这些探索不见得一定会为问题提供解决方案,但会打开全新的视野,无用是暂时的,因为这些新视野蕴含着实用和理论价值。
随着“无用”或理论知识迅速积累,用科学精神击败实际问题的可能性也在变大。加入这场角都的不只有发明家,还有所谓的“纯”科学家。我之前提到的马可尼是位发明家,虽为人类文明贡献巨大,也只是站在巨人的肩膀之上(pick other men’s brains)。爱迪生(Edison)也一样。巴斯德(Pasteur)却不同,他是一位伟大的科学家,并不排斥解决实际问题——像是法国葡萄藤的生长情况、啤酒酿造遇到的问题,巴斯德不仅为这些近在眼前的问题出谋划策,还从中提炼影响深远的理论,这些理论当时看似没什么用,但极有可能以一种难料的形式让我们受益。欧立希的思索原本全凭好奇心驱使,却急转直下研究梅毒,不找出攻克的办法不罢休,并最终发明撒而佛散(salvarsan)。班廷(Banting)发明了用于糖尿病治疗的胰岛素(insulin),迈诺特(Minot)和惠普尔(Whipple)发明了用于治疗恶性贫血的动物肝浸膏(liver extract),它们都属于同一范畴:发明者均为真正的科学人,他们深切的知道,大量“无用”的知识是由不在乎它们是否有用的人积累起来的,到了一定时候,这些知识“熟”了,即可借助科学的方法将它们用于解决实际问题。

现在我们已经清楚,须万分谨慎的将一项科学发明或发现完全归功于某一个人。几乎所有的发明或发现都历经漫长的风雨飘摇的研究过程。甲找到这个,已找到那个,丙继续往前走……直至某个天才式的人物将前人的成果拼在一起,成就就此定型。科学正如密西西比河,源自远方沙漠里一条小渠,渐渐流淌成大川。这条奔腾咆哮、冲破堤坝的大河正是由无数条小渠汇聚而成。
这个论点我难以穷尽讨论,且允许我这样去总结:近一两百年间,专业学院在各自领域内做出的成就可能不在于培养出多少工程师、律师或医生,而在于进行了大量看似无用的科学活动,尽管这些活动本身的初衷是追求”用处”。从这些无用的科学活动中,我们获得了许多发现,它们对人类思想、人类精神意义之重大,远远胜过这些学院建立之初力图创造的实用价值。
上述文字强调了——倘若需要强调——精神和学术自由的重大意义。我提到了实验科学,我提到了数学,对于音乐、美术和各种不受束缚的人类精神的表达形式,我的观点也同样适用。只要人类灵魂因这些人类精神的表达形式得到净化、提升、并获得满足,它们的存在就有意义。它们的存在无需任何明确或暗含的“用处”的肯定,“用处”是我们评判某个学院、大学或研究机构的存在价值时用到的标准。
只要一所大学解放了一代代人的灵魂,它就足以获得肯定,无论从这里走出的毕业生是否为人类文明做出过所谓“有用”的贡献。一首诗、一部交响乐、一幅画、一条数学公理、一个崭新的科学事实,这些成就本身就是大学、学院、研究机构存在的意义。

我现在探讨的话题是近日争论的焦点。有些大国——尤其是德国和意大利——正忙着压制人类精神之自由。大学被视为信奉某种政治、经济、种族教义的人手中的工具。在某个民主国度,不时蹦出个脑残儿质疑神圣的学术自由的重要性。人类真正的敌人并非勇敢、有担当的思想家,不管他想的是对是错。真正的敌人是那些试图为人类精神套上模具,让它有翅难展。在意大利、德国、英国、美国,人类精神都曾振翅飞翔。
精神自由不是一个新话题。德国遭遇拿破仑征服时,冯•洪堡(von Humboldt)在它的鼓舞下,构想并建立了柏林大学。吉尔曼(Gilman)在它的鼓舞下创立了约翰霍普金斯大学(Johns Hopkins University),随后美国各个院校都依据该校进行了不同程度的自身改良。对于每一个珍视自己不朽灵魂的人来说,不管精神自由给他带来过什么,都是一条真理。然而,无论是在自然科学还是人文科学领域,对精神自由的论证都比找到它的源头难的多,因为它暗含着一种宽容,一种对人类多样性的宽容。在人类历史上,还有什么比建立在种族或宗教之上的喜恶更愚蠢、更荒谬的呢?人性需要交响乐、绘画和科学真理吗?人类需要基督教交响乐、基督教绘画、基督教科学还是犹太教交响乐、犹太教绘画、犹太教科学?还是伊斯兰教的、埃及的、日本的、中国的、美国的、德国的、俄国的、共产主义的、保守主义的对于人类灵魂无限深度的研究成果和表达?

四.

普林斯顿高等研究院(the Institute for Advanced Study)由路易斯•班伯格(Louis bamberge)和凯若琳•班伯格•富尔德(Caroline Bamberger Fuld)兄妹二人于1930年在新泽西普林斯顿建立。选址普林斯顿一方面是因为创始人对新泽西州的热爱,但据我所知,还因为普林斯顿拥有一个小型研究生院,水准甚高,能够承担最高保密要求的科研合作。高等研究院欠普林斯顿大学的情,永世难还。1933 年,高等研究院各岗位人员基本就位,开始运行。研究院成员都是名声显赫的美国学者——数学家中有 Veblen、Alexander 和 Morse; 人文研究学者有中 Meritt、Lowe 和 Goldman 小姐;公法学家和经济学家中有 Stewart、Riefler、Warren、Earle 和 Mitrany。此外许多已在普林斯顿大学、普林斯顿图书馆和实验室供职的学者和科学家,也为高等研究院效力。除此之外,希特勒为该院“送”来不少科学家,如数学方面的Einstein、Weyl、von Neumann,人文学科方面的 Herzfeld、Panofsky,以及在过去六年间被这些学科巨头形成的强大气场吸引来的一批年轻人,得益于他们,美国学术研究水平日渐强大。

从组织角度看,普林斯顿高等研究院的组织结构极简单,也极不正规。该院下设数学研究所、人文科学研究所、和经济政治研究所。各所均配备一批固定的教授,其他成员一年调整一次。各所自行其是,所内研究人员各行其是。该院容纳了来自二十二的国家、三十九个高等研究院的科学人员,分属不同研究小组,他们享有与教授同等的自由度,既可与这位或那位教授合作,亦可做独立研究,在必要的时候咨询相关同事。这里没有例行公事,教授、研究员、访客之间不划定界线。普林斯顿大学的学生、教授与高等研究院的研究院、教授相互融合,不分彼此。学术氛围熏陶着每一个人。(Learning as such is cultivated.)没有教师会议,也没有委员会。这里的每一个人享受着益于思考和讨论的环境。数学家专攻数学,人文科学家专攻人文科学,经济学家专攻经济学,政治学学生专攻政治学。行政工作的规模被最小化,不予重视。脑中无物的人,无法专注思考的人,在高等研究院是撑不下去的。

我且举几个例子。一次,一位哈佛教授在得到一份来普林斯顿的津贴后,写信问我:“我来这的任务是什么?”我回信:“普林斯顿没有任务,只有机会。”

另一次,一个年轻有为的数学家在普林斯顿待了一年后,前来与我道别。临走前,他说:“我猜你想知道这一年对我意味着什么。”
我答曰是。
他说:“数学正经历迅猛发展,现阶段的文献资料太丰富了。我这个博士学位已经拿了十年之久,虽有过紧跟学科发展的时期,但现在觉得越来越吃力。在普林斯顿这一年,我觉得,窗帘拉开了,屋子亮堂了,窗子打开了。我正构思两篇论文,不日即将发表。”
“这种状态能维持多久?”我问他。
“五年,也可能十年。”
“然后呢?”
“重返普林斯顿。”

第三个例子才发生不久。西方一所大型大学的教授,去年底来到普林斯顿,原打算与普林斯顿大学的 Morey 教授合作,重启一些工作。Morey 教授提议他不妨去拜会一下高等研究所的 Panofsky 和 Swarzenski 二人。就因为这个提议,现在这位教授与三人均有合作。
他说:“我要在这待到明年十月。”
“这儿夏天很热的。”我说。
“忙并快乐着,哪还顾得上热。”

你看,自由带来的不是死寂,是过劳的危险。最近,有个英国研究员的妻子向我咨询:“在这里大家是不是都工作到凌晨两点?”

高等研究院连楼都没有。数学家做客普林斯顿大学的Fine Hall。人文科学家要么做客普林斯顿大学的 McCormick Hall,要么散落于小镇各处。经济学家们占了普林斯顿酒店的一个套房。我呢,驻扎在拿骚街的一幢写字楼里,与商店老板、牙医、律师、脊椎按摩师为邻,楼里还有一批普林斯顿的学者,正在做当地政府的一份调查和人口研究。正如吉尔曼教授六十年前在巴尔的摩说的那样,有没有楼不重要。只是我们怀念同事之间的亲切来往,所以由创立者捐资,一幢名为 Fuld Hall 的大楼即将拔地而起。但这栋楼就是形式感的全部。高等研究院还会维持现有规模,坚持全体研究人员信奉的轻松、安全、自由的氛围,远离组织与公事。我们与普林斯顿各学院的非正式接触也将继续,我们还将不断从各地约请人员来普林斯顿。我们已有来自哥本哈根的Niels Bohr、来自柏林的 von Laue,、来自罗马的 Levi Civita、来自斯特拉斯堡的 Andre Weil、来自剑桥的 Dirac 和 G.H.Hardy、来自苏黎世的 Pauli、来自卢万的 Lemaitre、来自牛津的 Wade-Gery、以及来自哈佛大学、耶鲁大学、哥伦比亚大学大学、康奈尔大学、约翰霍普斯金大学、芝加哥大学、加利福尼亚大学等其他学术机构的各位美国同仁。

不轻言允诺。我们珍视一个希望:不懈的追求“无用”知识,“用处”就会出现。过去如此,将来亦如此。但我们从不据此维护高等研究院。高等研究院是学者的天堂。和诗人、音乐一样,学者们也应该顺应自己的想法,才能竭尽所能,成就辉煌。

std::move操作导致的一个神秘崩溃

原文:The mystery of the crash that seems to be on a std::move operation – The Old New Thing (microsoft.com) January 20th, 2022

客户遇到了只在ARM上出现的程序崩溃。下面是一个简化的版本

-
void polarity_test(std::shared_ptr<Test> test)
{
    test->harness->callAndReport([test2 = std::move(test)]() mutable
    {
        test2->reverse_polarity();
        ::resume_on_main_thread([test3 = std::move(test2)]()
        {
            test3->reverse_polarity();
        });
    });
}
-

他们说,只在第一行就崩溃了:

test->harness->callAndReport([test2 = std::move(test)]() mutable

现在,std::move实际上并不生成任何代码。它只是把引用从左值改为右值,这是一个完全在计算机大脑中(编译阶段)进行的操作。它不需要生成代码。

问题在别的地方。

由于该问题只发生在一个CPU架构(ARM)上,因此后端代码生成器(编译器)可能存在bug。但是为了安全起见,他们联系了编译器前端团队、后端团队(用于代码生成)和库团队(用于shared_ptr)。

我介入并指出,有一个求值顺序(order-of-evaluation)的依赖关系。

test->harness->callAndReport([test2 = std::move(test)]() mutable

语句的左边从test中读取。lambda捕获修改了test(通过std::move将其移动到捕获的变量test2)。

历史上,大多数子表达式的求值顺序是不确定的,虽然有一些操作定义了一个顺序,最明显的是短路表达式(short-circuiting)求值在第二个操作数之前计算第一个操作数(如果有的话)¹。

传统的表达式排序规则不要求在计算参数之前必须决定调用哪个函数。

传统的依赖关系图是这样的²:

test 
 
operator-> 
 
harness 
 
operator->test2 = std::move(test)
callAndReportlambda constructed
function call

由于在左边读取test和在右边修改test之间没有依赖关系,操作可以以任意一种顺序发生。

然后c++ 17出现了。

c++ 17增加了在传统规则之外的额外的求值顺序规则:在下面的表达式中,a在b之前求值:

OperationDescription
a(b)Function call
a[b]Subscript operator
a.*b
a->*b
Pointer to member
a << b
a >> b
Shifting
b = a
b op= a
Assignment
(note: right to left)

就我个人而言,我发现“标准”选择在参数之前对函数求值是很有趣的。在实践中,如果函数是通过指针追踪来识别的,那么首先计算参数会更方便,因为这样做不会干扰很多寄存器。

无论如何,由于函数调用现在在参数之前求值,从c++ 17开始的求值顺序现在要求在lambda中test2 = std::move(test)之前求值左边的test。

因此,问题归结为客户正在使用的语言版本。
客户回来后说,他们正在使用Visual Studio 2019,但使用的是c++ 14模式。
这就解释了。


下次,我们将看看潜在的修复(除了“升级到c++ 17”)。

¹编译器以任何顺序求值的自由情况导致底层体系结构会影响操作顺序。基于堆栈的参数更有可能在基于寄存器参数之前计算:一旦计算了基于寄存器参数的值,就必须在计算其他参数时找到保存它的位置。你可以尝试将它保存在用来传递参数的寄存器中(好),或者你可以尝试将它暂时保存在另一个寄存器中(好),或者你可以spill它并在调用之前重新加载它(坏)。如果其他参数计算起来很复杂,您可能会被迫spill。另一方面,基于堆栈的参数无论如何都会spill到堆栈中,所以您可以计算它并spill它,这样就完成了。在调用之前,您不必复刻(burn)一个寄存器来保存参数。

这意味着即使您只考虑调用约定,最优的求值顺序也可能在x86-32(没有寄存器参数,除了这个)、x86-64/arm(4个寄存器参数)和arm64(8个寄存器参数)之间变化。

²尽管在传统的排序中,我在前面的操作符->之后显示了harness,这并不是语言的规则,是精神内联的产物。真正发生的是

 is

test 
 
operator->&Test::harness
operator->*
(produces harness)

但是 &Test::harness不依赖任何东西。