sbcl - 如何为check-type和assert输入新值

时间:2015-08-10 02:41:20

标签: common-lisp

我从书中删除了一个例子:ANSI Common Lisp,第14.6章条件。

但是check-type和assert示例在sbcl中不起作用。 我怎样才能输入新值?无论我输入什么新值,它总是失败。

但是,它适用于clisp。

示例代码:

(let ((x '(a b c))) (check-type (car x) integer "an integer")  x)


(let ((sandwich '(ham on rye)))
    (assert (eql (car sandwich) 'chicken)
        ((car sandwich))
        "I wanted a ~a sandwich." 'chicken)
    sandwich)

在sbcl中: 示例1:

* (let ((x '(a b c))) (check-type (car x) integer "an integer")  x)
; in: LET ((X '(A B C)))
;     (CHECK-TYPE (CAR X) INTEGER "an integer")
; --> DO BLOCK LET TAGBODY TAGBODY SETF 
; ==>
;   (SB-KERNEL:%RPLACA X
;                      (SB-KERNEL:CHECK-TYPE-ERROR '(CAR X) #:G0 'INTEGER
;                                                  "an integer"))
; 
; caught WARNING:
;   Destructive function SB-KERNEL:%RPLACA called on constant data.
;   See also:
;     The ANSI Standard, Special Operator QUOTE
;     The ANSI Standard, Section 3.2.2.3
; 
; compilation unit finished
;   caught 1 WARNING condition

debugger invoked on a SIMPLE-TYPE-ERROR in thread
#<THREAD "main thread" RUNNING {B3E2341}>:
  The value of (CAR X) is A, which is not an integer.

Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [STORE-VALUE] Supply a new value for (CAR X).
  1: [ABORT      ] Exit debugger, returning to top level.

(SB-KERNEL:CHECK-TYPE-ERROR (CAR X) A INTEGER "an integer")
0] 0

Type a form to be evaluated: 0

debugger invoked on a SIMPLE-TYPE-ERROR in thread
#<THREAD "main thread" RUNNING {B3E2341}>:
  The value of (CAR X) is A, which is not an integer.

Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [STORE-VALUE] Supply a new value for (CAR X).
  1: [ABORT      ] Exit debugger, returning to top level.

(SB-KERNEL:CHECK-TYPE-ERROR (CAR X) A INTEGER "an integer")
0] 

例2:

* (let ((sandwich '(ham on rye)))
    (assert (eql (car sandwich) 'chicken)
        ((car sandwich))
        "I wanted a ~a sandwich." 'chicken)
    sandwich)
; in: LET ((SANDWICH '(HAM ON RYE)))
;     (ASSERT (EQL (CAR SANDWICH) 'CHICKEN) ((CAR SANDWICH))
;             "I wanted a ~a sandwich." 'CHICKEN)
; --> TAGBODY SETF 
; ==>
;   (SB-KERNEL:%RPLACA SANDWICH
;                      (SB-IMPL::ASSERT-PROMPT '(CAR SANDWICH) (CAR SANDWICH)))
; 
; caught WARNING:
;   Destructive function SB-KERNEL:%RPLACA called on constant data.
;   See also:
;     The ANSI Standard, Special Operator QUOTE
;     The ANSI Standard, Section 3.2.2.3
; 
; compilation unit finished
;   caught 1 WARNING condition

debugger invoked on a SIMPLE-ERROR in thread
#<THREAD "main thread" RUNNING {B3E2341}>:
  I wanted a CHICKEN sandwich.

Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [CONTINUE] Retry assertion with new value for (CAR SANDWICH).
  1: [ABORT   ] Exit debugger, returning to top level.

(SB-KERNEL:ASSERT-ERROR (EQL (CAR SANDWICH) (QUOTE CHICKEN)) (((CAR SANDWICH) HAM)) ((CAR SANDWICH)) "I wanted a ~a sandwich." CHICKEN)
0] 0

The old value of (CAR SANDWICH) is HAM.
Do you want to supply a new value?  (y or n) y

Type a form to be evaluated:
'chicken

debugger invoked on a SIMPLE-ERROR in thread
#<THREAD "main thread" RUNNING {B3E2341}>:
  I wanted a CHICKEN sandwich.

Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [CONTINUE] Retry assertion with new value for (CAR SANDWICH).
  1: [ABORT   ] Exit debugger, returning to top level.

(SB-KERNEL:ASSERT-ERROR (EQL (CAR SANDWICH) (QUOTE CHICKEN)) (((CAR SANDWICH) HAM)) ((CAR SANDWICH)) "I wanted a ~a sandwich." CHICKEN)
0] 

但是在clisp中,它运作良好。

[1]> (let ((x '(a b c))) (check-type (car x) integer "an integer")  x)

*** - The value of (CAR X) should be an integer.
      The value is: A
The following restarts are available:
STORE-VALUE    :R1      Input a new value for (CAR X).
ABORT          :R2      Abort main loop
Break 1 [2]> :R1
New (CAR X)> 99
(99 B C)
[3]> (let ((sandwich '(ham on rye)))
    (assert (eql (car sandwich) 'chicken)
You are in the top-level Read-Eval-Print loop.
Help (abbreviated :h) = this list
Use the usual editing capabilities.
(quit) or (exit) leaves CLISP.
    ((car sandwich))
You are in the top-level Read-Eval-Print loop.
Help (abbreviated :h) = this list
Use the usual editing capabilities.
(quit) or (exit) leaves CLISP.
    "I wanted a ~a sandwich." 'chicken)
    sandwich)

** - Continuable Error
I wanted a CHICKEN sandwich.
If you continue (by typing 'continue'): Input a new value for (CAR SANDWICH).
The following restarts are also available:
ABORT          :R1      Abort main loop
Break 1 [4]> continue
New (CAR SANDWICH)> 'chicken
(CHICKEN ON RYE)
[5]> 

1 个答案:

答案 0 :(得分:2)

您不应该修改文字数据。 Common Lisp标准中未定义后果。

这是未定义的:

(let ((x '(a b c)))
  (setf (car x) 10))

这有效:

(let ((x (list 'a 'b 'c)))
  (setf (car x) 10))