tsm*_*tsm 2 lisp types common-lisp clos
我正在写一个Lisp程序,并试图对类型有点认真.我想有性能改进,但我更感兴趣的是使用类型注释来提高文档和安全性.问题是nil
.到目前为止我遇到了两个问题.
图表A:
>(defmethod foo ((bar bar-class) (quux quux-class))
...)
>(foo (make-instance 'bar-class) nil)
ERROR: No applicable method, etcetera etcetera, because nil is not of type quux-class
Run Code Online (Sandbox Code Playgroud)
图表B:
(defmethod initialize-instance :after ((f foo) &rest args)
"Initialize the grid to be the right size, based on the height and width of the foo."
(declare (ignorable args))
(setf (slot-value f 'grid) (make-array (list (width f) (height f))
:element-type 'foo-component
:adjustable nil
:initial-element nil)))
style-warning:
NIL is not a FOO-COMPONENT.
Run Code Online (Sandbox Code Playgroud)
这里的最佳做法是什么?到目前为止,我所拥有的唯一具有远程洞察力的想法是使用空对象模式并拥有(defclass nil-quux-class (quux-class) ...)
和(defclass nil-foo-component (foo-component) ...)
,但这似乎充其量只是hacky.我不确定为什么,但确实如此.坦率地说,我不习惯在CLOS中设计模式化的变通方法:)
(一)你想,当你调用发生什么foo
用nil
的quux
说法?
如果你什么都不想发生那么
(defmethod foo ((bar bar-class) (quux null))
nil)
Run Code Online (Sandbox Code Playgroud)
会把你排除在外
如果您希望调用相同的代码,就好像您已经传递了一个实例quux-class
,那么:
(defmethod foo ((bar bar-class) (quux quux-class))
(do-stuff bar quux))
(defmethod foo ((bar bar-class) (quux null))
(do-stuff bar quux))
Run Code Online (Sandbox Code Playgroud)
要么:
(defmethod foo ((bar bar-class) quux)
(unless (or (typep bar 'bar-class)
(null bar))
(error "Expected a bar-class or null, got ~s." quux))
(do-stuff bar quux))
Run Code Online (Sandbox Code Playgroud)
(B)你走了
(make-array size :element-type 'foo-component
:initial-element nil)
Run Code Online (Sandbox Code Playgroud)
而你的lisp实现已经指出了一个矛盾 - 最初的元素不能同时nil
和foo-component
s.(嗯,我想这取决于你的类型foo-component
.我假设它不包括null
.)
你可能会考虑:
(make-array :element-type '(or foo-component null)
:initial-element nil)
Run Code Online (Sandbox Code Playgroud)
但要注意:你知道数组中包含foo-component
s或nil
s ,你希望你的lisp获得什么?优化?代表您错误检查?(根据您正在使用的lisp实施,您的里程可能会有所不同.)