Как мне завершить функцию в F # - PullRequest
0 голосов
/ 29 апреля 2018
let Trans(DirPath:string) =
    if ( numOfVmFiles(DirPath) > 1) then //if there are more than 1 vm files in the directory
            Init("")
    let VmFiles = ListOfVmFiles(DirPath)
    for VmFile in VmFiles do // for each vm file
            ReadFile(VmFile)

Я получил эту ошибку: Блок ошибок после этого 'let' является незавершенным. Ожидайте выражения. что мне написать? thznk u

Ответы [ 3 ]

0 голосов
/ 29 апреля 2018

В F # функция возвращает значение последнего вычисленного выражения. В вашем конкретном случае он возвращает единицу (), потому что цикл for возвращает единицу, если только значения его тела yield s (в этом случае вам нужно будет обернуть его в seq). Как уже упоминалось в комментариях, этот код анализируется нормально - ваша проблема с незаконченным выражением в другом месте вашего кода.

Переписанный Девоном Бериссом хороший пример лучших практик:

  • Явно объявите возвращаемое значение вашей функции в подписи.
  • ignore функция возвращает значения, если функция вызывается только для побочных эффектов (например, readFile и init("")).
  • Предпочитают функциональное поведение, такое как map, над императивами, такими как для .. do.

Кроме того, столь сильная зависимость от побочных эффектов может вызвать трудности в других местах. Более распространенная практика с перехватом данных - это иметь такую ​​функцию, как readFile, возвращать содержимое файла как seq и направлять результат в последующую обработку:

List.map readFile vmFiles
|> seq.Concat // concatenate the file outputs
|> processContents

Правильно ли это для вас, зависит от того, что именно вы собираетесь делать с содержимым каждого файла.

0 голосов
/ 30 апреля 2018

Существующие ответы дают вам хорошие советы о том, как лучше написать ваш код. Вы сказали, что получаете сообщение об ошибке:

Блок, следующий за этим 'let', незакончен. Ожидайте выражения.

Как правило, это указывает на отсутствие = или неправильный отступ после завершения вашей функции (или некоторую простую синтаксическую ошибку, подобную этой). В размещенном вами фрагменте весь синтаксис выглядит хорошо для меня, поэтому я подозреваю, что что-то не так и в другом месте. Следующее не дает ошибок:

let numOfVmFiles a = 0
let Init a = ()
let ListOfVmFiles a = []
let ReadFile a = ()

let Trans(DirPath:string) =
    if ( numOfVmFiles(DirPath) > 1) then 
            Init("")
    let VmFiles = ListOfVmFiles(DirPath)
    for VmFile in VmFiles do // for each vm file
            ReadFile(VmFile)

Вы получаете два предупреждения - потому что имена переменных должны быть camelCase, а не PascalCase, но без ошибок. Как говорили другие, вы, вероятно, должны заставить Init и ReadFile возвращать что-то, а затем вам нужно собрать результаты (чтобы сделать ваш код более функциональным), но это отдельная проблема.

0 голосов
/ 29 апреля 2018

Проблема в том, что функция не возвращает значение. Функции всегда должны возвращать значение. Если возвращать нечего, верните unit. Вы можете вернуть единицу как ().

Я сделал здесь несколько неправильных предположений, но попытался уточнить, что это были. В функции trans я также показываю, как вы можете указать тип возвращаемого значения. Обычно лучше позволить компилятору выводить тип, пока он не сможет. Наведите указатель мыши на функции и посмотрите, что компилятор говорит вам о типах. string -> int -> string list означает, что функция принимает строку и целое число и возвращает список строк.

let init dirName = () //unit is returned... kind of like void but is actually a return value
let listOfVmFiles dirName = ["some";"files"] // list of string
let readFile path = "content of file" //string

let trans(dirPath:string) : string list = // takes a string and returns a list of string represented as string-> string list
    let vmFiles = listOfVmFiles(dirPath) // get files from path
    if(vmFiles.Length > 1) then init("") // init if more than 1 file
    List.map readFile vmFiles // return a list of the content of the files

Если функция выполняет побочный эффект и ничего не возвращает, то это можно сделать так:

let trans(dirPath:string) : unit =
    let vmFiles = listOfVmFiles(dirPath)
    if(vmFiles.Length > 1) then init("")
    List.map readFile vmFiles |> ignore //ignore the result
    ()

При этом игнорируется результат сопоставления функции readFile со списком, а затем возвращается unit с использованием ().

Я рекомендую fsharp для развлечения и прибыли для изучения fsharp. Надеюсь, что это помогает и удачи. Хотя синтаксис кажется странным изначально придерживаться его. Это здорово!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...