newLISP: изменение списка ассоциаций
У меня проблема с изменением записей в списке ассоциаций. Когда я запускаю этот код
Пример А
(set 'Dict '(("foo" "bar")))
(letn (key "foo"
entry (assoc key Dict))
(setf (assoc key Dict) (list key "new value")))
(println Dict)
результат:
(("foo" "new value")) ; OK
что ожидается. С этим кодом
Пример Б
(set 'Dict '(("foo" "bar")))
(letn (key "foo"
entry (assoc key Dict))
(setf entry (list key "new value"))) ; the only change is here
(println Dict)
результат:
(("foo" "bar")) ; huh?
Почему Dict
не обновляется во втором случае?
редактировать
Я хочу проверить, есть ли запись в Dict
и если это так - обновите его, в противном случае оставьте его в покое. С letn
Я хочу избежать дублирования кода
(letn (key "foo"
entry (assoc key Dict))
(if entry ; update only if the entry is there
(setf entry (list key "new value")))
2 ответа
Решение
В выражении letn запись переменной содержит копию ассоциации, а не ссылку. Установите связь напрямую, как показано в примере Cormullion:
(setf (assoc key Dict) (list key "new value"))
В новой модели программирования LISP на все можно ссылаться только один раз. Назначение всегда делает копию.
Я понимаю, что списки ассоциаций таковы:
> (set 'data '((apples 123) (bananas 123 45) (pears 7)))
((apples 123) (bananas 123 45) (pears 7))
> (assoc 'pears data)
(pears 7)
> (setf (assoc 'pears data) '(pears 8))
(pears 8)
> data
((apples 123) (bananas 123 45) (pears 8))
> (assoc 'pears data)
(pears 8)
>
Если вы хотите проверить наличие ключа и обновить его значение, сделайте что-то вроде этого:
(letn (key "foo")
(if (lookup key Dict)
(setf (assoc key Dict) (list key "new value"))))