Quotes

Thus, programs must be written for people to read, and only incidentally for machines to execute. — Preface to the First Edition, Structure and Interpretation of Computer Programs
Recursion is the root of computation since it trades description for time. — Alan Perlis, EPIGRAMS IN PROGRAMMING
It goes against the grain of modern education to teach children to program. What fun is there in making plans, acquiring discipline in organizing thoughts, devoting attention to detail and learning to be self-critical? — Alan Perlis, EPIGRAMS IN PROGRAMMING
古者富贵而名摩灭, 不可胜记, 唯倜傥非常之人称焉. —— 报任安书, 司马迁著
我们并非居于国家之中, 而是语言之中. 语言是我们的祖国, 而别无其他. —— 萧沆
活着必须革命/心高气傲/哪里去不到 —— 抗战二十年

一些无聊的人生建议和忠告

  1. 如果你读不懂一本书, 那么很有可能不是因为你太过愚蠢, 而是因为作者太过愚蠢.
  2. 出于我的个人经验, 烂书分为以下几种: 一是把读者当傻子的, 只说废话; 二是从来不组织文字的, 和流水账没有区别; 三是信奉神秘主义的, 就等着读者来解谜.
  3. 不要做无法挽回的事情, 特别是伤害自己的身体这种.
  4. 分析学 (我指的是数学上的分支) 还处于它的原始时期, 现在不是研究分析的好时机.
  5. 科学分为两种, 一种是需要做实验的, 另一种是不需要做实验的. 如果你想要研究前者, 首先应该做好浪费一生的心理准备. 物理学似乎是唯一的例外, 虽然研究物理也需要实验, 但是物理学家把会浪费生命的东西基本上都开除物理籍了.
  6. 当试图完成宏大的计划时, 先从能完成的小事出发. 当试图阅读晦涩难懂的厚书时, 先看能够读懂的地方.
  7. 一本数学书籍, 如果其预备部分的内容对于你而言也并非烂熟于心, 那就不要读了, 反正也读不懂. 当然, 唯一的例外可能是一些数学常识, 这个因人而异. 如果你觉得你读不懂的部分都是常识, 那就继续吧.
  8. 数学证明是为无法理解的读者准备的, 甚至数学定义也是. 如果你已经充分理解了, 那就不要浪费时间阅读证明了.
  9. 物理学家往往会接受数学家觉得不严格的证明, 数学家往往会接受逻辑学家觉得不严格的证明. 似乎我还忘了哲学家, 哲学家成为了一切思想的垃圾桶, 但是本不该如此.
  10. 能够计算是一种非常令人愉悦的性质, 因为这样的话就不需要你计算了.
  11. 可复合性也同样令人愉快, 即便看上去没有, 也应该去寻找它. 两种基本的策略, 一种是限制, 另一种是扩张.
  12. 对于递归的排斥只是大脑未能发育完全的后遗症.

The Ship of Theseus

人工语言?

试图让机器分析和理解自然语言是全然不可能的事情, 这种不可能性深植于自然语言本身. 我们要做的事情, 不该是探究现存的自然语言的规律, 而应该是设计新的自然语言, 它能够克服自然诞生的自然语言的缺陷. 或许这个说法并不够准确, 因为的确已经有许多人工的自然语言了, 最经典的当然是Esperanto. 但是这些语言的问题在于, 它们在各个方面都模仿已有的自然语言. 这阻碍了真正的探索和进步. 比如说, 我不认为语言必须写成字符序列的形式, 或许来源于Lisp的S-expression就是一种很好的替代. (当然, S-expression也得以字符序列的形式写出来, 但是读者应该明白我的意思.) 我们不应该试图一开始就设计庞然巨物, 而应该从一系列小的语言开始. 这些小的语言应该试图呈现各种各样的语言机制. 接下来我们应该试图理解如何将这些小的语言复合起来. 我们必须区分什么样的机制是正交的或者可加的, 而什么样的机制与其他所有机制都耦合在一起. 在此基础之中, 我们必须开始设计丰富的语言, 在这一步的时候, 我们应该充分理解所有的设计决定会造成的影响. 我不认为一种语言可以完成所有目的, 事实上我们应该设计各种各样的丰富的语言. 而这种努力的结果应该是设计语言的成熟方法论, 它应该允许对于语言没有深刻理解的人也能够设计语言达成自己各种各样的目的, 并且这样的语言也应该很容易为他人所掌握. 这是我所认为的语言学接下来的任务.

无题

