Code for calculating difference of sets not working

You have problems, and we're glad to hear them. Explain the problem, what you have tried, and where you got stuck.
Feel free to share a little info on yourself and the course.
Forum rules
Please respect your teacher's guidelines. Homework is a learning tool. If we just post answers, we aren't actually helping. When you post questions, be sure to show what you have tried or what you don't understand.
Post Reply
kiwifreak3
Posts: 5
Joined: Sat Jun 09, 2012 8:23 am

Code for calculating difference of sets not working

Post by kiwifreak3 » Sat Jun 09, 2012 8:42 am

Hi everyone,
I'm trying to write a program (in emacslisp) to calculate the difference of two lists; could someone give me a hint as to why my code is returning an error saying "invalid function...", when I try it on an example?
I'd be grateful for help,
Thanks

Code: Select all

(defun diff (A B)
; calculates A\B
(setq index 0)
(if (or (equal A []) (equal B []))
    (print A)
(; else:
(while (< index (length A))
(
(if (string-equal (elt A index) (car B))
    ((aset A index (elt A 0)) (setq A (cdr A)))
)
(setq index (+ index 1))
)
)
(diff (A (cdr B)))
)
)
)
(diff [1 a c 5] [1 3 "foo" 4 7])

ramarren
Posts: 613
Joined: Sun Jun 29, 2008 4:02 am
Location: Warsaw, Poland
Contact:

Re: Code for calculating difference of sets not working

Post by ramarren » Sun Jun 10, 2012 12:06 am

In Lisp all parentheses are usually meaningful, they are not just grouping/block delimiters. In your case you have superfluous parentheses around the else branch of IF and around the body of WHILE. This makes the system interpret those as function calls, and an entire expression does not name a function.

Additionally even with this fixed your code will not work. In EmacsLisp arrays and lists are different types, and CAR and CDR will not work on the former. Also you shouldn't just SETQ variables. Establish variables with LET.

kiwifreak3
Posts: 5
Joined: Sat Jun 09, 2012 8:23 am

Re: Code for calculating difference of sets not working

Post by kiwifreak3 » Sun Jun 10, 2012 2:04 am

Thanks a lot Ramarren, you really helped me out there... I see I made quite some mistakes; I think I've got rid of them now although I'm still using the setq command within the while-loop, because I can't quite figure out where I should put the end-bracket of let otherwise (- perhaps after the end-bracket of the while-loop?)
perhaps someone could look at my new code; I think I'm nearly there - it's just returning nil instead of A\B...
I'd be grateful!

Code: Select all

(defun diff (A B)
; calculates A\B
(if (or (equal 0 (length A)) (equal 0 (length B)))
   A
; else:
(let ((index 0))
(while (< index (length A))
(if (equal (elt A index) (car B))
    (aset A index (elt A 0)) (setq A (cdr A))
)
(setq index (+ 1 index))
)
)
(diff A (cdr B))
)
)
(diff '(a b c d e) '(d e f g h))

ramarren
Posts: 613
Joined: Sun Jun 29, 2008 4:02 am
Location: Warsaw, Poland
Contact:

Re: Code for calculating difference of sets not working

Post by ramarren » Sun Jun 10, 2012 5:17 am

kiwifreak3 wrote:I think I've got rid of them now although I'm still using the setq command within the while-loop, because I can't quite figure out where I should put the end-bracket of let otherwise
Sorry, I misspoke, you shouldn't create variables with SETQ, because they will be set as global variables and leak out of your function, and it also risks changing a variable with the same name which belongs to a surrounding context. Inside a LET which establishes your own context for the variable using SETQ is fine.

You are trying to use both iteration and recursion, and modifying the list at the same time. This seems overly complicated. I suggest using a nested iteration and an accumulator variable. That is, use LET to initialize a variable to NIL, and then PUSH on it. To decide what to push use a loop over A. To check if an element of A is in B use MEMBER or implement an equivalent if you can only use primitives. Don't forget to return you accumulator (possibly REVERSE'd, if order seems important) and the end of the function.

Rather than using index and ELT to loop over lists you should probably either use DOLIST or at least a (while list-variable ... (setq list-variable (cdr list-variable))). Note that in EmacsLisp empty list is false, and so can be used as a termination condition.

kiwifreak3
Posts: 5
Joined: Sat Jun 09, 2012 8:23 am

Re: Code for calculating difference of sets not working

Post by kiwifreak3 » Sun Jun 10, 2012 6:23 am

Tanks so much, that realy is so much more simple than my version...

Code: Select all

; calculates A\B
(let (C)
  (dolist (element A)
    (if (not (member element B))
	(push element C)
    )
  )
C
)
)
(diff '(a b a c d) '(c d e d e f))

Post Reply