The fundamental problem is with:
(putp NIL word-dict (car partsVar))
When putp
is called, nil
is bound to symbol
, word-dict
is bound to ht
, and (car partsVar)
, i.e. the next symbol in the list of parts of speech, is bound to value
. Within putp
the expression:
(setf (gethash symbol ht) value)
becomes:
(setf (gethash 'nil word-dict) (car partsVar))
Here, (gethash 'nil word-dict)
is the place that is set to the value (car partsVar)
. Since there is no 'nil
key in the hash table yet, a new key is created and given the value (car partsVar)
, which is 'verb
in the OP example.
In the original putp
expression, (car partsVal)
should have been in the symbol
position as that is the key which should be updated:
(defun resetPartsOfSpeech (word-dict &rest parts)
(do ((partsVar parts (cdr partsVar)))
((null partsVar) t)
(putp (car partsVar) word-dict 'nil)))
Although this solves the problem, there is a better solution.
(defun reset-parts-of-speech (word-dict &rest parts)
(dolist (part parts)
(putp part word-dict 'nil)))
When you want to do a simple iteration over a list of elements, symbols for parts of speech in this case, just use a simple dolist
. Additionally, it would be good to get into better habits with respect to Lisp style. Prefer kebab-case to camel-case; put all closing parentheses on one line (almost always); use proper indentation to make program structure clear. A good lisp-aware text editor can be most helpful for the last two.
Here is some testing in the REPL using a set-isa
function based on the previous question by OP:
SCRATCH> (defvar *word-dict* (make-hash-table))
*WORD-DICT*
SCRATCH> (set-isa 'verb 'eat 'sleep 'walk)
NIL
SCRATCH> (set-isa 'noun 'cake 'ice-cream 'pizza)
NIL
SCRATCH> (gethash 'verb *word-dict*)
(WALK SLEEP EAT)
T
SCRATCH> (gethash 'noun *word-dict*)
(PIZZA ICE-CREAM CAKE)
T
SCRATCH> (set-isa 'adjective 'delicious 'sweet 'crispy)
NIL
SCRATCH> (gethash 'adjective *word-dict*)
(CRISPY SWEET DELICIOUS)
T
SCRATCH> (resetPartsOfSpeech *word-dict* 'verb)
T
SCRATCH> (gethash 'verb *word-dict*)
NIL
T
SCRATCH> (gethash 'noun *word-dict*)
(PIZZA ICE-CREAM CAKE)
T
SCRATCH> (reset-parts-of-speech *word-dict* 'adjective 'noun)
NIL
SCRATCH> (gethash 'noun *word-dict*)
NIL
T
SCRATCH> (gethash 'adjective *word-dict*)
NIL
T
Update
The above was predicated on OP statement: "This function resets the value for each of the specified parts of speech to NIL...," which seemed to suggest that OP wants the hash table to store parts of speech as keys and lists of words as the associated values. This also seems to align with a previous question posted by OP. But, after an exchange of comments, it seems that OP may prefer a hash table with individual words as keys and parts of speech as the associated values. It is unclear how words which may be associated with multiple parts of speech should be handled.
The hash table shown in OP example code #S(HASH-TABLE :TEST FASTHASH-EQL (NIL . VERB) (LICKED . VERB) ;...,
along with OP comments, supports this second interpretation. If this is the case, then what does it mean to "reset each value" in the hash table to 'nil
? Perhaps the sensible thing to do is to remove each entry entirely which has a value that matches a provided part-of-speech argument.
This can easily be accomplished by using dolist
to loop over the list of parts of speech, and subsequently mapping over the hash table with maphash
and a function that removes any entry holding a matching value:
(defun remove-parts-of-speech (word-dict &rest parts)
(dolist (part parts)
(maphash #'(lambda (k v) (if (eql v part) (remhash k word-dict)))
word-dict)))
Here is another REPL demonstration using OP's current set-isa
function which populates a hash table with words for keys and parts of speech for values. After populating the hash table with nine words which are 'noun
s, 'verb
s, and 'adjectives
, the remove-parts-of-speech
function is used to remove all entries which are nouns or verbs from *word-dict*
. After this, only the three adjective entries remain in the hash table.
CL-USER> (defvar *word-dict* (make-hash-table))
*WORD-DICT*
CL-USER> (set-isa 'verb 'run 'jump 'climb)
RUN
JUMP
CLIMB
T
CL-USER> (set-isa 'noun 'hat 'shoe 'scarf)
HAT
SHOE
SCARF
T
CL-USER> (set-isa 'adjective 'salty 'spicy 'sour)
SALTY
SPICY
SOUR
T
CL-USER> *word-dict*
#<HASH-TABLE :TEST EQL :COUNT 9 {1003CE10C3}>
CL-USER> (hash-table-count *word-dict*)
9
CL-USER> (remove-parts-of-speech *word-dict* 'noun 'verb)
NIL
CL-USER> (hash-table-count *word-dict*)
3
CL-USER> (gethash 'spicy *word-dict*)
ADJECTIVE
T