死亡是唯一重要的事情. 你必须直面死亡, 然后才能考虑接下来该做什么. 最不重要的事情是名誉, 因为名誉依赖于人类. 很容易想见, 在不久的将来, 人类也将不复存在. 所以, 你应该"玩". "玩"才是唯一真正重要的事情. 玩的目的并非向别人展示自己获得了乐趣, 或是乐趣衍生的成果, 而是乐趣本身才是目的. Have fun!

论编程教育

当前的编程教育几乎是一团糟. 大概没有比这更好的形容了. 首先, 但是最不重要的一点是, 每个人都很傲慢, 不论是教授编程的人, 还是学习编程的人. 每个人都似乎以为自己是最聪明的, 并不是认为自己是最聪明的, 而是自己必须是最聪明的. 并且, 每个人似乎都以为自己是最正确的. 这只是表面因素. 然而, 即便是这表面因素, 大概也足够使绝大多数人恼火了. 很多聪明的人就是这样, 在学会编程之前就离开了, 并且决定只在必要的时候编写程序, 而不是掌握如何编写程序.

显然, 最不重要的一点是, 接下来我所说的也只是我个人的主观臆断, 并且不仅是主观臆断, 还充斥着"一般论"和"特殊论"的交织, 听起来就毫无阅读的意义可言. 然而, 我必须要在此辩护一下, 就是是否是主观臆断和是否符合现实和是否值得阅读之间都毫无关系可言. 所以, 你只有读完之后才知道是否浪费了时间.

似乎绝大多数人都不把计算机科学当作科学. 就是那些把计算机科学当作科学的人中, 绝大多数也不把编写程序视为科学. 然而, 就是那些把编写程序视为科学的人中, 绝大多数也只认为编写程序的科学是一种自然的, 实验性质的科学. 这种现实是非常荒谬的.

算法和想法

当前有一种极端不正常的风气, 尤其流行于程序员和计算机科学学生群体, 那就是算法(和数据结构)至高无上论. 我实在无法理解就是了.

首先, 我会想到Alan Perlis的经典名言:

You think you know when you can learn, are more sure when you can write, even more when you can teach, but certain when you can program.
这句话其实反映了计算机科学, 编程语言和算法的先进性, 然而却被相当多的人误解了. 这种先进性在于编程语言迫使人类精确/准确地表达自己的想法, 从而扫除本来隐藏于人类心智中的模糊和gap. 其后果在于使得编程语言可以成为学习和思想交流的媒介. 然而, "算法至上"主义者似乎完全错误地理解了这句话. 实际上, Alan Perlis的名言还可以补充一下, 即这种可以编程的情况要排除只是机械复制粘贴代码.

的确如此, 我甚至不是第一次遇到这种情况. 他们洋洋得意, 但是其实什么也不懂. 举个例子, 比如说Dijkstra算法, 应该绝大多数人都有所耳闻或者编写过相应的程序. 对于本人而言, 其实Dijkstra算法应该被称为Dijkstra实现, 它是对于uniform-cost search这个想法的实现. 可以说, 虽然许多人都写下了对于Dijkstra算法的理解, 但是我发现他们其实并不真的理解. 他们所谓的理解其实就是观察Dijkstra实现的运行情况, 试图从这种运行情况中总结出什么所谓高深莫测的观点或者性质, 或者是, 他们把验证/证明算法的正确性当作理解算法本身. 然而这只是徒劳而已, 因为他们连uniform-cost search这样最简单的想法也没能领会. 实际上, Alan Perlis的名言只是最理想的情况, 不能理解想法却能够机械编写程序才是真切的现实. 这似乎是计算机科学好的一面? 然而, 我觉得不如说这恰恰是其缺陷.

当然, 这不仅限于计算机科学, 毕竟计算机科学也只是人类的一个领域. 比如说数学, 数学系的学生知道自己很多时候可以验证证明的正确性并将它们记下来却不知道为什么这样证明, 或者迷失于作者的思路之海当中. 当然, 他们也知道当他们真正理解作者背后的想法时, 那些看起来复杂的技术性细节就没有那么令人生畏了, 甚至他们可以发现更简单的证明. 对于非数学系但经常使用数学的人而言, 情况又是另外一种. 他们往往满足于句法和符号操作 (其实也就是算法), 但对于其背后的语义和涵义并不感兴趣. 目前的现实是句法和语义之间存在很多gap, 在并不真正理解的情况下, 很容易产生(离谱的)错误却不自知. 不过, 我想现在越来越多的人也对于数学本身产生了兴趣, 这或许要归功于当前的人工智能热潮和数学科普人的努力.

