如何在Emacs中实现基于system-type的提前返回式字体名称生成
在Emacs中实现类Pascal的提前返回式字体选择
需求很明确:参照Pascal的提前返回逻辑,根据Emacs的system-type返回对应字体名称——默认返回Courier,如果是macOS(darwin)则提前返回Menlo,Linux(gnu/linux)则提前返回Monospace。嵌套if-else的写法能正常工作,但尝试的宏写法始终返回Courier,下面来解决这个问题。
参考的Pascal实现
先看你参考的Pascal代码逻辑:
{ ASSUMING system_type is a global VAR } FUNCTION font_name: String BEGIN result :='Courier'; IF system_type = 'darwin' THEN Exit('Menlo'); IF system_type = 'gnu/linux' THEN Exit('Monospace'); END;
失效的宏写法问题分析
你写的宏代码始终返回Courier,问题有两点:
- 没必要用宏:
system-type是运行时确定的值,宏是编译时展开的工具,这里用普通函数才是正确选择。 - 宏的返回逻辑错误:Emacs Lisp宏的body里,只有最后一个表达式会作为宏展开后的返回值。你写的前两个
when表达式只是单独展开执行,但没有控制返回流程,最后直接返回"Courier",所以不管什么系统都只会得到默认值。
失效的宏代码:
(defmacro font-name () (declare (indent defun)) `(when (eq system-type 'darwin) "Menlo") `(when (eq system-type 'gnu/linux) "Monospace") "Courier")
可行的提前返回实现
方法一:用cond实现类提前返回逻辑
cond是Emacs Lisp中最常用的多分支判断结构,它会依次检查条件,匹配到第一个满足的条件后立即返回对应值,剩下的分支不会执行,逻辑上和Pascal的提前返回完全一致:
(defun font-name () (cond ((eq system-type 'darwin) "Menlo") ((eq system-type 'gnu/linux) "Monospace") (t "Courier")))
方法二:用return-from实现显式提前返回
如果你想要完全复刻Pascal里Exit的写法,可以用return-from在函数中直接提前返回,和Pascal的逻辑一一对应:
(defun font-name () (when (eq system-type 'darwin) (return-from font-name "Menlo")) (when (eq system-type 'gnu/linux) (return-from font-name "Monospace")) "Courier")
原可行的嵌套if-else写法
作为对比,你原来的嵌套if-else写法是可行的,但可读性不如上面两种:
(defun i4w-editor-font () (if (eq system-type 'darwin) "Menlo" (if (eq system-type 'gnu/linux) "Monospace" "Courier")))
内容的提问来源于stack exchange,提问作者huckfinn
相关产品推荐
相关产品推荐

