Как правильно читать эту функцию SML, которая использует foldl?
Я новичок в SML, и у меня возникают проблемы с пониманием того, что является аргументами и что передается внутренней функции в этом коде.
fun print_mat mat =
let
val _ = (Array.foldl (
fn (arr, _) =>
let val _ = (print_arr arr) in () end
) () mat)
in () end;
Который предназначен для использования в:
val mat =
Array.fromList[
(Array.fromList [0, 1, 1, 0, 1]),
(Array.fromList [1, 0, 1, 0, 0])
]
val _ print_mat mat
То, что я не вижу, как arr
выбирается из моего mat
и используется внутри функции закрытия.
1 ответ
foldl
делает что-то большее, чем применять fn (arr, _) => ...
к каждому элементу. Он накапливает результат, который в вашем случае отбрасывается с шаблоном подстановки, _
в пользу стоимости единицы, ()
, Итак, как указывает Андреас Россберг, вы на самом деле ничего не накапливаете и даже не генерируете никакого значения результата, поэтому Array.app
лучше подходит.
Чтобы понять, что
fun print_mat mat = Array.app print_arr mat
делает, вы можете посмотреть на его реализацию:
fun app f a =
let val a = from_array a
val stop = length_ a
fun lr j = if j < stop then (f(sub_ a j); lr (j+1))
else ()
in lr 0 end
Смысл, это вызывает f
(в твоем случае print_arr
) в 0-м ряду a
(в твоем случае mat
), затем в 1-м ряду, затем во 2-м, пока не появятся еще ряды. Когда строк больше нет, возвращаем ()
, Между тем, вы не сделали ничего лишнего, например, накопили какую-то ценность, так как она всегда будет ()
что вы вернетесь, когда все равно будет сделано.
Интересно, вы видели, что Array2 существует? Это должно быть довольно идеально для матриц.
Что касается понимания сворачивания, см. ML для работающего программиста, гл. 5: Функции и бесконечные данные.
Я рекомендую сначала разбираться в свертывании в контексте списка.
Это также то, что лучше всего освещено в учебном материале.