-1

I'm trying to learn scheme (more specifically R5RS), and I want to define a procedure that takes as input a list with 3 elements, for example: '(5 + 2), where the middle argument always is an operator, and the 1st and 3rd are always operands.

Examples:

(proc-mid '(1 + 2))
--> 3
(proc-mid '(1 list 2))
--> (1 2)
(proc-mid '(20 * 5))
--> 100

My code so far is this:

(define (proc-mid exp)
    (define proc (cadr exp))
    (proc (car exp) cddr exp))

However, I get an error saying:

    application: not a procedure;
     expected a procedure that can be applied to arguments
      given: +
      arguments...:

My question is then, why is + not evaluated as a procedure?

Bjørn Olav Jalborg
  • 373
  • 1
  • 3
  • 14

3 Answers3

2

When Scheme evaluates (+ a b) it evaluates the operand + and it will hopefully have a procedure value, then a and b which both perhaps should evaluate to numeric values. Then apply will apply the result of + with the result of the operands.

The quoted expression '(+ a b) does not evaluate it's argument. Thus + does not get evaluated to a procedure and a and b gets not evaluated to numbers. The value is just the list (+ a b). If you were to make this with list you'd do (list '+ 'a 'b). If you do (list + a b) you get the 3 variables evaluated and get something like (#<system-procedure:+> 2 3) back.

The quoted expression '(+ 2 3) is special since you have numeric literals and they are self evaluating, but + is still a symbol and not the evaluated variable that look the same because quote does not evaluate it's argument.

(apply '+ '(2 3)) won't work since + in not a procedure.

You should perhaps map your primitives to the actual procedures?

;; assoc between symbols and their corresponding procedure value
(define PROCS `((+ . ,+) (* . ,*)))

(define (get-proc symbol)
  (let ((match (assq symbol PROCS)))
    (if match
        (cdr match)
        symbol)))
Sylwester
  • 47,942
  • 4
  • 47
  • 79
1

In your case + is a symbol since

'(element1 element2 ... elementn)

will turn text(non-numbers/boolean etc.) into symbols.

(define l1 '(1 a #f +))

(symbol? (car l1))
(symbol? (cadr l1))
(symbol? (caddr l1))
(symbol? (cadddr l1))

#f

#t

#f

#t

You can use eval carefully to evaluate the text like in this answer:

(eval '(+ 1 2))
 3  

docs: racket quote

Eggcellentos
  • 1,570
  • 1
  • 18
  • 25
0

+ is bound to a procedure in most scopes, but is itself a symbol. The procedure to which it is almost-always bound is a procedure. For instance, in (let ((+ "+")) +), + is a string. In any reasonable state, you'll have something like

(procedure? '+) => #f (procedure? +) => #t, all of which is to say, in most programming languages you can imagine the environment of available variables/functions/etc as a dictionary of symbols to values, it's just that in scheme the symbols which point to the values are accessible as values. So in quoting the list (+ 1 2), you refer to a list of symbols, the keys in the environment/dictionary, instead of the values. (symbol? (cadr '(1 + 2))) versus (procedure? (cadr (list 1 + 2)))

jcc333
  • 759
  • 5
  • 15