problem with assoc

Discussion of Scheme and Racket

problem with assoc

I am trying to write a calculator procedure for the little schemer .. I have one procedure that works

Code: Select all
`(define value  (lambda (n)    (if (atom- n)   n   (if (eq? (car (cdr n)) '0+)       (0+ (car n)(value (car (cdr (cdr n)))))       (if (eq? (car (cdr n)) '0*)      (0* (car n)(value (car (cdr (cdr n)))))      (if (eq? (car (cdr n)) '0-)          (0- (car n)(value (car (cdr (cdr n)))))          (if (eq? (car (cdr n)) '0/)         (0/ (car n)(value (car (cdr (cdr n)))))         (if (eq? (car (cdr n)) '0^)             (0^ (car n)(value (car (cdr (cdr n)))))         #f))))))))`

so I tried another method that does not work

Code: Select all
`(define alist '((0+ 0+)(0* 0*)(0- 0-)(0/ 0/)(0^ 0^)))(define value  (lambda (n)    (if (atom- n)   n    (let ((f (assq (car (cdr n)) alist)))      (if (or (eq? (car (cdr n)) '0+)         (eq? (car (cdr n)) '0*)         (eq? (car (cdr n)) '0-)         (eq? (car (cdr n)) '0/)         (eq? (car (cdr n)) '0^))          (f (car n) (value (car (cdr (cdr n)))))          #f)))))`

the error message for example (value '(3 0+ 4)) has ERROR: in procedure (#{0=}# ... wrong type to apply .. when I try (assoc '0+ alist) I get (#{0+}# . #{0+}#) so this is where my problem is .. but why?

Posts: 11
Joined: Wed Nov 02, 2011 11:56 pm

Re: problem with assoc

Each element of the association list is a list, so you want 'f' to be some element of that list—the second element, I guess? I mean, it's redundant to be mapping each symbol to itself.
David Mullen

Posts: 78
Joined: Mon Dec 01, 2014 12:29 pm

Re: problem with assoc

You are doing a very typical mistake of confusing symbols with bound procedures.Your alist must bedefined so that the value is a procedure and not just a symbol. Thus the symbol needs to be evaluated on the right hand side:

Code: Select all
`(define alist `((0+ ,0+)(0* ,0*)(0- ,0-)(0/ ,0/)(0^ ,0^)))`

As you probably know this is just syntax sugar for:

Code: Select all
`(define alist (list (list '0+ 0+) (list '0* 0*)(list '0- 0-)(list '0/ 0/)(list '0^ 0^)))`
I'm the author of two useless languages that uses BF as target machine.
Currently I'm planning a Scheme compiler :p
sylwester

Posts: 133
Joined: Mon Jul 11, 2011 2:53 pm

Re: problem with assoc

I have re written my code

Code: Select all
`(define a-list `((+ ,0+)(* ,0*)(- ,0-)(/ ,0/)))`
and
Code: Select all
`(define val-  (lambda (n)    (if (atom- n)   n   (lambda f     (f (car n)(val- (car (cdr (cdr n)))))     (assoc (car (cdr n)) a-list)))));;; or (define val  (lambda (n)    (if (atom- n)   n   (let ((f ((car (cdr (assoc (car (cdr n)) a-list))))))     (f (car n)(val (car (cdr (cdr n)))))))))`

but still get an error (val- '(3 + 4)) #<procedure 1e50de0 at <current input>:71:8 f. I am assuming that the lambda or let of f is the problem .. I have been looking online on how to access the a-list and use it to generate a procedure with no success.

Posts: 11
Joined: Wed Nov 02, 2011 11:56 pm

Re: problem with assoc

val- doesn't make sense.. If it's an atom return the atom if not return a procedure..

In val you have double parentheses in an expression so the 0+ is applied with zero arguments and the result is then stored as f. It's most likely a number so then you are trying to apply it as a procedure.

Another thing I see is that your evaluator doesn't evaluate the first argument.. Thus '(+ (- 3 1) (- 3 2)) would fail.. In the default case your evaluator must find the procedure, then evaluate the second and third argument since both can be expressions. In the end you need to apply the values like this:

Code: Select all
`(define (evaluator expression)  (if (atom? expression)      expression      (let ((proc (find-proc (car expression)))            (arg1 (evaluator (cadr expression)))            (arg2 (evaluator (caddr expression))))        (proc arg1 arg2))))(evaluator '(+ (- 3 1) (- 3 2))) ;==> 3`

The assoc:

Code: Select all
`(define *procedures* `((+ ,+)(* ,*)(- ,-)(/ ,/)))(define *sym* '+)(assoc *sym* *procedures*) ; ==> (+ #procedure)((cadr (assoc *sym* *procedures*)) 1 3) ; ==> 4`
I'm the author of two useless languages that uses BF as target machine.
Currently I'm planning a Scheme compiler :p
sylwester

Posts: 133
Joined: Mon Jul 11, 2011 2:53 pm

Re: problem with assoc

with a lot of help on irc groovy2shoes in particular I came up with

Code: Select all
`(define a-list `((+ . ,0+)(* . ,0*)(- . ,0-)(/ . ,0/)(0^ . ,0^)));;; where 0+ etc are prewritten procedures could have used + - (define value  (lambda (n)    (if (atom- n)   n   (let ((op (car (cdr n))))     (let ((f (assq op a-list)))       (if f      ((cdr f)(car n)(value (car (cdr (cdr n)))))      #f)))))`

and managed to simplify it down to ..

Code: Select all
`(define value  (lambda (n)    (if (atom- n)   n   ((lambda (f)      (if f          (f (car n)(value (caddr n)))          #f))    (cdr (assq (cadr n) a-list))))))`

this code is good for questions of (2 + (3 * 4)) type and things like (+ (2 + 3)(3 * 4)) are a seperate procedure in the litte schemer where I got the inspiration for this procedure from.

the real question for me now is why the association list has to be written the way it is with dot notation ..

thanks for all the help .. really appreciated

Posts: 11
Joined: Wed Nov 02, 2011 11:56 pm

Re: problem with assoc

It doesn't. If you look at the code snipplet I gave I waste an extra cons for each element just because your original question does not use dotted list but lists of proper lists.

These are the same and makes a list of two elements
Code: Select all
`(cons '+ (cons + '())) `(+ . (,+ . ()))`(+ ,+); ==> (+ #procedure:+)(car `(+ ,+)) ; ==> +(cadr `(+ ,+)) ; ==> #procedure:+`

The elements you ended up with saves one cons by storing the two values in car and cdr, a single pair:
Code: Select all
`(cons '+ +)`(+ . ,+); ==> (+ . #procedure:+)(car `(+ . ,+)) ; ==> +(cdr `(+ . ,+)) ; ==> #procedure:+`

Thus in your own procedure to use lists instead of dotted you would need to replace one cdr with a cadr. However if you don't you get a list of one procedure instead of a procedure.
I'm the author of two useless languages that uses BF as target machine.
Currently I'm planning a Scheme compiler :p
sylwester

Posts: 133
Joined: Mon Jul 11, 2011 2:53 pm

Re: problem with assoc

thanks a lot .. ya I feel like a dummy all good info thanks again