Hi all,
I am writing some matrix/vector classes and functions [1], and have a
class hierarchy as follows:
(in-package :cl-user)
(defclass matrix-like ()
((nrows :initarg :nrows :reader nrows :initform 0)
(ncols :initarg :ncols :reader ncols :initform 0)))
(defclass simple-matrix (matrix-like)
((data :initarg :data :reader data)))
(defclass matview (matrix-like)
((parent :initarg :parent :reader parent
:type matrix-like)))
(defclass vector-like (matrix-like) ())
(defclass vecview (vector-like matview)
((parent :initarg :parent :reader parent
:type (or vector-like simple-matrix))))
Notice that both MATVIEW and VECVIEW have a PARENT slot, and that
VECVIEW inherits matview, so the :TYPE declaration of the slot should be
inherited as well, in the form of an (AND T1 ... TN) as per the
Hyperspec section 7.5.3.
It should be ok since (OR VECTOR-LIKE SIMPLE-MATRIX) is a subtype of
MATRIX-LIKE in the above class definitions (all classes indirectly
subclass MATRIX-LIKE).
However CMUCL tells me that it doesn't understand the type definition
for the slot PARENT of VECVIEW:
Error in function PCL::INTERNAL-ERROR:
Internal error: PCL::SPECIALIZER-APPLICABLE-USING-TYPE-P
cannot handle the
second argument
(OR (CLASS #<STANDARD-CLASS VECTOR-LIKE {58827525}>)
(CLASS #<STANDARD-CLASS SIMPLE-MATRIX {587E647D}>)).
[Condition of type SIMPLE-ERROR]
But it is ok if I change the definition by explicitly writing the full
AND type.
(defclass vecview (vector-like matview)
((parent :initarg :parent :reader parent
:type (and matrix-like (or vector-like simple-matrix)))))
By the way, SBCL and clisp don't complain. So, did I write unportable
code, or is CMUCL wrong here?
You may want to know whay I need a type like this. VECVIEW is a view on
a vector, and I would like to allow to build VECVIEWs on matrices by
viewing them as a flat vector (for example, to extract a row or a
column), but only for simple matrices, since doing this on MATVIEWs
introduces too many complexities.
Thanks in advance,
Evan
[1] http://groups.google.com/group/lisp-matrix-devel
--=-=-=
[cc attempted to cmucl-imp]
* Evan Monroig <··············@obakechan.net> :
Wrote on Wed, 18 Jun 2008 09:42:28 +0900:
| Hi all,
|
| I am writing some matrix/vector classes and functions [1], and have a
| class hierarchy as follows:
[SNIP]
|
| Error in function PCL::INTERNAL-ERROR:
| Internal error: PCL::SPECIALIZER-APPLICABLE-USING-TYPE-P
| cannot handle the second argument
| (OR (CLASS #<STANDARD-CLASS VECTOR-LIKE {58827525}>)
| (CLASS #<STANDARD-CLASS SIMPLE-MATRIX {587E647D}>)).
|
| But it is ok if I change the definition by explicitly writing the full
| AND type.
I just took a quick initial look at this:
This seems to be SBCL BUG 391 which was fixed in sbcl-0.9.7.1
(2005-11-29 by Christophe Rhodes)
,----
- Typed slots with moderately difficult types, combined with
- subclassing, cause the computation of effective-slot-definitions to
- go awry.
- (defclass foo () ((x :type fixnum)))
- (defclass bar (foo) ((x :type (integer 1 5))))
- gives an error from SB-PCL::SPECIALIZER-APPLICABLE-USING-TYPE-P.
- This is probably because of an inappropriate use of *SUBTYPEP in
- COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGS.
`----
The "cannot handle second argument" is thrown by PCL::*SUBTYPEP, which
only handles a few types.
The way SBCL fixes this bug is by simply deleting the branch involving
PCL::*SUBTYPEP which causes the problem. PCL::SUBTYPEP does not deal
with (OR) types or other integer types. The comment in the patch admits
that this solution is neither efficient not elegant, but just it does
get rid of the error. Here is how the [slightly tab-doctored for CMUCL]
patch ported over from SBCL looks like
--=-=-=
Content-Type: text/x-patch
Content-Disposition: inline; filename=csr-sbcl-std-class-fix-20051129.diff
--- a/pcl/std-class.lisp
+++ b/pcl/std-class.lisp
@@ -1127,9 +1127,14 @@
allocp t))
(setq initargs (append (slot-definition-initargs slotd) initargs))
(let ((slotd-type (slot-definition-type slotd)))
- (setq type (cond ((eq type t) slotd-type)
- ((*subtypep type slotd-type) type)
- (t `(and ,type ,slotd-type)))))))
+ (setq type (cond
+ ((eq type t) slotd-type)
+ ;; This pairwise type intersection is perhaps a
+ ;; little inefficient and inelegant, but it's
+ ;; unlikely to lie on the critical path. Shout
+ ;; if I'm wrong. -- CSR, 2005-11-24
+ (t (kernel:type-specifier
+ (kernel:specifier-type `(and ,type ,slotd-type)))))))))
(list :name name
:initform initform
:initfunction initfunction
--=-=-=
I would prefer waiting for a solution that fixes the subtypep branch in
the code that causes this problem by teaching it to do types correctly,
rather than committing this fix. However I wanted to note this solution
so one could apply it in a pinch, if it was a showstopper.
--
Madhu
--=-=-=--
Madhu <·······@meer.net> writes:
> * Evan Monroig <··············@obakechan.net> :
> Wrote on Wed, 18 Jun 2008 09:42:28 +0900:
>
> | Error in function PCL::INTERNAL-ERROR:
> | Internal error: PCL::SPECIALIZER-APPLICABLE-USING-TYPE-P
> | cannot handle the second argument
> | (OR (CLASS #<STANDARD-CLASS VECTOR-LIKE {58827525}>)
> | (CLASS #<STANDARD-CLASS SIMPLE-MATRIX {587E647D}>)).
> |
> | But it is ok if I change the definition by explicitly writing the full
> | AND type.
>
> I just took a quick initial look at this:
>
> This seems to be SBCL BUG 391 which was fixed in sbcl-0.9.7.1
> (2005-11-29 by Christophe Rhodes)
>
> ,----
> - Typed slots with moderately difficult types, combined with
> - subclassing, cause the computation of effective-slot-definitions to
> - go awry.
> - (defclass foo () ((x :type fixnum)))
> - (defclass bar (foo) ((x :type (integer 1 5))))
> - gives an error from SB-PCL::SPECIALIZER-APPLICABLE-USING-TYPE-P.
> - This is probably because of an inappropriate use of *SUBTYPEP in
> - COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGS.
> `----
Indeed it seems to be the same bug, and in CMUCL for the above two
classes one way to go around the bug is to explicitly define oneself the
AND type in the following way:
(defclass foo () ((x :type fixnum)))
(defclass bar (foo) ((x :type (and fixnum (integer 1 5)))))
> The way SBCL fixes this bug is by simply deleting the branch involving
> PCL::*SUBTYPEP which causes the problem. PCL::SUBTYPEP does not deal
> with (OR) types or other integer types. The comment in the patch admits
> that this solution is neither efficient not elegant, but just it does
> get rid of the error. Here is how the [slightly tab-doctored for CMUCL]
> patch ported over from SBCL looks like
[snip]
> I would prefer waiting for a solution that fixes the subtypep branch in
> the code that causes this problem by teaching it to do types correctly,
> rather than committing this fix. However I wanted to note this solution
> so one could apply it in a pinch, if it was a showstopper.
Thanks a lot for giving this fix. Actually it is not a showstopper for
the example that I gave and the example that is in the SBCL bug, because
one can explicitly give the derived type (I don't know if it would work
for more complicated type declarations).
Cheers,
Evan Monroig