Питер Норвиг упоминает в Парадигмы программирования искусственного интеллекта, на стр. 50, компромисс между спецификой и согласованностью и при выборе использования setq или setf для обновления переменной до значения. Что вы порекомендуете? Вы когда-нибудь сталкивались с ситуацией, когда это имело большое значение для читаемости?
Lisp стиль: setq vs. setf
Ответ 1
Использование setq более низкоуровневое, но производительность setf не является проблемой. И setf позволяет вам (или библиотечным писателям) предоставлять настраиваемое поведение setf, например, настраивать части пользовательских структур данных. Я говорю: пойдите с setf везде, если у вас нет причин не делать этого.
Также см. Практический общий Lisp, глава 3: "Макрос SETF является общим оператором присваивания Lisp". PCL доступен онлайн бесплатно: http://gigamonkeys.com/book/
Ответ 2
FWIW, я всегда использую setf
. Если я немного изменил структуру своего кода, мне просто нужно изменить "место" вместо места и оператора (setq → setf).
Кроме того, не беспокойтесь о производительности, setf точно так же, как setq для символов:
CL-USER> (macroexpand '(setf foo 42))
(SETQ FOO 42)
Ответ 3
Вы можете использовать setf
везде, где вы могли бы использовать setq
. Фактически, setf
на самом деле является макросом, который строится на setq
. Таким образом, это должно быть чисто читаемостью и проблемой стиля.
Почти весь код, который я видел, позволяет избежать использования setq
и использует setf
.
Ответ 4
setf - это "заданное поле", оно меняет место и может иметь пользовательские расширения. setq устанавливается с цитированием первого аргумента.
Ответ 5
Я рекомендую вам следовать окончательному совету Норвига в этом разделе: быть последовательным. "Читаемость" - это, конечно, самая важная причина для выбора в программировании. Если важно сообщить читателю (возможно, вам через 2 месяца), что вы имеете дело со всей ячейкой значения символа, используйте setq
; в противном случае используйте setf
. Но только если вы согласны.
Ответ 6
Вы не ошибетесь, если используете setf везде вместо setq.
Это похоже на то, что перетаскивает Common Lisp из будущего, много неиспользуемого материала, который разработчики все равно должны поддерживать.