Как в Lisp'e с идеологической и практической точки зрения заполнять массив ? Как быстрее всего (по времени) эффективней ? Циклы понятно - но это как-то не по-Lisp'овски. Если можно пример. Например a(i) = sin(i) - Цикл по i.
все что написаное ниже, чисты бред пришедший мне в голову тока-что.
1) в лиспе есть массивы как таковые ваобше ?
2) в принцепе массив является часным случаем функции от одного аргумента.
3) заполнять если не циклами то рекурсивно, по другому помоему никак.
4) и ваобше нафига вам массив в лиспе, если идти из теории программирования, то там говорится что-то подобное несовместимости массивов и списков, всмысле юзать их вместе не есть гуд. а лисповская программа один большой список.
> 1) в лиспе есть массивы как таковые ваобше ?
make-array ?
> 2) в принцепе массив является часным случаем функции от одного аргумента.
????
3) и 4)
Вот примерчик бы.
Можно поиграться с параметром :initial-contents или с make-into.
Но цикл IMHO проще и нагляднее. И вполне в духе CL с его LOOP'ом.
(defparameter a (make-array 10))
(dotimes (i (length a))
(setf (aref a i) (sin i)))
ЗЫ: Я не труЪ лиспер. :)
массивы нужны как упорядоченные наборы с доступом к произвольному
элементу за время О(1). Т.е. для построения прог без них
теоретически вполне можно обойтись, но с ними в некоторых
редких случаях прога пишется легче и работает намного быстрее.
Циклы - вполне кошерный и адекватный инструмент, будучи
применяемы корректно. Например для инициализации массива.
Рекурсивный же способ например таков:
(defun fill-array (a &optional (n 0))
(when (array-in-bounds-p a n)
(setf (aref a n) (sin n))
(fill-array a (incf n))))
(defparameter a (make-array 10))
(fill-array a)
Им можно пользоваться при желании но я не вижу никаких преимуществ
перед dotimes в данном случае. Варианты с :initial-contents и map
требуют чтобы значения, назначаемые элементам массива, были все
уже вычислены на момент операции, а не вычислялись по ходу
присвоения каждому элементу, так что это не всегда приемлемо.
Обработка полноценных массивов (допускающих запись и чтение значений) это всегда циклы в том или ином виде. Все остальные решения - syntactic sugar, который маскирует в себе цикл, с целью уберечь несформировавшуюся психику от жестокой правды жизни
Вот всё-таки со списками не выходит. Пытаюсь так:
(setf s (list 1))
(setf s (append s 1))
Первый раз проходит (1 . 1) получаю. А дальш е - ошибка. Что не так ?
append хавает на вход два списка, а ты ей подсовываешь список s и атомарное значение 1
надо так
(setf s (list 1))
(setf s (append s (list 1))
Cобственно глюки динамической типизации :)
А то что получается у тебя после первого выполнения кода не спиок, а пара значений, есть такой тип данных в лиспе, на ее основе строятся списки. Почитай про организацию списков в лиспе. Сразу поймешь
Можно еще использовать iterate:
CL-USER> (require :iterate)
CL-USER> (use-package :iterate)
CL-USER> (iter (for i from 1 to 5)
(collect (sin i) result-type simple-vector))
#(0.84147096 0.9092974 0.14112 -0.7568025 -0.9589243)
> append хавает на вход два списка, а ты ей подсовываешь
> список s и атомарное значение 1
Нет, append appendид:
[1]> (setq s nil)
NIL
[2]> (setq s (append (list 1 2 3) s nil))
(1 2 3)
[3]> (setq s (append (list 4 5 6) s nil))
(4 5 6 1 2 3)
списки, а не точечные пары, в лиспе оканчиваются на nil.