Page **1** of **1**

### problem with assoc

Posted: **Mon May 23, 2016 9:57 pm**

by **MadMuppet006**

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?

### Re: problem with assoc

Posted: **Tue May 24, 2016 12:48 pm**

by **David Mullen**

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.

### Re: problem with assoc

Posted: **Tue May 24, 2016 5:01 pm**

by **sylwester**

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^)))
```

### Re: problem with assoc

Posted: **Wed May 25, 2016 4:13 am**

by **MadMuppet006**

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.

### Re: problem with assoc

Posted: **Thu May 26, 2016 8:05 am**

by **sylwester**

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
```

### Re: problem with assoc

Posted: **Sat May 28, 2016 5:17 am**

by **MadMuppet006**

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

### Re: problem with assoc

Posted: **Tue May 31, 2016 2:57 pm**

by **sylwester**

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.

### Re: problem with assoc

Posted: **Sun Jun 05, 2016 12:16 am**

by **MadMuppet006**

thanks a lot .. ya I feel like a dummy

all good info thanks again