如何在 SBCL 中创建解释函数?

How do you create an interpreted function in SBCL?

我想创建一个解释函数定义,而不是编译函数定义。

SBCL manual 说:

Variable: *evaluator-mode* [sb-ext] : Toggle between different evaluator implementations. If set to :compile, an implementation of eval that calls the compiler will be used. If set to :interpret, an interpreter will be used.

所以,我尝试创建一个 BAR 函数(它不存在):

(let ((sb-ext::*evaluator-mode* :interpret))
  (defun bar (x) (+ x 1)))

但是,我检查了一下,BAR 已经编译好了:

CL-USER> (compiled-function-p #'bar)
T

那么,如何创建 BAR 的解释版本?

你问题中的 let 形式只在运行时设置了求值模式。至此,函数已经编译完成

您需要在加载时设置它,并确保 load 文件而不是编译然后加载它。

试试这个:

your-file.lisp中:

;; at load time, set evaluator mode to interpret (before bar definition is met)
(eval-when (:load-toplevel :execute)
  (setf sb-ext::*evaluator-mode* :interpret))

;;define your interpreted function
(defun bar (x)
  (+ x 1))

;; set evaluator back to compile mode (optional)
(eval-when (:load-toplevel :execute)
  (setf sb-ext::*evaluator-mode* :compile))

;;check if bar is a compiled function
(print (compiled-function-p #'bar)) ;;prints NIL

然后用(load "your-file.lisp")加载它(这不会先编译文件)。

我认为 *evaluator-mode* 本质上是一个全局变量。例如,如果您这样做:

> (setf sb-ext:*evaluator-mode* ':interpret)
:interpret
> (setf (symbol-function 'bar)
        (lambda (x) x))
#<interpreted-function nil {10026E7E2B}>
> (compiled-function-p #'bar)
nil

你得到一个解释函数。但是如果你这样做:

> (setf sb-ext:*evaluator-mode* ':compile)
:compile
> (setf (symbol-function 'bar)
        (let ((sb-ext:*evaluator-mode* ':interpret))
          (lambda (x) x)))
#<function (lambda (x)) {52C3687B}>
> (compiled-function-p #'bar)
t

你不知道。我对此的看法(可能是错误的)是在每个顶级表单开始时有效的值才是最重要的:一旦系统决定它将对表单使用编译评估器,那么它不能改变主意。

请注意 'top-level form' 有一个复杂的定义,特别是在处理文件时,然后以

的形式
(let (...)
  (x ...))

那么(x ...)不是顶级表格。