fun list n = List.tabulate (n, fn x => x + 1)
С простым аккумулятором,
val list =
let fun list' k 0 = k
| list' k n = list' (n::k) (n-1)
in list' nil end
Это строит список, начиная с хвоста. Если вы думаете о сокращениях,
list 5
=> list' nil 5
=> list' (5::nil) 4
=> list' (4::5::nil) 3
=> list' (3::4::5::nil) 2
=> list' (2::3::4::5::nil) 1
=> list' (1::2::3::4::5::nil) 0
=> [1, 2, 3, 4, 5]
С другой стороны,
Что-то заставляет меня думать, что мне нужна вспомогательная функция, которая создает неограниченные списки для использования в рекурсии, но я в замешательстве.
Представление неопределенного списка - это функция, которая принимает список и возвращает список: например, для представления 10::_
вы можете использовать fn x => 10::x
.
fun list n =
let fun list' m k = if m > n then k nil else
list' (m+1) (fn x => k (m::x))
in list' 1 (fn x => x) end
Еще раз, если вы думаете о сокращениях,
list 5
=> list' 1 (fn x => x)
=> list' 2 (fn x => (fn x => x) (1::x))
=> list' 3 (fn x => (fn x => (fn x => x) (1::x)) (2::x))
=> list' 4 (fn x => (fn x => (fn x => (fn x => x) (1::x)) (2::x)) (3::x))
=> list' 5 (fn x => (fn x => (fn x => (fn x => (fn x => x) (1::x)) (2::x)) (3::x)) (4::x))
=> list' 6 (fn x => (fn x => (fn x => (fn x => (fn x => (fn x => x) (1::x)) (2::x)) (3::x)) (4::x)) (5::x))
=> (fn x => (fn x => (fn x => (fn x => (fn x => (fn x => x) (1::x)) (2::x)) (3::x)) (4::x)) (5::x)) nil
=> (fn x => (fn x => (fn x => (fn x => (fn x => x) (1::x)) (2::x)) (3::x)) (4::x)) (5::nil)
=> (fn x => (fn x => (fn x => (fn x => x) (1::x)) (2::x)) (3::x)) (4::5::nil)
=> (fn x => (fn x => (fn x => x) (1::x)) (2::x)) (3::4::5::nil)
=> (fn x => (fn x => x) (1::x)) (2::3::4::5::nil)
=> (fn x => x) (1::2::3::4::5::nil)
=> [1, 2, 3, 4, 5]
В этом случае алгоритм может быть структурирован таким образом, что для аккумулятора достаточно обычной структуры данных, но использование продолжения в качестве аккумулятора является очень мощным и полезным методом, который не следует упускать из виду.