将nil视为通配符类型

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中设计模式化的变通方法:)

Nic*_*ine 5

(一)你想,当你调用发生什么foonilquux 说法?

如果你什么都不想发生那么

(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实现已经指出了一个矛盾 - 最初的元素不能同时nilfoo-components.(嗯,我想这取决于你的类型foo-component.我假设它不包括null.)

你可能会考虑:

(make-array :element-type '(or foo-component null)
            :initial-element nil)
Run Code Online (Sandbox Code Playgroud)

但要注意:你知道数组中包含foo-components或nils ,你希望你的lisp获得什么?优化?代表您错误检查?(根据您正在使用的lisp实施,您的里程可能会有所不同.)