1

I'd like some help with understanding an SBCL compiler warning message, which occurs when compiling a lambda expression. The lambda expression is temporarily stored as the symbol-value of a user-defined name, and the compiled function is subsequently stored under the name's symbol-function.

* (compile nil (symbol-value 'activate-connector-if!))
; in: LAMBDA (STATE ?CONNECTOR)
;     (APPLY #'SOME
;            (LAMBDA (WOULDWORK-PKG::?T1 WOULDWORK-PKG::?T2)
;              (AND
;               (GETHASH (+ 126 # #)
;                        (WOULDWORK-PKG::PROBLEM-STATE.IDB WOULDWORK-PKG::STATE))
;               (GETHASH (+ 126 # #)
;                        (WOULDWORK-PKG::PROBLEM-STATE.IDB WOULDWORK-PKG::STATE))
;               (LET (#)
;                 (WHEN VALUES #))
;               (LET (#)
;                 (WHEN VALUES #))
;               (NOT (EQL WOULDWORK-PKG::$HUE1 WOULDWORK-PKG::$HUE2))))
;            NIL NIL)
; --> MULTIPLE-VALUE-CALL SB-C::%FUNCALL SOME LET BLOCK SB-INT:DX-FLET FLET
; --> #:WRAPPER102 BLOCK LET
; ==>
;   (SB-C::%FUNCALL #:G100 #:G99)
;
; caught WARNING:
;   function called with one argument, but wants exactly two
;   See also:
;     The ANSI Standard, Section 3.2.2.3
;
; compilation unit finished
;   caught 1 WARNING condition
#<FUNCTION (LAMBDA (STATE ?CONNECTOR)) {1002E32AAB}>
T
T

The warning corresponds to the two required arguments, but there is no information about where the function is being called from. However, there is only one possible place it can be called from, and a check verifies that it is being called with two arguments.

Since the program runs fine on all test cases in spite of this warning, at first I thought it meant the function is never being called. But a trace verifies it is being called properly a number of times with the correct arguments.

Is there any other way to get at what is generating the warning?

davypough
  • 1,847
  • 11
  • 21

1 Answers1

5

(LAMBDA (WOULDWORK-PKG::?T1 WOULDWORK-PKG::?T2) ...) requires 2 arguments, but it's being called with just 1 argument by SOME. When you convert the APPLY call to a normal function call, it looks like:

(some (lambda (?t1 ?t2) ...) '())

There need to be as many sequence arguments as arguments to the predicate function, but there's only one sequence and two arguments.

Maybe you meant to use FUNCALL rather than APPLY? APPLY treats its last argument as a list of arguments, so NIL is spread into no arguments.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • Thanks for the clue about how to better read a debugger message. But then why doesn't `(apply #'some (lambda (x y) (list x y)) nil nil)` produce a warning at the REPL? Doesn't SBCL wrap this in a lambda and then compile? – davypough Feb 16 '21 at 17:44
  • 1
    @davypough: it probably should warn. Not warning doesn't mean the code is right... –  Feb 16 '21 at 18:15
  • 1
    @davypough I'm not sure that SBCL's REPL actually works by compiling the expression first. And actually executing that expression doesn't signal an error, because `SOME` appears to check whether any of the lists are empty and never bothers to call the predicate. If you change to `(apply #'some (lambda (x y) (list x y)) '(1) nil)` you get a runtime error, not compile-time. – Barmar Feb 16 '21 at 18:47