久别重逢的乡音:中日韩汉字音

2023-12-01 孙耀珠 杂谈

最近学习了上海外国语大学朱磊老师的《中国传统音韵学》,拿到了成绩优秀的认证证书,课程内容让我受益匪浅。传统上韵书是为文人写诗押韵作参考用的,不过我更感兴趣的是韵书所揭示的中古汉语读音哺育了不少域外方音,比如日语和韩语的汉字音。「久别重逢的乡音」便是摘自课程最后一讲的标题,而我想反过来从普通话与日韩汉字音的对应关系出发,印证一下中古汉语的本源地位,顺便介绍一下从中古汉语切韵音到现代汉语普通话发生了哪些重大变化。这既是我的学习笔记,也算是之前《跨越国境的汉字》的续篇了。

Read More

跟住疫情去游学

2023-01-25 孙耀珠 游记

2019 年我初到香港,当时反送中运动愈演愈烈,尤其是亲历了十一之后港铁瘫痪、双十一前后港大校园被占领,我以为那已经是最糟糕的时代了。没想到 2020 年结束元旦假期从冲绳回香港,便听见机场广播呼吁旅客警惕武汉出现的不明肺炎,从此新冠疫情大幕拉起,我再也没有机会出过国。香港一直被定位为「亚洲国际都会」,但在这与世隔绝的两年多里,这个名号怕是要拱手让人了。不过随着两岸三地先后放弃清零政策,现在终于有了与全世界重新连接的感觉,我去年也有幸踏着疫情的尾巴去美国和新西兰开了会,在这里浅浅纪念一下我的学术首航暨首次跨洲旅行。

Read More

多态的多态

2021-12-31 孙耀珠 编程语言

尤记得本科的面向对象编程课有一道经典例题:C++ 的多态性体现在何处?标准答案着眼于 C++ 的虚函数解释了动态派发的机制。自那以后的很长一段时间里,我对多态的认识就固化在了子类型多态上;直到博士期间开始搞编程语言的研究,才发现学术界对多态的定义远不局限于此。

英语里有个单词叫做 autological,是说一个词可以形容其本身,比方说「名词」本身就是个名词,「阳平」这两个字的声调本身就是阳平,而「多态」本身也很多态。编程语言中最常见的多态有四种:特设多态参数多态子类型多态行多态。通俗来讲,只要是为不同类型的数据或操作提供了相同的名字就可以叫多态。

本文只是一篇科普性质的文章,所以基本上只以实际编程语言为例,不会用任何形式化的语言来描述这些类型系统。如果希望深入学习相关的理论知识,建议阅读 TAPL 或者 PFPL;Giuseppe Castagna 在韩国 SIGPL Summer School 2019 的特邀讲座也很值得一看。

Read More

HTML 模板语言纵览

2020-08-09 孙耀珠 领域专用语言

前端开发的本质,是把结构化的数据映射到 HTML。HTML 本身是静态的,因此模板引擎应运而生,接下了动态生成 HTML 的任务,直到近年来在前后端分离的浪潮下被面面俱到的前端框架所兼并。本文试图梳理出模板语言的主流范式,不过注意本文并非按照时间线编排,如果要还原历史的话,应该是 PHP (1995) → Zope 2 (1998) → JSTL (2002) → Django (2005) → Haml (2006) → Mustache (2009) → AngularJS (2010)。

Read More

Linux 内核性能演变

2020-04-10 孙耀珠 文献阅读

本文是我在《系统设计与实现》课程的热点话题阅读报告,内容来源于 Xiang (Jenny) Ren, et al. 发表在 SOSP 2019 的论文《An Analysis of Performance Evolution of Linux’s Core Operations》(下文简称 [Ren19])。

