数据工程师的“最后一公里”

作为一名数据工程师,我经常处理“大”数据。但有时候也需要处理“小”数据。比如通过大数据计算得到的一些相对“小”的数据结果,还需要进一步的统计分析。如果再用大数据的框架跑一遍计算,非常浪费资源浪费时间。效率最高的方法还是在本地就把这些数据处理了。

这类数据处理场景就像送快递,包裹跨越万水千山终于到了目的地城市。这时候应该选择什么交通工具来把快递送到你的手上呢?长途和短途所选择的交通工具肯定是有差别的。在这种“小数据”的场景下,什么工具才是效率最高的?为了解决数据分析领域的“最后一公里”问题,我尝试了很多种工具,但总觉得不太顺手。因此实现了 ob-pyspark-sql 这个 org-mode 扩展包,解决自己的痛点,提升工作效率。

如何把项目做完?

今年做了几个开源项目,github 上的 org-tidy、alfred-app-switcher,在公司内部开源了一个 rust 实现的命令行工具,另外还有一些正在进行中的项目。做的过程中发现并没有自己想象的那么容易,会遇到很多来自自身的阻力。总结一下这些困难,如何克服它们,把项目做完。

Emacs bury-all

使用 emacs 时,经常会打开一些特殊的 buffer,比如 magit、rg、compilation。这些 buffer 都有自己的 keymap。如果使用了模态编辑插件(modalka、evil 等),很容易在这些 buffer 触发误操作。所以我个人的习惯是这一类 buffer 用完即关。

目前关掉这些 buffer 的方式有些低效,需要多次操作。比如下面图中左侧是普通 buffer,右侧是 rg,当前活跃的是左侧窗口,如果要关闭 rg,需要先跳到右侧,再按下 q

另外当打开了多个 magit buffer 时,需要在每个 magit buffer 里面都按下 q ,才可以关闭所有的 magit buffer。

因此实现了下面这个 bury all 的操作,不管当前在哪个窗口,只要按一个键就可以关掉所有的这一类 buffer。之所以叫 bury all 是因为 emacs 的 buffer 并不是真的退出,而是把这些 buffer 放在 buffer list 的最下层不展示出来而已,的确是 bury。

