GNU Emacs附带的(显然)邮件读写包的数量让我感到不知所措,更不用说第三方了.我甚至不知道从哪里开始,所以让我说一下我正在寻找什么样的功能,希望有人能说服我,一个选择比其他选择更好.
我已经使用Claws Mail一年多了,我对它非常满意.也就是说,我将大部分计算时间花在终端Emacs上,我也希望从中管理我的电子邮件.我需要的一些功能是:
我可能错了,但似乎我的选择是在MH-E,Gnus和Message/Rmail之间.我已经很好地调查了这些中的每一个,并且被所有三个显然无限的可定制性所震撼.我有能力学习任何一个,但我对电子邮件一般都不太了解,我想在深入研究之前确保我有正确的选择.MH-E使用与Claws Mail相同的邮箱格式,但我不知道应该做多少差异.
为什么以下不起作用?
;;;; foo.lisp
(in-package :cl-user)
(eval-when (:compile-toplevel :load-toplevel :execute)
(require :cl-interpol))
(cl-interpol:enable-interpol-syntax)
(defun read-and-eval (s)
(eval (read-from-string s)))
(cl-interpol:disable-interpol-syntax)
Run Code Online (Sandbox Code Playgroud)
然后:
LISP> (load (compile-file "foo.lisp"))
=> T
LISP> (read-and-eval
"(let ((a \"foo\")) (princ #?\"${a}\"))")
=> no dispatch function defined for #\?
Run Code Online (Sandbox Code Playgroud) 问题flet
在于必须内联定义其中绑定的函数.换句话说,没有办法做到这一点:
(new-flet ((a (lambda (f x)
(funcall f (* x 2))))
(b (function-generator)))
(a #'b 10))
Run Code Online (Sandbox Code Playgroud)
我考虑过自己定义这样一个宏,但问题是这flet
似乎是设置本地函数值的唯一方法.symbol-function
始终只获取全局定义,function
不能与之一起使用setf
.如果有的话,任何人都知道如何干净利落地完成这项工作?
Common Lisp Hyperspec声明"宏表单不能扩展为声明;声明表达式必须显示为它们引用的表单的实际子表达式."
我对"扩展到"的含义感到困惑.由于以下原因,以下宏将无法正常工作:
(defmacro optimize-fully ()
`(declare (optimize (speed 3) (safety 0))))
Run Code Online (Sandbox Code Playgroud)
但是,如果宏扩展只包含一个(declare ...)
表达式呢?
(defmacro defun-optimized (name (&rest lambda-list) &rest body)
`(defun ,name ,lambda-list
(declare (optimize (speed 3) (safety 0)))
,@body))
(defun-optimized foobar (a b)
(* a b))
Run Code Online (Sandbox Code Playgroud)
这违反了规范吗?我使用的CL实现,SBCL,并没有抱怨,事实上,上面的宏似乎正如预期的那样工作.是什么赋予了?
emacs lisp是否具有提供唯一对象标识符的功能,例如内存地址?Python有id()
,它返回一个保证在当前现有对象中唯一的整数.那么elisp呢?
我编写了一个特殊的解析器生成器,它创建代码将旧的和鲜为人知的7位字符集转换为unicode.对解析器生成器的调用扩展为defun
包含在a中的一堆s progn
,然后进行编译.我只想将生成的defun
s中的一个 - 顶级的 - 暴露给系统的其余部分; 所有其他内容都是解析器的内部,只能从顶层的动态范围内调用.因此,defun
生成的其他s具有未处理的名称(用其创建gensym
).这个策略适用于SBCL,但我最近使用CLISP进行了第一次测试,我得到的错误如下:
*** - FUNCALL: undefined function #:G16985
Run Code Online (Sandbox Code Playgroud)
似乎CLISP无法处理具有未分隔名称的函数.(有趣的是,系统编译没有问题.)编辑:在大多数情况下,它似乎可以处理具有未分隔名称的函数.请参阅下面的Rörd的答案.
我的问题是:这是CLISP的一个问题,还是Common Lisp的限制,某些实现(例如SBCL)碰巧被克服了?
编辑:
例如,顶级生成函数(被调用)的宏扩展parse
有一个如下表达式:
(PRINC (#:G75735 #:G75731 #:G75733 #:G75734) #:G75732)
Run Code Online (Sandbox Code Playgroud)
评估此表达式(通过调用parse
)会导致类似上面的错误,即使该函数在同一个宏扩展中明确定义:
(DEFUN #:G75735 (#:G75742 #:G75743 #:G75744) (DECLARE (OPTIMIZE (DEBUG 2)))
(DECLARE (LEXER #:G75742) (CONS #:G75743 #:G75744))
(MULTIPLE-VALUE-BIND (#:G75745 #:G75746) (POP-TOKEN #:G75742)
...
Run Code Online (Sandbox Code Playgroud)
#:G75735的两个实例绝对是相同的符号 - 而不是两个具有相同名称的不同符号.正如我所说,这适用于SBCL,但不适用于CLISP.
编辑:
SO用户Joshua Taylor指出这是由于长期存在的CLISP错误.
我不明白为什么Emacs 24的新词法作用域功能如此之好的原因是我想不出任何没有它们就无法实现的新功能.例如,以下闭包:
(setq lexical-binding t)
(defun f1 (num1)
(lambda (num2)
(setq num1 (* num1 num2))))
(fset 'f2 (f1 5))
==> (closure ((num1 . 5) t) (num2) (setq num1 (* num1 num2)))
(f2 5)
==> 25
(f2 2)
==> 50
Run Code Online (Sandbox Code Playgroud)
可以使用常规动态范围实现,如下所示:
(defun f1 (num)
(let ((tmpvar (make-symbol "num")))
(set tmpvar num)
`(lambda (num2)
(set ',tmpvar (* (eval ,tmpvar) num2)))))
(fset 'f2 (f1 5))
==> (lambda (num2) (set (quote num) (+ (eval num) num2)))
(f2 5)
==> 25
(f2 2)
==> 50 …
Run Code Online (Sandbox Code Playgroud)