给出这个示例代码(来自Reddit/r/lisp问题):
(defun next (pos)
(nth (1+ pos)
'(0 1 2 3 4 5 6 7 8 9 10)))
(defvar *next* (function next))
(let ((old-next #'next)
(previous (make-hash-table)))
(format t "~% 1 EQ? ~a" (eq old-next *next*))
(defun next (pos)
(or (gethash pos previous)
(setf (gethash pos previous) (funcall old-next pos))))
(format t "~% 2 EQ? ~a" (eq old-next *next*)))
Run Code Online (Sandbox Code Playgroud)
以上建立了一个功能NEXT.在里面LET,我们保留旧功能OLD-NEXT.然后我们重新定义了NEXT内部的全局函数LET.
CCL/CMUCL/GCL/ECL/CLISP/LispWorks/ABCL:
? (load "test.lisp")
1 EQ? T
2 …Run Code Online (Sandbox Code Playgroud) SBCL 64位,1.1.7
如果我想创建一个包并使用包中的一些小符号:CL,我将创建一个像这样的包:
(defpackage :foo
(:import-from :cl
:defun :defmacro :in-package
:null :car :cdr :cons :if
:eq))
Run Code Online (Sandbox Code Playgroud)
但是,在这个包中,如果我定义一个带有可选参数的函数并在不提供可选参数的情况下调用它,我总会得到一个错误:
(defun test (&optional a))
(test)
invalid number of arguments: 0
[Condition of type SB-INT:SIMPLE-PROGRAM-ERROR]
Restarts:
0: [RETRY] Retry SLIME interactive evaluation request.
1: [*ABORT] Return to SLIME's top level.
2: [REMOVE-FD-HANDLER] Remove #<SB-IMPL::HANDLER INPUT on descriptor 10: #<CLOSURE (COMMON-LISP:LABELS SWANK-BACKEND::RUN :IN SWANK-BACKEND:ADD-FD-HANDLER) {100490B95B}>>
3: [ABORT] Exit debugger, returning to top level.
Run Code Online (Sandbox Code Playgroud)
定义宏得到相同的错误,但有更多信息:
(defmacro test (&rest body))
(test)
error while parsing arguments to DEFMACRO …Run Code Online (Sandbox Code Playgroud) ANSI Common Lisp.为什么我在最后一个案例中得到了另一个答案?
(list 1 2 3 nil) ; (1 2 3 nil)
(funcall (function list) 1 2 3 nil) ; (1 2 3 nil)
(apply (function list) '(1 2 3 nil)) ; (1 2 3 nil)
(apply (function list) 1 2 3 nil) ; (1 2 3)
Run Code Online (Sandbox Code Playgroud) 我想在类对象上定义方法,这些方法基于类的祖先继承,实例方法的继承方式相同。有什么办法可以做到这一点?
这是行不通的:eql-方法专门化。考虑以下示例:
(defclass animal ()())
(defclass bird (animal)())
(defclass woodpecker (bird)())
(defmethod wings-p ((animal-class (eql (find-class 'animal)))) nil)
(defmethod wings-p ((bird-class (eql (find-class 'bird)))) t)
Run Code Online (Sandbox Code Playgroud)
调用会(wings-p (find-class 'woodpecker))生成一个no-method-error,您会看到原因- 对于任何方法专门化器,类woodpecker显然都不eql是。
我想定义“方法” bird,animal以便当我调用wings-p时(find-class woodpecker),wings-p返回t。
我觉得这几乎是所有其他OO系统的标准功能,但是我不记得如何使用CLOS做到这一点。
查看HyperSpec中#'adjoin的文档,我在示例部分中看到以下内容:
(setq slist '()) => NIL
(setq slist (adjoin '(test-item 1) slist)) => ((TEST-ITEM 1))
(adjoin '(new-test-item 1) slist :key #'cadr) => ((TEST-ITEM 1))
Run Code Online (Sandbox Code Playgroud)
我希望以下内容:
(adjoin '(new-test-item 1) slist :key #'cadr) => ((NEW-TEST-ITEM 1) (TEST-ITEM 1))
Run Code Online (Sandbox Code Playgroud)
我的期望是由于HyperSpec(17.2.1)中的以下文本:
当通过下图中列出的运算符F对序列S的每个元素Ei迭代地考虑对象O时,有时控制在S中测试O的存在的方式由F测试.控制是基于用a:test或:test-not argument指定的函数提供的.
并进一步:
对象O可能无法直接与Ei进行比较.如果提供了:key参数,则它是一个参数的指示符,用于将每个Ei作为参数调用一个参数,并产生一个用于比较的对象Zi.(如果没有:关键参数,Zi就是Ei.)
由:key参数指定的函数永远不会在O本身上调用.但是,如果函数在多个序列上运行(例如,在set-difference中发生),则O将是在另一个序列的元素上调用:key函数的结果.
因此我们将sl(序列,S)'((TEST-ITEM 1))和O作为'(new-test-item 1).要检查是否应该连接O,该函数#'cadr将应用于S的元素,第一个是'(test-item 1).所以,那个测试给出了:
(cadr '(test-item 1)) => 1
Run Code Online (Sandbox Code Playgroud)
现在,当'(new-test-item 1)根据应用于#'cadrS的E1 的结果#'eql(当没有提供时使用的等式函数)检查O,时:test,false结果应该意味着O被连接.至少这就是我的想法.我有什么误会?
handler-case 是在 Common Lisp 中处理条件的关键,但 Ubuntu 18.04 上的 GCL 2.6.12 认为它是一个未定义的函数:
>(handler-case (error "test") (error (condition) condition))
Error: UNDEFINED-FUNCTION :NAME HANDLER-CASE
Fast links are on: do (si::use-fast-links nil) for debugging
Signalled by EVAL.
UNDEFINED-FUNCTION :NAME HANDLER-CASE
Broken at EVAL. Type :H for Help.
1 Return to top level.
>>
Run Code Online (Sandbox Code Playgroud)
对于 也是如此handler-bind。
GCL 手册中唯一与处理条件或错误相关的函数是 GCL 特定的universal-error-handler.
如何在 GCL 中处理条件,最好以其他 Lisps 支持的方式处理?
lisp common-lisp gnu-common-lisp condition-system ansi-common-lisp
(setf vec (make-array 4 :initial-element nil))
(svref vec 0)
Run Code Online (Sandbox Code Playgroud)
在上面的代码片段中,我们创建了一个长度为4的向量,并通过(svref vec)访问其元素.
(vector 1 2 3 4 5)
Run Code Online (Sandbox Code Playgroud)
在上面的代码片段中,我们使用向量函数创建长度为5的向量.我们如何访问此向量的元素?svref如何用于此向量?