1991年9月17日,赫尔辛基大学的大四学生 Linus Torvalds 向 ftp.funet.fi 上传了自己课余时间编写的 Linux 0.01 源代码,由此揭开了开源操作系统的崭新篇章。如今,Linux 已成为最主流的服务器操作系统,TOP500 榜单中的超级计算机更是悉数采用。在高性能计算对 Linux 依赖越来越强的大背景下,[Ren19] 对近年来 Linux 内核的核心操作性能进行了系统性的评估,得到一个骇人听闻的结论:绝大多数内核操作的性能均有退化。不过值得庆幸的是,研究团队发现可以通过编译配置或是简单的补丁来禁用掉那些导致性能退化的内核改动。

Read More

跨越国境的汉字

2020-03-29 孙耀珠 杂谈

我身边的同学们大都只懂汉语和英语,聊天时偶尔会发现他们对日本、韩国、朝鲜和越南的汉字使用知之甚少。比如有人见到汉字就觉得是汉语,但实际上日韩朝越都在以自己的方式使用着汉字,比如很难说「大変面白」「本当上手」也算是规范汉语,虽然这些字我们都认识。

另一个常见的误解是:为什么 Matsumoto Yukihiro 被翻译成了松本行弘?为什么 Jang Won-young 被翻译成了张员瑛?首先要意识到英语不是日韩的母语,因此上面的罗马字也只是音译。实际上 Matz 的姓名本来就是汉字「松本行弘」,只是这四个字都用了日语训读,导致中日读音大相径庭。而韩国的情况更麻烦一点,因为他们现在几乎不用汉字了,所以姓名里的谚文对应哪个汉字要么靠猜要么询问本人。张员瑛的原名是「장원영」,一开始大家猜测其对应的汉字是「張元英」,不过很遗憾猜错了,后来官方宣布她的姓名汉字是「張員瑛」。当然日本人名也有要猜的时候,比如说「松山ケンイチ」「石原さとみ」(也都猜错过,哈哈哈哈)。不过如今对汉字如此执着的也只有中国了,日韩互译对方人名的时候并不会追溯到汉字,而是直接按照当地的读音来音译(即现地音):松本行弘在韩语里就叫 마츠모토 유키히로,张员瑛在日语里就叫 チャン・ウォニョン。

Read More

日系偶像综述

2019-02-24 孙耀珠 杂谈

刚刚过去的 2018 年,被一些媒体称为「中国偶像元年」,这一年里爱奇艺的《偶像练习生》和腾讯的《创造101》将偶像和粉丝经济的概念一下子推向了主流文化。很遗憾没有去萧山现场看《创造101》的录制,不过我去钱江世纪公园看了首届天猫亚洲偶像嘉年华(AIF2018),明显感觉在两大偶像综艺繁荣的背后,中国国内所谓的养成系偶像还不成气候。一般来说持续数日或者多舞台同时演出才称得上是音乐节,单日单舞台的 AIF 也就是地下偶像拼盘的水平吧,演出阵容和规模远不如日本的 TIF。不过在 AIF 上见证了 AKB48 Team SH 的首次公开亮相,我还是非常兴奋的,毕竟也算是跻身上海队的古参饭了。

对「偶像」这个词的理解,一千个读者眼中就有一千个哈姆雷特。在日本虽然也有汉语词「偶像」,但只有崇拜对象之意;我们现在讨论的偶像则为「IDOL」的音译词「アイドル」。虽然「IDOL」仍然是偶像的意思,但经过音译的转换已经退化为了表音符号;因此在当代日语的语境中,「アイドル」并不会自然而然地跟崇拜对象之意关联起来,而是被赋予了新的含义:与粉丝分享成长过程、以其存在本身为魅力的人物(参见维基百科)。请允许我将这个语义下的偶像称为日系偶像,本文便是个人对日系偶像领域的国内外研究现状综述,其中也结合了我在东京一年的见学体验以及赴北上广参加偶像活动的经历。

Read More

幽灵・熔毁・预兆

2019-01-31 孙耀珠 文献综述

