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"))))
Другие вопросы по тегам