Search code examples
common-lisp

Problems with scope in defstruct common lisp


I am following the book the ray tracer challenge .. I have created a vector3 and color defstruct

(defstruct (vector3 
             (:conc-name nil)
             (:constructor v3 (x y z w)))
  (x 0.0 :type float)                                                                                                                                                              
  (y 0.0 :type float)                                                                                                                                                              
  (z 0.0 :type float)                                                                                                                                                              
  (w 0.0 :type float))                                                                                                                                                             
                                                                                                                                                                       
(defstruct (colors
             (:conc-name nil)
             (:constructor colors (r g b w)))                                                                                                    
  (r 0.0 :type float)                                                                                                                                                              
  (g 0.0 :type float)                                                                                                                                                              
  (b 0.0 :type float)                                                                                                                                                              
  (w 0.0 :type float))

and some other functions like a scale multiplier

(defun vector-scalar (s v1)                                                                                                                                            
  (vector3 (* s (x v1))                                                                                                                                                
           (* s (y v1))                                                                                                                                                
           (* s (z v1))                                                                                                                                                
           (* s (w v1))))     

but when I try and load the file I am getting errors such as

caught WARNING:                                                                                                                                                      
;   Derived type of COMMON-LISP-USER::V1 is                                                                                                                            
;     (VALUES COMMON-LISP-USER::VECTOR3 &OPTIONAL),                                                                                                                    
;   conflicting with its asserted type                                                                                                                                 
;     COMMON-LISP-USER::COLORS.                                                                                                                                        
;   See also:                                                                                                                                                          
;     The SBCL Manual, Node "Handling of Types"  

I thought that whatever was inside a procedure had local scope so I do not understand why what I would consider an input for a function is being confused with a defstruct. If I load just the vector defstruct I do not get the error.

My worry is that any defstruct that I create that has four parameters will become confused with the vector3

I'm not sure how to resolve this problem because I don't actually understand whats wrong to start with.


Solution

  • Both of your structure definitions define an accessor named w which therefore can't exist. SBCL is not properly noticing this but instead making inferences about the type of the variable which can never be true (it's assuming based on what I suppose is the last definition of w it saw that it's a colors but then based on one of the other accessors that it must be a vector3).

    If you want multiple distinct classes to have the same accessors, you need to use defclass not defstruct: defclass defines accessors as generic functions.