去年肆虐了一年的幽灵系列漏洞似乎已经风平浪静了,但实际上它们对 CPU 微架构和系统软件领域依然有着长久而深远的影响。幽灵系列漏洞针对的并不是某个具体的硬件缺陷,而是将矛头对准了分支预测和乱序执行这两个现代 CPU 普遍采用的优化策略,并通过缓存旁路攻击完成对机密数据的任意读取,通用性极强,也极难做到全面的防御。本文将从幽灵系列漏洞的原理入手,介绍它们对现代计算机系统产生的影响和目前可行的对策。

Read More

关于 REST 的思考

2018-07-11 孙耀珠 文献综述

这篇文章是我在《B/S 体系软件设计》课程的中期报告(命题作文)。因为在开发求是潮手机站时有写过与后端 API 通信的部分,在其他项目中也不时要考虑 API 设计的问题,所以在这方面也有一些自己粗浅的体悟。

表现层状态转化(REST)是一种网络应用程序的架构风格,通常体现在客户端与服务端的通信方式上。不过 REST 与简单对象访问协议(SOAP)等不同,它并不是一种规范化的协议,而是直接基于 HTTP 实现的一种接口风格。它相比 SOAP 等协议而言更加简单自然,因此在网站接口设计上得到了广泛应用。REST 这个名字起得有点令人费解,这是 Roy Fielding 在其博士论文1中创造的名词,不过其思想也可以被解释为「HTTP 对象模型」,并且这些思想早已被用在 HTTP 和 URI 标准的设计上。因此,我们可以先从 HTTP 和 URI 谈起。

  1. Roy Fielding. Architectural Styles and the Design of Network-based Software Architectures. PhD dissertation, University of California, Irvine, 2000. Chapter 5: Representational State Transfer (REST) 

Read More

东京一年

2018-03-04 孙耀珠 游记

東京工業大学

说起来,第一次来日本还是四年前的高中毕业旅行,当时沿着东海道线一路游览了近畿、箱根和东京。如今作为留学生重踏东京的土地,身份从风尘仆仆的游客转变为一千三百万都民中的一员,想到能与真实的东京近距离接触就十分心动。

Read More

使用 fastlane 自动化 iOS 部署

2016-11-30 孙耀珠 运维

对于 iOS 开发者来说,应用发布和代码签名证书大概是最令人头疼的两个环节了,这倒不是因为技术上有多难,而是它们的操作流程相当麻烦,尤其是在中国的网络环境下。

一般来讲,手动发布应用更新大致有以下流程:修改所有 Target 的版本号、用 Xcode 给项目 Archive、在 Xcode Organizer 中上传到 App Store、到 iTunes Connect 更新相关信息、提交给苹果审核。而其中上传那一步在不翻墙的情况下成功率极低,经常会卡在「Authenticating with the iTunes Store…」,而且系统 SOCKS 代理(如 Shadowsocks)在此时似乎并不起作用,只有使用 Proxifier 或者 VPN 才有效果。也是基于这个原因,我一般不会直接在 Organizer 中直接上传,而是先导出为 .ipa 文件,再使用 Xcode 附带的 Application Loader 上传,这样就免去了上传失败的话每次直接上传时将 .xcarchive 转为 .ipa 的时间。

当然以上还没考虑第一次发布时配置证书的流程,一个初学者面对苹果开发者中心琳琅满目的 Certificates / Identifiers / Provisioning Profiles 多半是一脸懵逼,不过幸运的是从 Xcode 8 开始已经能够比较完美地自动管理代码签名了,不再像以前一样需要自己去 Fix issues。

对于 iOS 应用的部署,如果你也像我一样饱受折磨,fastlane 也许是你的救星。

Read More

Deploy Rails with PostgreSQL Using Passenger and Nginx on CentOS

2016-02-10 孙耀珠 运维

最近读完了 Michael Hartl 的《Ruby on Rails Tutorial》,于是想试着在自己的 Digital Ocean (CentOS 7) 上部署一下最终完成的 sample app。最简单的方法当然是:

$ rails server -e production -b 0.0.0.0 -p 80

但 Rails 内建的 WEBrick + SQLite 性能较差,而且这样部署也不够灵活,还是上 Apache / Nginx 比较主流。与 Apache 相比 Nginx 的异步模型能更好地处理高并发的场景,Passenger 性能不错并且可以直接集成于 Apache / Nginx 而不必反向代理,而 PostgreSQL 比 MySQL / MariaDB 功能更强大,这三者是 Ruby 服务器的最佳实践之一,因此我决定折腾一下 Nginx + Passenger + PostgreSQL。

Read More

Ruby: collect, detect, inject, reject, select

2016-01-04 孙耀珠 编程语言

在比较 Ruby 和 Python 的时候,很多人会说 Python 是一门简约的语言,而 Ruby 是一门魔幻的语言。之所以说 Ruby 魔幻,一方面是因为神奇的元编程和甜甜的语法糖,另一方面是在 Ruby 中总有不止一种方法去做一件事(There’s more than one way to do it),循环便是其中一例。

如果写过主流的结构化编程语言,那么一定对 for 循环非常熟悉吧。Pascal 继承了 ALGOL 风格的 for 循环,由初值、终值以及可选的步长组成;C 语言则创造了现在广为人知的三段式 for 循环,被 Java / JavaScript / PHP 等主流语言所沿用;而 Python / Swift 等语言使用 for-in 语句结合 range 也能实现相同的功能:

for i := 0 to n-1 do ……         ⍝ Pascal
for (int i = 0; i < n; ++i) ……  ⍝ C
for i in range(0, n): ……        ⍝ Python
for i in 0..<n { …… }           ⍝ Swift

而在 Ruby 的世界中,有一些有趣的方法可以取代 for 循环:

n.times { |i| …… }
0.upto(n-1) { |i| …… }
(0...n).each { |i| …… }

不过 Ruby 并没有激进地删掉 for 关键字,实现了 each 方法的对象都能以 for-in 语句进行迭代。像上述 times / upto / each 这样的方法在 Ruby 中被称为迭代器(iterator),其实现方式与后来 Python / JavaScript 等语言中的生成器(generator)相似,但使用方式更接近于函数式编程中广泛采用的高阶函数(higher-order function)。

Read More

使用 Qt 多线程避免事件循环阻塞

2015-11-17 孙耀珠 调库

这学期选了一门物理实验的小课题「宇宙射线μ子探测」,于是需要给实验用到的程序写个 GUI。因为目标平台是 Windows,何宇就直接去写 WPF 了;而我本身不是 Windows 用户,当然倾向于寻找一个跨平台的解决方案,目前主流的 GUI 框架中 Qt 大概是最优雅的选择(知乎上也有对此的讨论)。

除了原生的 C++,Qt 也支持其他许多语言的绑定,譬如 PyQt、QtRuby 等等;Qt 近年新推的 Qt Quick 也改用了可以内嵌 JS 的新语言 QML。不过因为我恰好在上 C++ 的面向对象程序设计课,正想借此机会实践一下,所以我还是选择了原生的 C++。

因为实验模拟是个计算密集型的任务,整个计算函数要跑很长时间,如果直接调用它,必然会阻塞事件循环。这样一来,GUI 所有的绘制和交互都被阻塞在事件队列中,整个程序就失去响应了。

Read More

魔都纪行

2015-08-05 孙耀珠 游记

大一这年来,屈指一算我总共去了三次上海:第一次是去看 CCG;第二次游历了五角场,然而重点是去嘉兴路看了 SNH48 剧场公演;最近的一次是去看 ChinaJoy。虽然说不上有多熟悉上海,但渐渐对上海有了一种莫名的亲切感,大概今后依然会经常造访魔都吧。

CCG