虽然说了这么多, 但读者应该看出了我想强调的观点, 即想法是第一义的, 而算法不过是想法的自然而然的果实. 当前的情况却是颠倒的, 很多人认为算法是至高无上的, 想法却是次要的, 甚至他们把各种各样本来不是算法的东西也称为算法, 其后果就是他们往往完全忽略了算法背后的想法. 比如说编译器构造这样的领域, 我觉得很多人学不会并不是能力问题, 而是因为他们从一开始就错误地理解了这个领域最基本的内容 (而且, 编译原理是一个很烂的具有误导性的别名). 典型地, 有人把词法分析和句法分析当成编译器构造的主要研究对象. 这好比一个厨师认为他最主要的工作是研究怎么制造菜刀和铁锅. 研究制造菜刀和铁锅当然有助于研究怎么做菜, 但是这和做菜本身存在很大的偏差. (可能我也有点敏感了, 但我听到像递归下降算法这样的话时就挺不舒服的, 因为递归下降本身是个自然的想法, 其根源是follow the syntax/grammar/structure这样的理念.) 那么, 编译器构造研究什么呢? 它研究如何弥合两种不同语言的差异, 研究不同的语言之间保持语义的变换. 当然, 它的目的往往在于让程序跑得更快. 此时我想到了Kent Dybvig的PhD论文, 我觉得那算是一种典范 (或许其内容更贴近"编译原理"这样的名字). Kent Dybvig的风格往往就是我想一下我要做什么, 然后我就正确地以切实的方式做了. (这篇论文还不能完全体现他的风格, 因为论文的目的是刻画编译器构造的原理, 而不是实际写一个编译器.)

好像有点离题了, 那就写这么多吧.

一切美好的, 或消失殆尽

久来不事写作, 若有词不达意, 句不成理之处, 还请不要见怪.

无题

猎人, 小丑, 国王

Galgame评论

魔法使之夜

魔法使之夜给我带来的触动, 除了魔术之外, 大概就是将我引向那过去的似乎并不存在的年代. 对于主人公静希草十郎而言, "城市"的规则是令他费解的, 但最终他发现了"山中"和城市的共通之处. 对于我而言, 魔法使之夜里的城市却是值得怀念的. 也就是说, 那是大叙事还未全然消失之时, 生活中仍然存在着某种形式上的确定性.

沙耶之歌

装甲恶鬼村正

近月少女的礼仪

白色相簿2

兰斯系列

Baldr Sky Dive 1+2

黑暗圣经

拔作岛 (住在下体升级岛上的贫乳该如何是好?)

月姬

Fate/Stay Night

G弦上的魔王

意识流

白昼梦的青写真 (白日梦的构想图)

女仆咖啡厅帕露菲

夏娃年代记

一个卡牌游戏的设计 (The Design of a Card Game)

1. 前言

我的大脑之中一直盘旋着设计和实现一个游戏的想法, 但是始终未能完成, 不过我想至少要先迈出第一步, 不论是interactive fiction, visual novel还是card game. 鉴于发现card game最为简单, 所以还是从card game开始.

作为一个炉石玩家, 我觉得炉石算是卡牌游戏的典范. 只是炉石存在一个很严重的缺陷, 就是其规则并不明确, 往往依赖于实现, 并且各种卡牌的行为难以把握. 因此, 我的想法是设计一个炉石like的游戏, 但是专注于规则的确定性和可理解性.

卡牌的行为应该使用DSL一致地刻画, 这种DSL应该既是人类可读的也是机器可以直接执行的. 或许, 卡牌的字面描述应该直接通过程序从DSL生成.

2. 概念

本章描述游戏本身所牵涉的一切概念, 其必然要指定一种受限的本体论 (restricted ontology).

2.1. 卡牌类型 (Card Type)

2.1.1. 随从 (Minion)

一个随从(牌)拥有名称 (name), 费用 (cost), 种族 (minion type), 攻击 (atk), 血量 (hp), 字面描述 (desc), 行为描述 (behavior).

行为描述在某种意义上也被称为特效, 包括战吼 (battle cry), 亡语 (death rattle), 圣盾 (divine shield) 等. 还有一种类型的特效似乎应该值得特别注意, 因为在原本的炉石中并没有相应的词条, 也就是光环 (aura). 在某种意义上, 这可能是因为光环这种实体的理解存在本体论上的一些困难? 因此, 就将光环设计成无类型的异类了.

2.1.2. 法术 (Spell)

一个法术(牌)具有名称 (name), 费用 (cost), 类型 (spell type), 字面描述 (desc), 行为描述 (behavior).

2.2. 英雄 (Hero)

3. 卡牌的领域特定语言的设计 (The Design of a Domain-Specific Language for the Card Game)