从闭包的角度来讲,外部环境直接用accessor而不是reader和writer是不是不好?毕竟用accessor的话,外部对这个accessor对应的slot做什么就不在原对象的控制之下了。还是说我想多了?
(defclass myclass ()
((natual-numbers
:initarg :natrual-nambers
:accessor natrual-numbers-of
:writer set-natrual-numbers-for
:reader get-natrual-numbers-of)))
(cl-defmethod set-natrual-numbers-for ((instance myclass) value)
(dolist (num value)
(unless (and (integerp num)
(>= num 0))
(error "Not natrual number: %d" num)))
(setf (natrual-numbers-of instance) value))
(setq myinstance (myclass :natrual-nambers '(1 2 3 4 5)))
(setf (natrual-numbers-of myinstance) '(-1 -2 -3)) ;; 这就不好
(set-natrual-numbers-for myinstance '(-1 -2 -3)) ;; 会报错
(set-natrual-numbers-for myinstance '(1 2 3)) ;; 没问题
对于 accessor
你可以
(cl-defmethod (setf natrual-numbers-of) :before ((instance myclass) value) ...)
然后我在上个贴子提了 (satisfies fn)
的用法,你一定沒仔细看。
(cl-deftype h-list (type)
`(satisfies (lambda (x)
(do ((lst x (cdr lst))
(res t))
((or (eq lst nil) (eq res nil)) res)
(unless (typep (car lst) ,type)
(setq res nil))))))
(defclass myclass ()
((natual-numbers
:initarg :natrual-nambers
:accessor natrual-numbers-of
:type (h-list '(integer 0)))))
(setf (natrual-numbers-of myinstance) '(-1 -2 -3))
;; Lisp error: (invalid-slot-type myclass natual-numbers (h-list '(integer 0)) (-1 -2 -3))
我肯定仔细看了呀,只不过我这个问题重点在于对象没法控制外部对它的slot做什么,是例子没举好。
(你一打岔我都忘了)(setf natrual-numbers-of)
的原理是什么?只是cl-defmethod
单纯支持这种写法吗?
你沒法通過 defmethod
控制直接用 slot-value
來设置的,想「万无一失」只能用滥用类型檢查。
(setf (slot-value foo 'natual-numbers) -2)
;; 不会触发 (cl-defmethod (setf natrual-numbers-of) :before ...
;; 但仍会进行 type check
(macroexpand '(setf (natrual-numbers-of myinstance) '(-1 -2 -3)))
;; => (let* ((v myinstance)) (\(setf\ natrual-numbers-of\) (quote (-1 -2 -3)) v))
defun
也支持。 Common Lisp 里 defun
支持,然而 Emacs Lisp 要这樣写:
(defun \(setf\ foo\) (a b)
(+ a 1))
(setf (foo 2) 3) ;; => 4
cl-defun
也不支持。
为什么直接执行(setf natrual-numbers-of)
没有返回lambda,而是报错了?
- 你沒有 escape space。
- 你以為这是 lisp-1 啊?
(symbol-function '\(setf\ natrual-numbers-of\))
;; => #[642 ... byte-code
In NewLisp, which is a lisp-1 looks like Scheme (use this because it prints function definition):
(define (foo x) x))
foo
;; => (lambda (x) x)
where in Emacs Lisp
(defun foo (x) x)
(symbol-function 'foo)
;; => (lambda (x) x)
Languages like C, Ada, Python, JavaScript, Swift are all “lisp-1”。
是的
1 个赞
喔喔,你是说我把函数symbol当成变量symbol eval了是吗。
thx