(defun jxq-bury-window-buffers (window)
  (let ((continue t))
    (while (and continue (window-valid-p window))
      (when-let ((buff (window-buffer window)))
        (if (with-current-buffer buff
              (memq (keymap-local-lookup "q")
                    (list #'magit-mode-bury-buffer
                          #'magit-log-bury-buffer
                          #'quit-window)))
            (progn
              (quit-window nil window))
          (setq continue nil))))))

(defun jxq-bury-all ()
  (interactive)
  (mapcar #'jxq-bury-window-buffers (window-list)))

实现原理很简单,通过 window-list 函数遍历所有 window,看当前展示的 buffer 是否有给 q 键定义 keymap,如果 q 映射到的是诸如 quit-window 这样的函数,那就说明 buffer 是可以 bury 的。

理解Emacs Lisp的 List

Emacs Lisp 的基本数据类型,比如字符串、布尔值、数值等等,跟其他语言的差别不大。但它的 list 类型就相对复杂一些。我自己在初学者阶段发现有些概念特别晦涩难懂,每次在写 elisp 的时候都被困扰。

  • Cons Cell 就是 list 吗?

  • Association List (alist) 和 Property List (plist) 分别是什么,它们有什么区别?

  • 各种 List 之间的关系是怎样的?

经过大量代码实战之后,总算弄明白了这些问题。今天把我的理解分享出来,希望可以帮助到大家。

Emacs 29 升级指南

Emacs 29发布了,比较吸引我的新特性是treesitter、sqlite、svg的原生支持。虽然并没有特别迫切的需求,但还是忍不住想升级一下。以往都是直接下载 emacsformacosx 编译好的版本,这次发现没有native compile特性,非常慢。所以这次干脆自己编译了,还可以灵活选择需要的特性。

build-emacs-for-macos

首先尝试了build-emacs-for-macos这个辅助编译的脚本,它会帮你安装需要的依赖,编译过程还算顺利。但是发现它编译出来的emacs有点诡异。

打开Emacs后,会提示几个包的代码有些问题,这在我的预期之内。升级完Emacs,已经安装过的包最好都升级一下,或者删掉重装。因为老版本的emacs生成的elc文件,新版本不一定能兼容,就会出现各种奇奇怪怪的问题。

把有问题的包升级完,再重启emacs,问题依然存在。这就不符合预期了。索性把所有安装的包全部删掉,再重新安装。这样操作之后,再启动Emacs,看起来好像没问题了。

用了几天之后,诡异的问题又来了。有些包又有新版本,升级完重启后,发现依然使用老版本的,新版本被标记为obsolete。比如上面的doom-modeline,明明 20230819.1826 这个才是新版本,但生效的却是 20230815.230 。这个问题浪费了很多时间,我都开始看package.el代码,怀疑是不是Emacs 29本身带来了什么问题。

Scala命令行参数解析库对比

命令行是我们与程序之间最基础最朴素的交互方式,命令行参数是工具的灵魂,程序的功能有很多,指定不同的参数可以实现不同的功能。我写过无数解析命令行参数的代码,大部分都非常简单,满足基本功能要求即可。最近刚好需要实现一个相对复杂的命令行工具,简单的解析无法满足需求。因此重新考察了几个命令行参数解析库,做一下横向对比。

因为主要开发scala的程序,这里仅讨论适用于JVM的库。包括scopt、mainargs、scallop和picocli。对比下来,picocli完胜

命令行解析的需求

最开始并不清楚自己的需求到底是什么,这些库看起来都挺好,没什么区别。在实际开发的过程中,就逐渐发现这些库的缺点。好的命令行解析库应该满足下面这几点要求:

优化counsel-bookmark

Emacs的书签非常好用,通过它可以非常快速地跳转到对应位置。虽然使用 ivy-switch-buffer 已经可以非常快速地切换文件。但是书签跳转还要更高效一些:

  1. 书签精确到行级别,通过书签可以直接跳到某个文件的某一行。也可以给不同的行设置书签,然后在不同的行之间来回跳转。

  2. 有些文件路径非常深,记不住文件名和路径,不能通过 ivy-switch-buffer 快速的找到。这时候就可以记录一个书签,起个好记忆的名字,或者给书签打上tag。

Emacs原生书签功能相对简单,因此我使用了 BookmarkPlus,它在原生的基础上做了很多扩展,比如支持给书签打tag,支持函数的书签,支持书签的注释等等。

随着日常使用的积累,书签越来越多,书签的搜索成了一个大问题。一直用 counsel-bookmark 来搜索书签,但它只能按书签名称进行搜索:

书签多了之后经常忘记名称,找不到想要的书签,counsel-bookmark的功能就显得有些鸡肋。其实除了书签的名称之外,文件路径、书签tag都是非常重要的信息,如果把这些内容综合起来再搜索,只需要记得其中一项就可以匹配,效率会高很多。

基于org-mode、markdown和alfred的高效书签工作流

我的日常工作离不开浏览器书签,书签和笔记一样,也属于个人知识管理。如果不用书签,工作方式可能是这样的:

  • 前几天同事刚发了一份腾讯文档,需要看的时候要么打开聊天记录找,要么在腾讯文档里面找。要么为了下次不再找,不关掉浏览器的tab,直到打开了几十个tab不得不关。

  • 进入内部系统的某页面,先输入内容搜索,但是搜索非常慢,进入页面要等半天。

  • 同样是搜索的场景,但是搜索的“关键字”需要查一下代码才知道,比如系统内部id。

非常不喜欢这种“前戏”太多的工作方式,为了完成一个工作,需要先做另一件繁琐的操作,效率极其低下。

浏览器书签可以解决这些问题,但是浏览器的书签功能用起来非常不爽。

程序员生存指南:坚信未来的无限可能

自身的变化

近来发现对许多事情都提不起兴趣,心里有点慌,难道是抑郁症的前兆?转念一想,我只是对那些“建设性”的事情不感兴趣而已,吃喝玩乐还是很感兴趣,于是松了一口气。

摄影曾经是最喜欢的事情,不怕苦不怕累,凌晨四点起床去深圳湾拍日出,扛着三脚架去深圳和香港的大街小巷,拍了很多满意的城市风光照片。但近几年摄影频率大幅度降低,一年才会拍一次,三脚架也很久没动了。今年夏天天气很好,非常适合拍照,内心有一点躁动,想要去拍。但是最终还是没有行动,要么因为太困早上起不来,要么是觉得去了也不一定能拍到好的照片。本质的原因还是因为没有动力了。即便拍到好的照片又能怎么样呢,我的生活会发生变化吗?拍了这么多年,我的Instagram粉丝数依然少的可怜。想到这里,就像气球被扎破,一瞬间所有的乐趣都没有了。除了摄影之外,还有很多东西也不再有吸引力。比如对技术不再好奇和狂热,“新兴的语言和工具都是玩具而已”。