recursionschemeracketplai

"application: not a procedure" in binary arithmetic procedures


I have a simple Racket definition for multiplying binary numbers together. It uses a well-tested "addWithCarry" definition that takes three parameters: two lists and a carry digit and returns the binary sum. The binary numbers are represented as lists in reverse order.

I stepped through the test line with the debugger, and it goes through the recursion properly. It performs the multBins each time shrinking the y list as appropriate, then conducts the addWithCarry functions as expected. As it rises back up the stack, it suddenly throws an exception "application: not a procedure, expected a procedure that can be applied to arguments" with the parameter '(0 0 0 1 0 1 1) which is the value of the highest "x" added to the total. I know this error can occur when you are attempting to apply the result of a function as a function with a parameter, but I don't see this here. Watching the debugger, everything seems to be working perfectly until the very end. Any ideas?

(define (multBins x y)
  (cond
    ((null? y)       '() )
    ((= (first y) 0) ((multBins (cons 0 x) (rest y))))
    (#t              ((addWithCarry x (multBins (cons 0 x) (rest y)) 0)))))  
(test (multBins '(1 0 1 1)'(1 1 0 1))'(1 1 1 1 0 0 0 1))

Here is the addWithCarry definition:

(define (addWithCarry x y carry)
  (cond
    ((and (null? x)(null? y)) (if (= carry 0) '() '(1)))
    ((null? x) (addWithCarry '(0) y carry))
    ((null? y) (addWithCarry x '(0) carry))
    ( #t  (let ((bit1 (first x))
            (bit2 (first y)))
               (cond
                 ((= (+ bit1 bit2 carry) 0) (cons 0 (addWithCarry (rest x) (rest y) 0)))
                 ((= (+ bit1 bit2 carry) 1) (cons 1 (addWithCarry (rest x) (rest y) 0)))
                 ((= (+ bit1 bit2 carry) 2) (cons 0 (addWithCarry (rest x) (rest y) 1)))
                 (   #t                     (cons 1 (addWithCarry (rest x) (rest y) 1))))))))

Solution

  • In this line, you're calling multBins with (cons 0 x) and (rest y), and getting some result r, and then trying to call r:

    ((= (first y) 0) ((multBins (cons 0 x) (rest y))))
    ;                ^                              ^
    ;                +--- function application -----+
    

    The same kind of thing is happening in the next line, where you're calling addWithCarry with some arguments, getting a result r, and trying to call r:

    (#t              ((addWithCarry x (multBins (cons 0 x) (rest y)) 0)))))
    ;                ^                                                 ^
    ;                +-------------- function application -------------+
    

    Presumable the unapplicable value '(0 0 0 1 0 1 1) is being returned by one of these.

    In a very simplified case, consider this transcript from the DrRacket REPL:

    > (define (value)        ; a function that returns the 
        '(0 0 0 1 0 1 1))    ; same value that yours should
    
    > (value)                ; calling it produces the value 
    (0 0 0 1 0 1 1)
    
    > ((value))              ; calling it and then calling
                             ; return value causes the same
                             ; error that you're seeing
    ; application: not a procedure;
    ; expected a procedure that can be applied to arguments
    ;  given: (0 0 0 1 0 1 1)
    ;  arguments...: [none]
    

    You didn't mention what editor/IDE/debugger you're using, but some should have made this a bit easier to spot. For instance, when I load your code (minus the call to test, whose definition I don't have, and with definitions of first and rest), DrRacket highlights the location of the offending call:

    bad code highlighted in DrRacket IDE

    While both of the problematic calls that I've pointed out need to be fixed, the error that you're seeing right now is occurring in the second of the two.