为什么这个F#函数只运行一次?我打了两次电话,它只运行一次

时间:2018-05-31 01:49:24

标签: f#

我编写了以下代码来测试F#中的一些MonteCarlo代码。

我的问题是我只在控制台中看到随机数和“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 :(得分:9)

为了扩展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

声明名称的let声明是一个值。值只评估一次,因此值中的任何副作用都只会发生一次。 它们发生的时间并不完全由语言规范定义,所以你不能指望副作用何时发生。另一方面,每次调用函数时都会对函数进行求值。

现在,当你有一个不带参数的函数时,你如何声明它?好吧,你通过给它一个参数声明它,但是无关紧要的参数。具体来说,您声明它采用类型为unit的参数。 unit类型是F#中的特殊类型。它基本上对应一个空元组,并写为()

考虑一分钟的空元组类型。如果你有两个bool值的元组,那么这个元组有多少可能的值?四:可以是(false, false)(false, true)(true, false)(true, true)。如果您的元组只有一个 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来声明一个输入类型为()的函数,而不是让你选择一个你从未在函数体中实际使用的名称。 / p>

我希望这能为你解决问题。

相关问题