1
votes

This function resets the value for each of the specified parts of speech to NIL using putp. The first argument is a hashtable, for this example, lets call it word-dict.
There are a variable number of parts of speech passed to resetPartsOfSpeech.

Example: (resetPartsOfSpeech word-dict 'subject 'verb 'prep 'directObj)

(defun resetPartsOfSpeech(word-dict &rest parts)
(do ((partsVar parts (cdr partsVar)))
( (null partsVar) T)
;;; procces the car 
(putp NIL word-dict (car partsVar))
))

; here is the results of the function
#S(HASH-TABLE :TEST FASTHASH-EQL (NIL . VERB) (LICKED . VERB) (HAS . VERB) (ATE . VERB) (RAN . VERB) (TAUGHT . VERB)

As you see, it only adds the NIL variable to the list, not clearing them all out.

Helper Functions I Have, The job of these two functions is to put and get data from the hashtable created.

; creating the hash table
(setf word-dict (MAKE-HASH-TABLE))

(defun putp (symbol ht value)
(if (ATOM symbol)
    (setf (gethash symbol ht) value)
    (ERROR "~s is not a valid symbol for putp" symbol)
))

(defun getp (symbol ht)
 (gethash symbol ht) )

(defun isa(word partOfSpeech)      ; this function returns T if the specified word is that specified partOfSpeech,  
; otherwise, NIL is returned. 
(eql (getp word word-dict) partOfSpeech))

(defun set_isa (partOfSpeech &rest words)    ; this function defines each
word in the list of words to the specified partOfSpeech  

; in the dictionary (hard code word-dict). (do ((wordVar words (cdr wordVar)) ) ( (NULL wordVar ) T) ;;; proccess the CAR (putp (car wordVar) word-dict partOfSpeech) (print (car wordVar))))

What I am having trouble understanding is that how I should go about itterating thru each value in the hash table. What I was considering was doing a nested do or dolist loop but can't quite figure out how to go about that with the values from the table, or if that is even possible.

1
It would help, if you post your code formatted and indented. That would improve readability. Thanks!Rainer Joswig

1 Answers

4
votes

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 'nouns, 'verbs, 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