Thursday, 1 September 2022

SBCL Type Inference problem in a somewhat weird macro

I'm trying to create a shorthand for lambda using underbar (_), per:

(defmacro _ (&rest body)                                                                                                                                        
  `(lambda (&rest _) ,@(expand_s body)))                                                                                                                        
                                                                                                                                                                
(defun expand_s (s)                                                                                                                                             
  (cond ((null s) nil)                                                                                                                                          
        ((atom s)                                                                                                                                               
         (if (eq '_ s) '(nth 0 _)                                                                                                                               
             (let ((s_string (format nil "~a" s)))                                                                                                              
               (if (char-equal #\_ (aref s_string 0))                                                                                                           
                   `(nth ,(1- (parse-integer (subseq s_string 1))) _)                                                                                           
                   s))))                                                                                                                                        
        (t (cons (expand_s (car s)) (expand_s (cdr s))))))                                                                                                      
                                                                                                                                                                
(print (macroexpand '(_ (+ _1 _2))))                                                                                                                            
(print (mapcar (_ (+ (* _1 _2) (expt _2 _1))) '(1 2 3) '(10 20 30)))   

Ugly as it is, it works fine compiled in SBCL:

* (load "shlambda.fasl")                                                                                                                                        
                                                                                                                                                                
#'(LAMBDA (&REST _) (+ (NTH 0 _) (NTH 1 _)))                                                                                                                    
(20 440 27090)                                                                                                                                                                                                                                                                                                                

But the SBCL compiler really doesn't like it:

; compiling (PRINT (MAPCAR # ...))                                                                                                                              
; file: shlambda.lisp                                                                                                            
; in:                                                                                                                                                           
;      PRINT (MAPCAR (_ (+ (* |_1| |_2|) (EXPT |_2| |_1|))) '(1 2 3) '(10 20 30))                                                                               
;     (_ (+ (* |_1| |_2|) (EXPT |_2| |_1|)))                                                                                                                    
; --> FUNCTION + * NTH SB-C::%REST-REF AND IF                                                                                                                   
; ==>                                                                                                                                                           
;   NIL                                                                                                                                                         
;                                                                                                                                                               
; caught STYLE-WARNING:                                                                                                                                         
;   This is not a NUMBER:                                                                                                                                       
;    NIL                                                                                                                                                        
;   See also:                                                                                                                                                   
;     The SBCL Manual, Node "Handling of Types"                                                                                                                 
;                                                                                                                                                               
; caught STYLE-WARNING:                                                                                                                                         
;   This is not a NUMBER:                                                                                                                                       
;    NIL                                                                                                                                                        
;   See also:                                                                                                                                                   
;     The SBCL Manual, Node "Handling of Types"                                                                                                                 
                                                                                                                                                                
; --> FUNCTION + EXPT NTH SB-C::%REST-REF AND IF                                                                                                                
; ==>                                                                                                                                                           
;   NIL                                                                                                                                                         
;                                                                                                                                                               
; caught STYLE-WARNING:                                                                                                                                         
;   This is not a NUMBER:                                                                                                                                       
;    NIL                                                                                                                                                        
;   See also:                                                                                                                                                   
;     The SBCL Manual, Node "Handling of Types"                                                                                                                 
;                                                                                                                                                               
; caught STYLE-WARNING:                                                                                                                                         
;   This is not a NUMBER:                                                                                                                                       
;    NIL                                                                                                                                                        
;   See also:                                                                                                                                                   
;     The SBCL Manual, Node "Handling of Types"                                                                                                                 
;                                                                                                                                                               
; compilation unit finished                                                                                                                                     
;   caught 4 STYLE-WARNING conditions       

I guess type inference can't figure out the types of an &rest in a lambda (which, I admit, I'm amazed that it even accepts an &rest in a lambda!) But you can pretty much never figure out the types in an &rest, so ... ???

Thanks in advance for your guidance.



from SBCL Type Inference problem in a somewhat weird macro

No comments:

Post a Comment