This is a read-only archive of lispforum.com. The forum was locked to new users and posts and is preserved here as static HTML from a database snapshot taken on 2019-09-07.

setq and assoc problem

6 posts · 6572 views

Hello all,

As newbie in Lisp, I'm faced off at an issue linked to the assoc function.
Hereafter, the 2 parts of code involved in my issue:
 (setq values '((x . 100) (y . 200) (z . 50)))
 (assoc 'y values)
This code is working without any problem (the code is an example extracted from the assoc http://www.lispworks.com/documentation/ ... .htm#assoc)
 (setq FrAng '(((poisson) fish) ((chat) cat) ((chien) dog)))
 (assoc 'chat FrAng)
But this code is not working and I don't know why, I'm expected to have the 'cat' answer.
Could you please tell me where is located my mistake or give me a clue in order to fix it?
Is the keyword case-sensitivity like CHAT different to chat?
What is the difference between these 2 types of declaration?

By advance, thanks for your help. I assume my problem is obvious for people who know lisp and I'm sorry to bother lisp expert. :?

Re: setq and assoc problem

The two lists are structurally different. The keys, in the latter example, are themselves lists. So you'd need to use a different test function in order to compare the keys effectively:
(assoc '(chat) FrAng :test 'equal)

Re: setq and assoc problem

First some philosophical points:
  • I always use hash-tables instead of ASSOC for this kind of mapping, technically ASSOC can be faster performing for small tables, but for larger tables GETHASH is faster, and if your program is being held back by the performance of this kind of mapping there are other ways to solve it.
  • I consider using SETQ at toplevel to create "global" variables evil (as compared to using DEFVAR or DEFPARAMETER), and I'm not alone, sbcl will complain if you do it.
  • By default (for historical reasons that made sense in the days before colour monitors, yes, it's that old!) the reader upcases all symbols before interning them, which means that the names frang frAng and FRANG will all refer to the same symbol, which would mean that if you THOUGHT you had a separate variable using one of the other spellings then you just clobbered it with that SETQ.
I would have written your code like so:
(setq fr-ang '((poisson . fish) (chat .  cat) (chien . dog)))                                 
(assoc 'chat fr-ang)
  • (The reason your code didn't work) Your literal was badly formed for ASSOC: you had an extra set of parens around the form, and you had extras around each of the items you wished to lookup. Some people call lisp Lots of Irritating Silly Parentheses, but the numbers ALWAYS matter, you can't use too many or too few.
  • I changed the literal to use dotted-pairs (which lets you use CDR instead of SECOND to get the associated value out of the result of ASSOC, and uses less memory)

Re: setq and assoc problem

pjstirling wrote:...
I consider using SETQ at toplevel to create "global" variables evil (as compared to using DEFVAR or DEFPARAMETER), and I'm not alone, sbcl will complain if you do it.
...
Many implementations won't complain before you actually try to compile it. The implementations are free to choose how it should be treated but most will interpret it as if it was declared special. That means `setq` and `defparameter` are interchangable in those implementations except for the warnings.
(setq name-without-earmuffs 0)
(defun increase (&optional (step 1))
  (setq name-without-earmuffs (+ step name-without-earmuffs)))
I save this as test.cl. Now lets see what happens in CLISP:
(load "test.cl") ; no errors
(increase) ; 1

(compile 'increase) ; lots of warnings
; WARNING: in INCREASE : NAME-WITHOUT-EARMUFFS is neither declared nor bound,
;          it will be treated as if it were declared SPECIAL.

(compile-file "test.cl") ; lots of warnings
;; Compiling file test.cl ...
;WARNING: in #:|1 1 (SETQ NAME-WITHOUT-EARMUFFS 10)-1| in line 1 : NAME-WITHOUT-EARMUFFS is neither declared nor bound,
;         it will be treated as if it were declared SPECIAL.
;WARNING: in INCREASE in lines 2..3 : NAME-WITHOUT-EARMUFFS is neither declared nor bound,
;         it will be treated as if it were declared SPECIAL.
;WARNING: in INCREASE in lines 2..3 : NAME-WITHOUT-EARMUFFS is neither declared nor bound,
;         it will be treated as if it were declared SPECIAL.
;; Wrote file test.fas
;The following special variables were not defined:
; NAME-WITHOUT-EARMUFFS
;0 errors, 3 warnings
Just adding one line to the top of the file and perhaps adhering to the naming convention and you don't get these:
;; the two lines below can be replaced with one defparameter
(declaim (special *name-with-earmuffs*))
(setq *name-with-earmuffs* 0)

(defun increase (&optional (step 1))
  (setq *name-with-earmuffs* (+ step *name-with-earmuffs*)))
Now, since it's special it's obvious you know they're not lexical and thus the warnings don't show up.
However in my example where we are counting number of applications it might be better to use defvar since consecutive loading don't reset the value.
I'm the author of two useless languages that uses BF as target machine.
Currently I'm planning a Scheme compiler :p

Re: setq and assoc problem

Hello all,
Thanks for your help.
One thing which is very disturbing for me it that compare to C language, a function is not typed like void main(int argc, char* argv[]).
Thus, how do you understand a program which is only written without comment.
How do you debug it?
For the debugging part, I'm calling each routine with some data and check if its behavior is the one expected.

Thanks for your help one more time.

Re: setq and assoc problem

Generally if I expect a function to have problems with parameters with the wrong types I include some `(UNLESS (TYPEP param expected-type) (ERROR useful-error-message))` Between that, proper function and parameter naming, and if-all-else-fails docstrings it tends not to be a problem, and it's a much better experience programming than C++ where (even with auto) you must specify types redundantly.