无法生成随机数F#

Waz*_*zie 3 f# functional-programming

我正在研究一个小项目,我正在尝试学习F#的功能方式,由于一些奇怪的原因,我无法生成随机数,因此无法获得随机日期.这是我的F#代码

let IfancyHerList = [("Sara",1); ("Saima",2); ("Zoe",3);("Scarlett",4);
("Jennifer",5);("Sandra Bullock",6)]

let MyGirlFriend  = List.pick (fun funToNight  ->
                     let n = rand.Next(10)
                     match funToNight with                    
                     | (value,n ) -> Some value
                     |_ -> None) IfancyHerList
printfn "Your date for tonight is %s lucky fella" MyGirlFriend
Run Code Online (Sandbox Code Playgroud)

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

任何建议都会受到欢迎

谢谢

Dav*_*aab 6

您的代码没有按照您的预期执行.模式匹配在技术上与构建数据相反.它只是分解/解构数据.

你在这做什么:

match funToNight with                    
| (value,n ) -> Some value
|_ -> None
Run Code Online (Sandbox Code Playgroud)

具有以下含义:

  1. 检查是否funToNight是一个元组.
  2. 将元组的第一个值分配给 value
  3. 将元组的第二个值分配给 n

看起来你的期望是:

  1. 检查元组的第二个值是否在内部 n

这不是模式匹配的工作原理.

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

match funToNight with
| (value,x) when x = n -> Some value
| _ -> None
Run Code Online (Sandbox Code Playgroud)

但在我看来,你的案例正是一个用例,模式匹配开始时没有意义.您想要检查第二个条目是否是您的随机数,因此请使用if语句.

let MyGirlFriend  =
    List.pick (fun funToNight  ->
        let n = rand.Next(10)
        if   (snd funToNight) = n
        then Some (fst funToNight)
        else None
    ) IfancyHerList
Run Code Online (Sandbox Code Playgroud)

而不是fstsnd你也可以在lambda做到这一点.

let MyGirlFriend =
    List.pick (fun (name,nr)  ->
        let n = rand.Next(10)
        if   nr = n
        then Some name
        else None
    ) IfancyHerList
Run Code Online (Sandbox Code Playgroud)

这是选择的一般解决方案,也适用于其他大小的元组.fst并且snd只能使用具有两个元素的元组.

除此之外,您可能想要使用List.tryPick而不是List.pick.List.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!"
Run Code Online (Sandbox Code Playgroud)

附录

你的List.pick电话回复很多None,不会选择一个条目.原因是您在传递给lambda函数内生成随机数List.pick.

您当前的代码"流"是这样的.你仔细阅读清单.首先采摘("Sara",1).你会说,你生成一个随机的5.1并且5不匹配,因此("Saima", 2)将使用下一个条目.但是你再次生成一个新的随机数,让我们说3下一个条目被选中因为3并且2不相等.这可以继续,而不是每次选择任何条目.即使您将随机生成更改为rand.Next(6).

所以一般的建议是你不应该为lambda表达式添加副作用.我假设您要生成一个随机数,然后从列表中选择它.通过提取lambda之外的随机调用很容易改变.

let myGirlFriend =
    let n = rand.Next(10)
    List.tryPick (fun (name,nr) ->
        if   nr = n
        then Some name
        else None
    ) ifancyHerList
Run Code Online (Sandbox Code Playgroud)

所以一般建议,避免高阶函数的副作用.


rmu*_*unn 5

你真正的问题根本不是随机数,而是你的match陈述.你误解了它是如何工作的.简短版本:match (whatever) with (value, n) -> ...没有做你认为它做的事情:它总是匹配,并分配名称valuen你匹配的任何元组的两个部分.

较长的版本是你犯了与F#相同的错误:不理解匹配..所以我只是指出你的问题来阅读更深入的答案.