Skip to Content

给谢益辉的笑话

从 knitr 开始逐渐了解了谢益辉,后来翻了他的博客,发现这个人很对我的胃口。看见他在一篇博文中写过,想让他快速解决问题可以附个笑话。暑假没事干时瞎鼓捣 bookdown,花了好多时间之后发现结果很有戏剧性,就给他写了一封邮件。后来还来来往往写了几封,就不转移到博客了,太花时间(这一篇是以前已经写好了的,只需要整理一下)。

1 废话

我的英文不是很好,而且你也应该看得懂中文,所以我就直接写中文了,反正主要目的是给你讲个笑话。

我叫董卓尔,是南开大学的一名本科生,或者说是 R语言高级菜鸟(本来我想自封中级用户的,但不久前在 Stack Overflow 遭受了一次打击,就老实地做菜鸟了)。你可以叫我卓尔。

在学习R语言的过程中不可避免地接触到了你(bookdown 真的超棒),并且也在 GitHub 上与你有过多次交流 (我的用户名是dongzhuoer)。

这次给你发邮件是为了给你讲个笑话, 我觉得几乎不会重复,因为这个笑话是昨天刚发生的真人真事。本来事件应该像一般的 bug 一样,开一个 Issue 就好了。但是最后发生了出人意料的转折,以至于我觉得这成了一个值得发给你的笑话。

2 引言

招呼打完了,开始说正事。

起源是我觉得你的《R语言忍者秘笈》写的蛮好,但 bookdown 网站实在太慢,就 clone 了 GtiHub 源代码库到本地来 build。然而

R version 3.4.1 (2017-06-30) -- "Single Candle"
Copyright (C) 2017 The R Foundation for Statistical Computing

...

Type 'q()' to quit R.

Error in yaml::yaml.load(string, ...) : 
  Reader error: invalid trailing UTF-8 octet: #EF at 9

刚打开 R project 就报错,还能不能愉快地玩耍了?

3 开端

不过查错是忍者的基本技能,一番鼓捣之后,发现问题出在这:

yaml::yaml.load_file('_bookdown.yml')
Error in yaml.load(paste(readLines(input, encoding = "UTF-8"), collapse = "\n"),  : 
  Reader error: invalid leading UTF-8 octet: #B5 at 39

废话少说,开始调试:

debug(yaml::yaml.load_file)
yaml::yaml.load_file('_bookdown.yml')
debugging in: yaml::yaml.load_file("_bookdown.yml")
debug: {
    yaml.load(paste(readLines(input, encoding = "UTF-8"), collapse = "\\n"), 
        ...)
}

我觉得是 readLines() 的问题:

Browse[2]> readLines(input, encoding = "UTF-8")
[1] "book_filename: r-ninja"                  "chapter_name: [\"�\xda\", \"\xd5\xc2\"]"
[3] "repo: https://github.com/yihui/r-ninja/" "output_dir: _book"                      
[5] "clean: [packages.bib, r-ninja.bbl]"  

果然不正常,看看 readr::read_lines() 怎么样:

Browse[2]> readr::read_lines(input)
[1] "book_filename: r-ninja"                  "chapter_name: [\"第\", \"章\"]"         
[3] "repo: https://github.com/yihui/r-ninja/" "output_dir: _book"                      
[5] "clean: [packages.bib, r-ninja.bbl]" 

这个好,看来要改 yaml 源代码或者向作者报告了。

4 发展

然而在 viking/r-yaml 写 Issue 时,我又有了新发现:

Browse[2]> readLines(input)
[1] "book_filename: r-ninja"                  "chapter_name: [\"第\", \"章\"]"         
[3] "repo: https://github.com/yihui/r-ninja/" "output_dir: gitbook"                    
[5] "clean: [packages.bib, r-ninja.bbl]" 

这可真是太神奇了,怎么不加 encoding = "UTF-8" 反而好了?

继续写 Issue,把上面的情况也加上去。写着写着,我突然想到另一件与 "UTF-8" 有关的事,之前我在 .Rprofile 加了这句话:

options(encoding = "UTF-8")

也许是这句话惹的祸?果然,去掉之后(encoding 取默认值"native.enc"),就一切正常了。

5 高潮

华丽丽的分割线。

到此为止,都是一个正常的Issue,接下来才是笑话的重点。

由于刚学会 Git,可以从一个新的高度来使用 GitHub(之前连 clone 都不会,只会下载 *.zip),我暂时还处于一种比较新鲜的状态。于是找到 yaml源代码库之后,我没事翻了一下 contributors

哇,有 hadley 大人耶,还有益辉。按你的博客说的,我就不加扩展名(老师 、大牛等)了。

然后,我更加没事地翻了一下你的 commit

结果闪瞎我的狗眼啊!!!

这句话居然是你加的!含有中文的 .yml 文件也是你写的!这是搬起石头砸自己的脚吗?可为什么受到伤害的是我啊!

我觉得更贴切的比喻应该是这样的:你先挖了一个大坑(居然往.yml文件塞中文,定时炸弹啊),为了不让路人掉进去,你很负责地在周围设置了护栏(在 yaml::yaml.load_file 中加入 encoding = "UTF-8")。然而人算不如天算,还是留了一个缺口,最后我就很开心地偏偏对着这个缺口冲过去了(options(encoding = "UTF-8"))。

6 结局

不管怎么说,我还是花了一小时认真写好 Issue,希望能被 Google 收录。这样以后再有人遇到同样的问题时,可以查到很有用的参考资料。

最后,希望你不要觉得这是一个冷笑话吧。

7 尾声

有空麻烦看一下 bookdown 的这个 Issue。虽然我也做过网站,HTML、CSS、Javascript 也都会用,但是我觉得还是开发者解决起来更高效一些。