有没有办法找出原始函数(内置)是如何在 SBCL 中准确定义的?

Is there a way to find out how the primitive functions (built-in) where exactly defined inside SBCL?

我正在使用 Emacs、SBCL 和 Slime 学习 Common Lisp。

我想确切地知道什么是内置函数的代码定义。

我知道如何使用 (documentation ...)(describe ...)。但是,它们仅提供高级信息。我想看看代码细节。

例如,取nth内置函数。

Documentation 给我们:

CL-USER> (documentation 'nth 'function)
"Return the nth object in a list where the car is the zero-th element."

Describe 给我:

CL-USER> (describe 'nth)
COMMON-LISP:NTH
  [symbol]

NTH names a compiled function:
  Lambda-list: (SB-IMPL::N LIST)
  Declared type: (FUNCTION (UNSIGNED-BYTE LIST) (VALUES T &OPTIONAL))
  Derived type: (FUNCTION (T T) (VALUES T &OPTIONAL))
  Documentation:
    Return the nth object in a list where the car is the zero-th element.
  Inline proclamation: MAYBE-INLINE (inline expansion available)
  Known attributes: foldable, flushable, unsafely-flushable
  Source file: SYS:SRC;CODE;LIST.LISP

(SETF NTH) names a compiled function:
  Lambda-list: (SB-KERNEL::NEWVAL SB-IMPL::N LIST)
  Derived type: (FUNCTION (T UNSIGNED-BYTE LIST) (VALUES T &OPTIONAL))
  Inline proclamation: INLINE (inline expansion available)
  Source file: SYS:SRC;CODE;SETF-FUNS.LISP

(SETF NTH) has a complex setf-expansion:
  Lambda-list: (SB-IMPL::N LIST)
  (undocumented)
  Source file: SYS:SRC;CODE;DEFSETFS.LISP
; No value

我想看类似的内容:

(unknown-command 'nth)

这会 return 类似于:

(defun nth (x xs)
  (if (equal x 0)
      (car xs)
      (my-nth (- x 1) (cdr xs))))

Lisp 语言非常棒,并且拥有由出色的程序员构建的巨大生态系统。我希望有一些工具或命令。

谢谢

当此类信息可用时,应该可以通过 function-lambda-expression :

访问
* (FUNCTION-LAMBDA-EXPRESSION #'nth)
(LAMBDA (SB-IMPL::N LIST)
  (DECLARE (SB-INT:EXPLICIT-CHECK)
           (OPTIMIZE SPEED))
  (BLOCK NTH
    (TYPECASE SB-IMPL::N
      ((AND FIXNUM UNSIGNED-BYTE)
       (BLOCK NIL
         (LET ((SB-IMPL::I SB-IMPL::N) (SB-IMPL::RESULT LIST))
           (TAGBODY
            LOOP
             (THE LIST SB-IMPL::RESULT)
             (IF (PLUSP SB-IMPL::I)
                 (PSETQ SB-IMPL::I (1- SB-IMPL::I)
                        SB-IMPL::RESULT (CDR SB-IMPL::RESULT))
                 (RETURN (CAR SB-IMPL::RESULT)))
             (GO LOOP)))))
      (T (CAR (NTHCDR SB-IMPL::N LIST))))))
NIL
NTH

但是,它并不总是可用的,在这种情况下,您必须前往 the SBCL source code repository

首先,一些一般性的说明

  • 在您的自己的代码中,点击Meta-。应该会带您到代码源
  • 这将对通过 Quicklisp 安装的库“有效”。

现在 SBCL 代码本身:

  • 如果代码位于“预期位置”,则在内置函数上点击 Meta-.(如示例中的 nth上面)将带你到它的源头。我相信默认值是 /usr/share/sbcl-source/src/code/ 但可能有一种方法可以配置它。

  • 然而,还有另一种实用的方法来查看此内容:如果您查看上面 (describe ...) 的输出,该行是:

Source file: SYS:SRC;CODE;LIST.LISP
  • 注:不是最后一行,那是给(setf nth)的,略有不同

  • 这告诉您SBCL 源代码中的哪个文件您可以期望找到函数定义。

  • 因此,在 [repo](https://github.com/sbcl/sbcl/tree/master/src) 中,如果您找到 src/code/list.lisp, you should find the definition you're looking for;重现于此:

(defun nth (n list)
  "Return the nth object in a list where the car is the zero-th element."
  (declare (explicit-check)
           (optimize speed))
  (typecase n
    ((and fixnum unsigned-byte)
     (block nil
       (let ((i n)
             (result list))
         (tagbody
          loop
            (the list result)
            (if (plusp i)
                (psetq i (1- i)
                       result (cdr result))
                (return (car result)))
            (go loop)))))
    (t
     (car (nthcdr n list)))))