Безопасной реализацией является следующее:
let rot1 l =
let rec aux acc = function
[] -> []
| [x] -> x :: List.rev acc
| x :: l -> aux (x :: acc) l
in
aux [] l
Безопасно в том смысле, что пропуск пустого списка возвращает пустой список, а не вызывает исключение. Обратите внимание, что я настоятельно не рекомендую использовать List.hd и List.tl, потому что они могут потерпеть неудачу, с общим сообщением об ошибке.
Кроме того, рекурсивный вызов aux является завершающим вызовом (последнее, что нужно сделать перед возвратом). Компиляторы OCaml обнаружат это и избежат увеличения стека при каждом вызове функции (и, возможно, вызовут исключение или сбой). Об этом следует знать при работе с длинными списками и рекурсивными функциями.
Для эффективного выполнения этой операции, т. Е. В O (1), а не в O (length), нельзя использовать обычный список. Вы можете использовать модуль Queue из стандартной библиотеки или реализации двухсвязных списков, предоставленных третьими лицами.
Вот пример использования модуля очереди:
let rotate_queue q =
if not (Queue.is_empty q) then
let x = Queue.take q in
Queue.add x q
# let q = Queue.create ();;
val q : '_a Queue.t = <abstr>
# Queue.add 1 q;;
- : unit = ()
# Queue.add 2 q;;
- : unit = ()
# Queue.add 3 q;;
- : unit = ()
# Queue.iter print_int q;;
123- : unit = ()
# rotate_queue q;;
- : unit = ()
# Queue.iter print_int q;;
231- : unit = ()
#