Почему эта функция F # запускается только один раз?Я звоню дважды, и он запускается только один раз - PullRequest
0 голосов
/ 31 мая 2018

Я написал следующий код для проверки кода MonteCarlo на языке F #.

Моя проблема в том, что я вижу случайные числа и «oi» только один раз в моей консоли.Я дважды вызываю функцию oneRun, но похоже, что она запускается только один раз.

Вот код:

let genRandomNumbers count =
    let rnd = System.Random()
    printf "oi "
    List.init count (fun _ -> rnd.NextDouble ())

let oneRun = 
   let numberofClicks = 0
   let randomNumber = genRandomNumbers 50
   let action numberofClicks random = if random <= 0.10 
                                          then numberofClicks+1
                                          else numberofClicks
   randomNumber |> Seq.iter (printf "%f ")
   randomNumber |> List.fold action numberofClicks

[<EntryPoint>]
let main argv = 
    let a = oneRun
    printf "%d " a
    let b = oneRun
    printf "%d " b
    let key_info = Console.ReadKey()
    0 // 

Есть подсказки?Идеи?

1 Ответ

0 голосов
/ 31 мая 2018

Чтобы немного расширить правильные комментарии Mankarse, синтаксис F # для определения значений и функций выглядит очень похоже, поэтому их легко спутать.

Это значение:

let sum = 42

Это функция:

let addThree x = x + 3

И значения, и функции могут иметь после них блоков , а не только отдельные строки:

let sumWithSideEffects =
    // This will only be evaluated once
    printfn "Side effect happens here"
    42

let addThree x =
    // This will run every time you call the function
    let result = x + 3
    printfn "Added three to %d and got %d" x result
    result

A let объявление, которое просто объявляет имя, является значением.Значения оцениваются только один раз, поэтому любые побочные эффекты в значении произойдут только один раз.Точно , когда они происходят, точно не определяется спецификацией языка, поэтому вы не можете рассчитывать, когда произойдут побочные эффекты.С другой стороны, функции оцениваются каждый раз, когда вызывается функция.

Теперь, когда у вас есть функция, которая не принимает параметров, как вы ее объявляете?Ну, вы объявляете это, давая ему параметр, но параметр, который не имеет значения .В частности, вы заявляете, что он принимает параметр типа unit.Тип unit является специальным типом в F #.Это в основном соответствует пустому кортежу и записывается как ().

Подумайте о типе пустого кортежа на минуту.Если у вас есть кортеж из двух bool значений, сколько возможных значений может иметь этот кортеж?Четыре: это может быть (false, false), или (false, true), или (true, false), или (true, true).Если у вас есть кортеж всего one bool, он может иметь два значения: (true) или (false).Если у вас есть кортеж ноль значений (любого типа: bool, int, string, не имеет значения), то есть только одно возможное значение, которое он может иметь: (), пустой кортеж.И так как это тип только с одним возможным значением, именно поэтому он называется типом unit.

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

let myFunction () =
    printfn "I'm being called purely for the side effects"

Обратите внимание, как я помещаю пробел между именем функции и параметром unit.На самом деле у вас нет , чтобы иметь это место - совершенно законно писать let myFunction() = ... - но я хочу, чтобы вы увидели, что () - это не просто синтаксис объявления функции, это фактическое значение фактического типа.Это различие становится важным, когда вы начинаете делать более сложные вещи с помощью функций, поэтому я хочу, чтобы вы прояснили это сейчас.

Кстати, обычно в объявлении функции у вас будет имя параметра, а не значение, нотип unit обрабатывается специально: поскольку существует только одно возможное значение unit, вы уже знаете, с каким значением будет вызываться ваша функция, поэтому вам не нужно в любом случае присваивать это имя.Таким образом, F # позволяет вам объявить функцию с типом ввода unit, просто указав () в списке параметров, вместо того, чтобы заставлять вас выбирать имя, которое вы никогда не будете использовать в теле функции.

Я надеюсь, что это прояснит для вас.

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