无法生成随机数F#

无法生成随机数F#,f#,functional-programming,F#,Functional Programming,我正在做一个小项目,试图学习F#函数的方式,出于某种奇怪的原因,我无法生成随机数,因此无法获得随机日期。这是我的F代码 让n=rand.Next(10)生成一个随机数,但不在匹配块中 任何建议都是非常受欢迎的 谢谢你真正的问题根本不是随机数,而是你的匹配声明。你误解了它的工作原理。简短版本:match(whatever)with(value,n)->……不会做您认为它会做的事情:它总是匹配,并将名称value和n分配给您匹配的元组的两个部分 较长的版本是,您犯的错误与相同,因此我将向您指出该问题

我正在做一个小项目,试图学习F#函数的方式,出于某种奇怪的原因,我无法生成随机数,因此无法获得随机日期。这是我的F代码

让n=rand.Next(10)生成一个随机数,但不在匹配块中

任何建议都是非常受欢迎的


谢谢

你真正的问题根本不是随机数,而是你的
匹配
声明。你误解了它的工作原理。简短版本:
match(whatever)with(value,n)->……
不会做您认为它会做的事情:它总是匹配,并将名称
value
n
分配给您匹配的元组的两个部分


较长的版本是,您犯的错误与相同,因此我将向您指出该问题,以阅读更深入的答案。

您的代码没有达到您期望的效果。模式匹配在技术上与构造数据相反。它只是分解/解构数据

你在这里做什么:

match funToNight with                    
| (value,n ) -> Some value
|_ -> None
具有以下含义:

  • 检查
    是否为元组
  • 将元组的第一个值指定给
    value
  • 将元组的第二个值赋给
    n
  • 看来你所期望的是:

  • 检查元组的第二个值是否为
    n
  • 模式匹配不是这样工作的

    您可以通过在模式匹配中添加
    when
    子句来添加条件,例如将值与预定义变量进行比较。像这样:

    match funToNight with
    | (value,x) when x = n -> Some value
    | _ -> None
    
    但在我看来,您的案例正是一个用例,模式匹配从一开始就没有意义。您想检查第二个条目是否是您的随机数,因此请改用
    if
    语句

    let MyGirlFriend  =
        List.pick (fun funToNight  ->
            let n = rand.Next(10)
            if   (snd funToNight) = n
            then Some (fst funToNight)
            else None
        ) IfancyHerList
    
    除了
    fst
    snd
    之外,您还可以在lambda中执行此操作

    let MyGirlFriend =
        List.pick (fun (name,nr)  ->
            let n = rand.Next(10)
            if   nr = n
            then Some name
            else None
        ) IfancyHerList
    
    let myGirlFriend =
        let n = rand.Next(10)
        List.tryPick (fun (name,nr) ->
            if   nr = n
            then Some name
            else None
        ) ifancyHerList
    
    这是拾取的一般解决方案,也适用于其他大小的元组
    fst
    snd
    仅适用于正好有两个元素的元组

    此外,您可能希望使用
    List.tryPick
    而不是
    List.pick
    <代码>列表。如果无法找到元素,pick
    将引发异常。顶部变量应以小写开头。大写值用于类型/类

    下面是一个完整的工作示例:

    let rand = new System.Random()
    
    let ifancyHerList =
        [
            ("Sara",1); ("Saima",2); ("Zoe",3); ("Scarlett",4);
            ("Jennifer",5);("Sandra Bullock",6)
        ]
    
    let myGirlFriend =
        List.tryPick (fun (name,nr)  ->
            let n = rand.Next(10)
            if   nr = n
            then Some name
            else None
        ) ifancyHerList
    
    match myGirlFriend with
    | Some name -> printfn "Your date for tonight is %A lucky fella" name
    | None      -> printfn "You don't have a date tonight!"
    
    补遗 您的
    列表。pick
    调用返回大量
    None
    ,并且不选择条目。原因是您在传递给
    列表的lambda函数中生成了随机数。选择

    您当前的代码“流”是这样的。你看一下名单。首次挑选
    (“Sara”,1)
    。您生成一个随机变量,比如说
    5
    <代码>1和
    5不匹配,因此将使用下一个条目
    (“Saima”,2)
    。但是,您再次生成一个新的随机数,比如说
    3
    ,然后选择下一个条目,因为
    3
    2
    不相等。这可以在没有任何条目的情况下继续进行。即使您将随机生成更改为
    rand.Next(6)

    因此,一般的建议是,不要给lambda表达式添加副作用。我假设您要生成一个随机数,然后从列表中选择它。通过提取lambda之外的随机调用,很容易进行更改

    let MyGirlFriend =
        List.pick (fun (name,nr)  ->
            let n = rand.Next(10)
            if   nr = n
            then Some name
            else None
        ) IfancyHerList
    
    let myGirlFriend =
        let n = rand.Next(10)
        List.tryPick (fun (name,nr) ->
            if   nr = n
            then Some name
            else None
        ) ifancyHerList
    

    因此,一般建议是,避免在高阶函数中产生副作用。

    这是因为此随机数API与函数编程不兼容。伪随机数生成器具有隐式状态,在适当的函数程序中,必须将其作为参数传递给
    next
    ,并在
    对中获得一个数字和一个新的修改状态。一开始你不应该这么做。你的可能复制品接受了我的答案,但大卫·拉布的答案要完整得多。我觉得你应该不接受我的答案,而接受他的答案,因为这是你评论说这对你有多大帮助的答案。大卫,我们可以交换一下大脑吗?你12周来第一次这么好地解释了这一点,我必须理解函数式编程是怎么回事。非常感谢。问题解决了。@WaheedRafiq I为另一个问题添加了一个附录。