Так
(let loop ((p (- (length lst) 1)) (i 0) (l lst))
(cond
((= p 0)
lst)
((= i p)
(loop (+ p -1) 0 l))
((> (vector-ref (convert lst) i) (vector-ref (convert lst) p))
(loop (+ p 0) (+ i 1) (swap (convert l) i p)))
((< (vector-ref (convert lst) i) (vector-ref (convert lst) p))
(loop (+ p 0) (+ i 1) l)))
он вернет исходное состояние на (= p 0)
, когда я отправлю lst
из '#(3 2 1)
, но когда я запускаю функцию swap
отдельно, он вернет '#(1 2 3)
. p
- это последний массив, а i
- первый в массиве.
преобразовать только изменения в список в вектор и условие = p 0 завершит процесс
Ваши конверсии портят ваш результат. lst
никогда не изменялся, это то, что вы возвращаете. последний должен использовать else
вместо (> ...)
, поскольку, если он не больше, он равен или меньше. Не нужно это проверять. Я понятия не имею, что это должно делать, но очевидно, почему это не должно работать. Ваши проблемы не имеют ничего общего с именем let
.
Не могли бы вы привести минимальный полный пример, включая определения как convert
, так и swap
, а также значение lst
? Приведите пример, который можно запустить, не догадываясь. (см. MCVE)
Спасибо, Алекс, я понял, что постоянно передаю lst вместо l после того, как вы упомянули lst. Думаю, теперь это работает. Swap просто просто поменяйте местами две переменные, которые все, что он делает, и convert просто преобразует список-> вектор
Если ваша проблема решена, вы должны опубликовать ответ и принять его, чтобы этот вопрос больше не помечался как открытый.
Используйте l
вместо lst
, чтобы возвращалось значение окончательный, а не оригинал.
Вы начинаете с l = lst
и продвигаетесь в цикле, меняя l
на каждом шаге.
Когда вы достигнете последнего состояния, просто верните то, что вы построили, l
.
'#(3 2 1)
- это векторное обозначение. (list '#(3 2 1))
на входе должен возвращать (#(1 2 3))
Однако это не самое страшное. Перекрытие между списком и вектором несколько раз в одном и том же случае cond сигнализирует о том, что что-то не так. Вы тратите много времени и памяти, чтобы создать вектор, который используете только один. Я предлагаю преобразовать в вектор на входе и в список на выходе.
И можно было бы сделать несколько улучшений в обозначениях. Обычно функция lisp, которая преобразует типы, обозначается знаком «->» между типами. Итак, convert
должен быть (список-> вектор), и у вас должен быть соответствующий (вектор-> список). Одна функция не должна делать и то, и другое, по крайней мере, без явных аргументов, чтобы избежать неправильного типа данных.
Также swap
должен быть swap!
, поскольку он изменяет структуру данных на месте.
Также есть логическая ошибка. Если два элемента во входном списке равны, вы пропустите все свои предложения cond и вызовете исключение.
(let loop ((p (- (length lst) 1)) (i 0) (vec (list->vector l))
(cond
((= p 0)
(vector->list lst))
((= i p)
(loop (- p 1) 0 l))
((> (vector-ref vec i) (vector-ref vec p))
(loop p (+ i 1) (swap! vec i p)))
(else
(loop p (+ i 1) l)))
Значит, в случае, когда элементы равны
=
, то цикл завершен? Это как минимум кончится. Что делаетconvert
? Если аргумент является вектором, почему имя параметра указывает, что это список?