problem with assoc

Discussion of Scheme and Racket
Post Reply
MadMuppet006
Posts: 11
Joined: Wed Nov 02, 2011 11:56 pm

problem with assoc

Post by MadMuppet006 » Mon May 23, 2016 9:57 pm

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?

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

Re: problem with assoc

Post by David Mullen » Tue May 24, 2016 12:48 pm

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.

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

Re: problem with assoc

Post by sylwester » Tue May 24, 2016 5:01 pm

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

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

Re: problem with assoc

Post by MadMuppet006 » Wed May 25, 2016 4:13 am

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.

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

Re: problem with assoc

Post by sylwester » Thu May 26, 2016 8:05 am

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

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

Re: problem with assoc

Post by MadMuppet006 » Sat May 28, 2016 5:17 am

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

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

Re: problem with assoc

Post by sylwester » Tue May 31, 2016 2:57 pm

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

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

Re: problem with assoc

Post by MadMuppet006 » Sun Jun 05, 2016 12:16 am

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

Post Reply