LINUX.ORG.RU

Инкрементирование всех элементов в списке

 , ,


0

1

Написал так:
(mapcar 'incf '(1 2 3))
Интерпретатор выдал, что функция incf не объявлена.
Но если обернуть incf в lambda, то все нормально.
Почему так?

★★★★★

Последнее исправление: deterok (всего исправлений: 2)
Ответ на: комментарий от theNamelessOne

Понял, спасибо, никак не могу привыкнуть, что имена функций так можно коверкать.(1+)

deterok ★★★★★
() автор топика

Вариант с mapcar подходит если тебе нужен новый список с изменёнными элементами.

А если действительно нужно изменить элементы в существующем списке, то

(defvar *a* (list 1 2 3))

(loop :for i :on *a* :do (incf (car i)))

*a* => (2 3 4)
monk ★★★★★
()
Ответ на: комментарий от anonymous

мне нравится «fmakunbound», вся такая интуитивная

С учётом того, что то, что она отвязывает называется fdefinition, то вполне очевидно. Хотя, как и в сишном creat, очень хочется добавить букву e.

monk ★★★★★
()
Ответ на: комментарий от monk

Спасибо, есть еще один вопросик:
Есть ассоциативный список основанный на точечных парах.
Мне нужно локальной переменной присвоить указатель на cdr одной из точечных пар(по сути некое число) для дальнейшего изменения списка.
(При обычном использование let происходит копирование числа)
Как это правильно сделать?

deterok ★★★★★
() автор топика

Есть еще деструктивный map-into. По идее он может работать без consing.

CL-USER 1 > (setf x (list 1 2 3))
(1 2 3)

CL-USER 2 > (map-into x #'1+ x)
(2 3 4)

CL-USER 3 > x
(2 3 4)
dave ★★★★★
()
Ответ на: комментарий от deterok

Если ты имеешь в виду под «ассоциативным списком, основанным на точечных парах» обыкновенный alist, то для него есть стандартная функция assoc, которая возвращает точечную пару. Через нее можно менять ячейку cdr. В общем, вместо указателя использовать ячейку cons.

dave ★★★★★
()
Последнее исправление: dave (всего исправлений: 1)
Ответ на: комментарий от dave

Я так его и получаю, но при присвоение его переменной в let происходит копирование. Предлагаете обернуть в ячейку?

deterok ★★★★★
() автор топика
Ответ на: комментарий от deterok

Не понятен вопрос. Setf - это совершенно особый макрос в лиспе. Он имеет несколько способов настройки. Есть совершенно хардкордный, когда залезаешь в потроха кодогенерации. За исключением тривиального случая (setq), макрос идет в связке с некоторым символом. Конструкцию "(setf (cdr x) y)" следует воспринимать как одно целое.

dave ★★★★★
()
Последнее исправление: dave (всего исправлений: 2)
Ответ на: комментарий от deterok

cdr вести в присвоение i

Если тебе нужна ссылка, то нельзя. В целом можно считать cons структурой с двумя полями, которая передаётся по ссылке. А если ты напишешь (let ((i ...)) (setf i ...)), то меняться будет только переменная i, а не её содержимое (чего ты ожидаешь от ссылки).

присвоить указатель на cdr одной из точечных пар(по сути некое число)

Указателем является сама пара. А если ты к ней применишь cdr, то получишь просто число (которое уже не указатель).

monk ★★★★★
()
Ответ на: комментарий от deterok

как-нибудь и cdr

Если просто вопрос эстетики, а не производительности, то

(symbol-macrolet ((i (cdr (assoc 'a x))))
  (setf i (* i 3))) ;; будет изменять соответствующую ячейку
monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от monk

Быстро и красиво как-то так


(let ((pair (assoc 'a x))) ;; ссылка на пару
  (sumbol-macrolet ((i (cdr pair)))
     (setf i (* i i i)))) ; каждое обращение к i теперь O(1), а не O(n), как было бы если не выносить assoc
monk ★★★★★
()
Ответ на: комментарий от monk

Спасибо за разъяснение. Этого мне хватит.

deterok ★★★★★
() автор топика

Задача: инкрементировать все элементы в списке
Программист: (решение в одну строчку)
Лиспер: mapcar, incf, lambda, fmakunbound, defvar, list, loop, maplist, car, cdr, caar, cddr, cadr, cdddr, fdefinition, dotted pairs, setf, map-into, alist, assoc, let, symbol-macrolet...

anonymous
()
Ответ на: комментарий от dave

Да я и не обращаю. Так, на всякий случай, решил показать результат обсуждения.

deterok ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.