В F#: как получить список имен файлов в каталоге; ожидаемая единица имеет строку
Я только начинаю с F#, поэтому я решил попробовать несколько простых задач.
Здесь перечислены полные пути к файлам xml в каталоге:
System.IO.Directory.GetFiles("c:\\tmp", "*.xml")
|> Array.iter (printfn "%s")
Но я хочу только имена файлов, поэтому я попробовал:
System.IO.Directory.GetFiles("c:\\tmp", "*.xml")
|> Array.iter (System.IO.Path.GetFileName)
|> (printfn "%s")
Это не скомпилируется. Это дает ошибку:
Ожидалось, что это выражение будет иметь тип unit
но здесь есть строка типа
Я искал примеры, но ничего не смог найти. Я явно упускаю что-то простое и фундаментальное, но что?
1 ответ
Поскольку вы новичок, проще всего исправить ошибки, если подумать об утверждениях, подобных математическим утверждениям, которые могут быть построены из более простых функций, но которые также могут быть разбиты на части.
Таким образом, разбив вашу проблему на части, вы можете получить более мелкую ошибку, которую легче решить.
System.IO.Directory.GetFiles("c:\\tmp", "*.xml")
|> Array.iter (System.IO.Path.GetFileName)
|> (printfn "%s")
учитывается отдельно
let directoryArray = System.IO.Directory.GetFiles("c:\\tmp", "*.xml")
let nameArray = Array.iter (System.IO.Path.GetFileName) directoryArray
(printfn "%s") nameArray
теперь ошибки должны быть намного легче понять
Если мы посмотрим на подпись Array.iter
который iter : ('T -> unit) -> 'T [] -> unit
мы видим, что ему нужна функция ('T -> unit)
который принимает тип и возвращает unit
это означает, что ничего не вернуть, в этом случае печать будет работать, однако вы не хотите возвращать ничего, вы хотите преобразовать массив каталогов в массив имен файлов. Так Array.iter
не будет работать, и вам нужна функция Array, которая применяет функцию к каждому элементу в массиве и возвращает новый Array
, Array.map
Является ли это map : ('T -> 'U) -> 'T [] -> 'U []
Чтобы лучше понять функции Array и посмотреть, как они работают, можно добавить lambda function
,
Аналогично с (printfn "%s")
; можно добавить лямбда-функцию для передачи значения.
let directoryArray = System.IO.Directory.GetFiles("c:\\tmp", "*.xml")
let nameArray = Array.map (fun x -> (Path.GetFileName(x))) directoryArray
Array.iter (fun x -> printfn "%s" x) nameArray
Теперь мы можем упростить утверждения, используя |>
System.IO.Directory.GetFiles("c:\\tmp", "*.xml")
|> Array.map (fun x -> (Path.GetFileName(x)))
|> Array.iter (fun x -> printfn "%s" x)
и снова упростить, удалив lambdas
open System.IO
Directory.GetFiles("c:\\tmp", "*.xml")
|> Array.map Path.GetFileName
|> Array.iter (printfn "%s")