Основная проблема связана с:
(putp NIL word-dict (car partsVar))
Когда вызывается putp
, nil
связан с symbol
, word-dict
связан с ht
и (car partsVar)
, т. е. следующий символ в списке частей речи связан с value
. В пределах putp
выражение:
(setf (gethash symbol ht) value)
становится:
(setf (gethash 'nil word-dict) (car partsVar))
Здесь (gethash 'nil word-dict)
является местом , для которого установлено значение (car partsVar)
, Поскольку в таблице ha sh нет ключа 'nil
, создается новый ключ, которому присваивается значение (car partsVar)
, которое в примере OP равно 'verb
.
В оригинале putp
выражение, (car partsVal)
должно быть в позиции symbol
, поскольку это ключ, который необходимо обновить:
(defun resetPartsOfSpeech (word-dict &rest parts)
(do ((partsVar parts (cdr partsVar)))
((null partsVar) t)
(putp (car partsVar) word-dict 'nil)))
Хотя это решает проблему, есть лучшее решение.
(defun reset-parts-of-speech (word-dict &rest parts)
(dolist (part parts)
(putp part word-dict 'nil)))
Если вы хотите сделать простую итерацию по списку элементов, символов для частей речи в этом случае, просто используйте простой dolist
. Кроме того, было бы хорошо получить лучшие привычки в отношении стиля Lisp. Предпочитаю кебаб-кейс верблюжьему; поместите все закрывающие скобки в одну строку (почти всегда); используйте правильные отступы, чтобы сделать структуру программы понятной. Хороший текстовый редактор с поддержкой lisp может быть наиболее полезным для последних двух.
Вот несколько тестов в REPL с использованием функции set-isa
, основанной на предыдущего вопроса от 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
Обновление
Выражение выше было основано на операторе OP: " Эта функция сбрасывает значение для каждой из указанных частей речи в NIL ...,", что, по-видимому, указывает на то, что OP хочет, чтобы таблица ha sh сохраняла части речи в виде ключей, а списки слов - в качестве связанных значений. Это также похоже на предыдущий вопрос , опубликованный OP . Но после обмена комментариями кажется, что OP может предпочесть таблицу ha sh с отдельными словами в качестве ключей и частями речи в качестве связанных значений. Неясно, как следует обрабатывать слова, которые могут быть связаны с несколькими частями речи.
Таблица ha sh, показанная в примере кода OP #S(HASH-TABLE :TEST FASTHASH-EQL (NIL . VERB) (LICKED . VERB) ;...,
вместе с комментариями OP, поддерживает эту вторую интерпретацию. Если это так, то что означает «сбросить каждое значение» в таблице ha sh на 'nil
? Возможно, разумно было бы полностью удалить каждую запись, значение которой соответствует указанному аргументу части речи.
Это можно легко сделать, используя от dolist
до l oop поверх список частей речи и последующее сопоставление таблицы ha sh с maphash
и функцией, которая удаляет любую запись, содержащую совпадающее значение:
(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)))
Вот еще одна демонстрация REPL с использованием тока OP set-isa
функция, которая заполняет таблицу ha sh словами для ключей и частями речи для значений. После заполнения таблицы ha sh девятью словами 'noun
s, 'verb
s и 'adjectives
, функция remove-parts-of-speech
используется для удаления всех записей, которые являются существительными или глаголами из *word-dict*
. После этого в таблице ha sh остаются только три прилагательных.
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