去年暑假是我和初中同学第二次一起去看 CCG,原计划五天的行程因为随后的日本之行压缩成了两天,交通路线、食宿都是轻车熟路,没有什么波折。我原以为浦东新区是个高度现代化、处处高楼鳞次栉比的地方,正如我原以为上海站会干净整洁、富丽堂皇,然而真正来了才发现,这里的大街小巷跟我的家乡并没有太大差别:从地铁站到宾馆的路上,依旧是熟悉的小餐馆、小超市、以及路边叫卖的摊贩,只有远远眺望那红色的中国馆才提醒着我这里几年前可是举世瞩目的世博园区。

Read More

《C 陷阱与缺陷》笔记

2015-06-07 孙耀珠 编程语言

词法陷阱(Lexical pitfalls)

  • 由 ALGOL 派生的编程语言如 Pascal 和 Ada,使用 := 作为赋值运算符,而 = 作为比较运算符。C 语言则使用了另一种表示法,以 = 为赋值运算符,以 == 为比较运算符。
  • 在 C 语言中,&| 是按位运算符,而 &&|| 是逻辑运算符。另外,^ 表示按位异或,而不是乘方。
  • C 编译器在词法分析时遵从贪心法,比如 y = x/*p/* 会被理解为注释的开始,而不是 y = x / *p
  • 0 开头的整型字面量将被视为八进制,因此切忌用 0 来占位对齐。
  • 单引号引起的一个字符实际上代表一个整数,而用双引号引起的字符串代表一个无名的字符数组。如果误用单引号引起一个字符串,使用 Clang 等编译器会得到最后一个字符的整数值,而其他编译器也可能得到第一个字符的整数值。
Read More

Swift 学习笔记(三)

2015-05-05 孙耀珠 编程语言

Objective-C API

为了让 Swift 继承 Objective-C 的成熟生态,苹果开发了 Clang Importer 将 Objective-C API 引入 Swift,并自动进行了若干命名转换。而 Swift 3 更是对命名原则做了大规模的调整,使之更清晰、更适应于 Swift,详见 SE-0005SE-0006 两份提案,并且最终形成了一份 API Design Guidelines

初始化

  • 使用 Swift 调用 Objective-C 类的构造器时,方法名中的 initinitWith 前缀会被截去,其余各部分依次变为构造器的参数名。alloc 方法不必再手动调用,Swift 会自己处理内存分配。
  • 简洁起见,Objective-C 类的工厂方法也被映射成了 Swift 的便利构造器。
  • 在 Objective-C 中可能返回 nil 的构造器,在 Swift 中会被映射为可失败构造器。
// Objective-C
UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
UIColor *color = [UIColor colorWithRed:0.5 green:0.0 blue:0.5 alpha:1.0];
// Swift
let myTableView = UITableView(frame: .zero, style: .grouped)
let color = UIColor(red: 0.5, green: 0.0, blue: 0.5, alpha: 1.0)
Read More

Swift 学习笔记(二)

2015-05-02 孙耀珠 编程语言

结构体和类

  • 结构体(Structure)和类(Class)有以下共同特性:属性(property)、方法(method)、下标(subscript)、构造器(initializer)、扩展(extension)、协议(protocol);另外类还有以下独有特性:继承(inheritance)、类型转换(type casting)、析构器(deinitializer)、自动引用计数(ARC)。
  • 结构体是值类型,当其进行赋值操作或参数传递时会发生值拷贝,当然编译器也会在此基础上做 copy-on-write 优化;而类是引用类型,相当于通过指针间接访问,因此不会发生值拷贝,但同时 let 关键字和参数传递时不再能保证其指向的内容不被修改。1
  • 对于类的实例来说,相等(equality)不意味着相同(identity),我们可以通过 === / !== 来判断是不是同一个对象。
  1. 对结构体和值类型的进一步讨论可以参见 ObjC 中国,对于是选用结构体还是类可以参见 官方文档(优先选用结构体)。 

Read More

Swift 学习笔记(一)

2015-04-26 孙耀珠 编程语言

苹果自收购 NeXT 公司开始便使用 Objective-C 作为主力开发语言,至今已有近二十年了;而在这期间,各大科技公司都如火如荼地设计着更为现代的语言,譬如微软推出了 C# 和 F#、谷歌推出了 Go 和 Dart、Mozilla 推出了 Rust……虽然 Objective-C 随着 OS X 和 iOS 的迅速发展而越来越火,但相比之下它的语言设计已经落后于时代了,于是在这个大背景下 Swift 诞生了,开发者正是 LLVM / Clang 之父 Chris Lattner。

Swift 仍然是一门静态类型、面向对象的语言,不过它拥有很多现代的语言特性,譬如类型推断、代数数据类型、模式匹配、泛型等等,同时也有 Playgrounds 这样便利的交互式编程环境。Swift 非常强调安全性,不论是随处可见的可空类型、继承时复杂的构造规则,还是赋值没有返回值、控制流不能省略花括号,都是为了代码安全而考虑。另外 Swift 终于丢掉了 C 语言的包袱,语言层面上移除了指针,switch 语句不再需要 break,整型溢出会抛出运行时错误等等。

就目前来讲,用 Swift 进行 iOS 开发依然离不开 Objective-C 运行时,不过两者能够很方便地交互和共存,从前所有 Objective-C 撰写的 API 均可供 Swift 使用。Swift 的语法目前仍在不断改进,从 Swift Evolution 可见一斑;目前这三篇学习笔记已从初版更新到了 Swift 5.0(2019-03-25),这是第一个 ABI 稳定的版本,也就是说从 Swift 5.0 开始二进制接口将向下兼容。1

Read More

Sublime Text for Mac 使用配置

2014-11-08 孙耀珠 开发环境

Mac OS X 从不缺乏优秀的代码编辑器,从 Vim 和 Emacs 到 Xcode、IntelliJ IDEA、Eclipse,都有着为数甚多的忠实用户。然而大多数的 IDE 是为软件工程而设计的,若只是写写算法题,那么只需要简单的命令行程序,用这些面向工程的 IDE 堪比杀鸡用牛刀了。

Sublime Text 作为一个轻量级的代码编辑器,对于单文件编程非常友好,原生支持不少主流语言的编译运行。它吸收了前辈 TextMate 的优点,并在可扩展性方面更胜一筹。通过各种插件包,我们可以定制包括主题、配色方案、编译选项在内的方方面面。

即便如此,Sublime Text 还是有一些不尽如人意的地方需要进一步配置,以下便是 C / C++、Python、Ruby、HTML 的几处配置技巧。

测试环境:Sublime Text 3 Build 3065 (OS X Yosemite 10.10)

Read More

Hello, World!

2014-11-02 孙耀珠 杂谈

这是博客的第一篇文章,首先当然是说声欢迎来访~

我曾经用国外网络服务器商的免费空间搭建过 WordPress 博客,并绑定了 .tk 的免费域名。不过这些免费空间大多不太靠谱,一旦账号不活跃就很可能被停用;在国内不仅访问速度很慢,还有被墙的风险。于是不久我就放弃了原来的博客。

前几天,我偶然接触到了 Markdown 这个轻量级标记语言,发现其与维基百科所使用的 Wiki Markup 异曲同工(不考虑后者复杂的模板功能)——比 HTML 简单、比 Microsoft Word / Apple Pages 纯粹,但同时也能满足平时富文本编辑的需要。自然而然地,我萌生了用 Markdown 写博客的想法。对于一个程序员来说,网站搭建在自己的服务器上这种可控的感觉当然是最好的,不过像博客这样的静态网站托管在 GitHub Pages 也是不错的选择,还省去了自己去维护的工夫。而静态网站生成工具我选择了 Jekyll,首先是因为自己对于 Ruby 更加熟悉,其次 GitHub Pages 原生支持 Jekyll,因此可以直接托管源码,不用像 Hexo 一样先在本地生成所有静态文件再推送到 GitHub 上。

Read More