EMACS-DOCUMENT

=============>随便,谢谢

emacs-lisp中的f-strings

我非常喜欢Python 3中的f-string。它们允许您将变量名和表达式放在一个字符串模板中,然后展开该模板来创建新的字符串。下面是一个简单的例子:

username = 'John Kitchin'
somevar = 5**0.5
print(f'{username:30s}{somevar:1.2f}')
John Kitchin 2.24

相比之下,emacs-lisp中的字符串格式化就没那么有趣和简单了。初始状态下我们有:

(let ((username "John Kitchin")
      (somevar (sqrt 5)))
  (format "%-30s%1.2f" username somevar))
John Kitchin 2.24

That is still three lines of code, but it is ugly and hard to read like the old python code: 都是三行代码,但它很难看,像旧的python代码一样难以阅读:

print('%-30s%1.2f' % (username, somevar))
John Kitchin 2.24

我的经验表明,字符串越大,这个值就越难看出来,而f-string则更容易阅读。

如果您不想要这些格式化字段,那么神奇的's库为emacs-lisp提供了一些帮助。您可以像这样引用词法环境中的变量。

(let ((username "John Kitchin")
      (somevar (sqrt 5)))
  (s-lex-format "${username}${somevar}"))
John Kitchin2.23606797749979

今天,我决定做点什么,于是写了这个宏。它是 s-lex-format 的变体,引入了一个稍微新一点的语法。你现在可以添加一个可选的格式字段,该字段与变量名之间用空格分隔。

(defmacro f-string (fmt)
  "Like `s-format' but with format fields in it.
FMT is a string to be expanded against the current lexical
environment. It is like what is used in `s-lex-format', but has
an expanded syntax to allow format-strings. For example:
${user-full-name 20s} will be expanded to the current value of
the variable `user-full-name' in a field 20 characters wide.
(let ((f (sqrt 5))) (f-string "${f 1.2f}"))
will render as: 2.24
This function is inspired by the f-strings in Python 3.6, which I
enjoy using a lot.
"
  (let* ((matches (s-match-strings-all"${\(?3:\(?1:[^} ]+\) *\(?2:[^}]*\)\)}" fmt))
         (agetter (loop for (m0 m1 m2 m3) in matches
                        collect `(,m3 . ,(format (format "%%%s" (if (string= m2 "")
                                                                    (if s-lex-value-as-lisp "S" "s")
                                                                  m2))
                                                 (symbol-value (intern m1)))))))

    `(s-format ,fmt 'aget ',agetter)))
f-string

这就是它的用法。

(let ((username "John Kitchin")
      (somevar (sqrt 5)))
  (f-string "${username -30s}${somevar 1.2f}"))
John Kitchin 2.24

它仍然缺乏python中f-string的一些功能,例如,在python中,待展开的模板参数将被求值。上面解决方案相比就显得太简单了,因为它只使用了一个正则表达式,并且仅限于词法环境中的变量值。

print(f'{5**0.5:1.3f}')
2.236

尽管如此,这个简单的解决方案与我大多数时候的做法是一致的,所以我仍然认为它是一个改进!