2017-05-27 87 views
1

我主要工作在C#中,并且是F#/函数语言的新手,我遇到了一个非常简单的程序问题。 我有一个函数用两个整数字段创建一条记录。在match内选择字段System.Random.NextDouble以符合某些概率。然后我有一个for循环,应该运行四次createCustomer函数。在for循环中返回记录的F#调用函数只执行一次

我遇到的问题是Customer对于for循环的所有10次迭代都是一样的,getIATime中的printfn似乎只执行一次。

Program.fs

open Simulation 

[<EntryPoint>] 
let main argv = 
    printfn "%A" argv 
    printfn "Test" 

    for i in 1 .. 10 do 
     let mutable customer = createCustomer 
     printfn "i: %d\tIA: %d\tService: %d" i customer.interArrivalTime customer.serviceTime 


    ignore (System.Console.ReadLine()) //Wait for keypress @ the end 
    0 // return an integer exit code 

Simulation.fs

module Simulation 

type Customer = { 
    interArrivalTime: int 
    serviceTime: int 
} 

let createCustomer = 
    let getRand = 
     let random = new System.Random() 
     fun() -> random.NextDouble() 

    let getIATime rand = 
     printf "Random was: %f\n" rand 
     match rand with 
     | rand when rand <= 0.09 -> 0 
     | rand when rand <= 0.26 -> 1 
     | rand when rand <= 0.53 -> 2 
     | rand when rand <= 0.73 -> 3 
     | rand when rand <= 0.88 -> 4 
     | rand when rand <= 1.0 -> 5 

    let getServiceTime rand = 
     match rand with 
     | rand when rand <= 0.2 -> 1 
     | rand when rand <= 0.6 -> 2 
     | rand when rand <= 0.88 -> 3 
     | rand when rand <= 1.0 -> 4 

    {interArrivalTime = getIATime (getRand()); serviceTime = getServiceTime (getRand())} 
+1

你不需要在循环中说,“可变”关键字。在这种情况下,它与C#一样。如果你要在C#中的一个循环中声明一个变量,它不会是同一个变量,而是每个循环迭代的新变量。 –

+0

好的电话,忘了我甚至在那里。我曾尝试添加它以查看它是否能解决我遇到的问题 – WereGoingOcean

+0

如果您要进行代码审查,还会滥用“匹配”。 –

回答

4

getCustomer不是一个函数,而是一个。它的主体在程序初始化时只执行一次,结果存储在一个字段中,然后可以访问它。当你认为你“调用”这个函数时,你实际上只是参考了这个值。没有呼叫正在进行,因为没有任何呼叫。

要使getCustomer成为函数,请给它一个参数。这就是函数与F#中的值的区别:如果你有一个参数,你是一个函数;如果没有 - 你是一个价值。由于没有实际的数据要传递给该函数,因此可以给它一个类型为unit的“虚拟”(“占位符”)参数。这种类型有一个值,并将该值写为()

let createCustomer() = 
    let getRand = 
     let random = new System.Random() 
     fun() -> random.NextDouble() 

    ... 

然后调用它像这样:

for i in 1 .. 10 do 
    let mutable customer = createCustomer() 
    printfn "i: %d\tIA: %d\tService: %d" i customer.interArrivalTime customer.serviceTime 
+0

这是我的问题。我最终把'fun() - > {...}'放在最后,而不是在每个循环中创建'System.Random()'。谢谢! – WereGoingOcean

+1

请注意,可以在没有显式参数的情况下声明函数,但在调用时仍需要提供至少一个参数。我认为在技术上他们是包含功能的价值。这在F#中很常见,并且可能成为初学者混淆的来源。 –