Unable to generate random number F#
f#, functional-programming
Solution
Your code doesn't do what you expect it to do. Pattern Matching is technically the opposite of constructing data. It just decompose/de-construct data.
What you do here:
match funToNight with
| (value,n ) -> Some value
|_ -> None
has the following meaning:
- Check if `funToNight` is a tuple.
- Assign the first value of the tuple to `value`
- Assign the second value of the tuple to `n`
It seems what you expected was:
- Check if the second value of a tuple is what is inside `n`
And that isn't how Pattern Matching works.
You can add conditionals like comparing a value with a pre-defined variable by adding a `when` clause to the Pattern Matching. Like this:
match funToNight with
| (value,x) when x = n -> Some value
| _ -> None
But in my opinion, your case is exactly a use-case where Pattern Matching don't make sense to begin with. You want to check if the second entry is your random number, so use an `if` statement instead.
let MyGirlFriend =
List.pick (fun funToNight ->
let n = rand.Next(10)
if (snd funToNight) = n
then Some (fst funToNight)
else None
) IfancyHerList
instead of `fst` and `snd` you also can do it in the lambda.
let MyGirlFriend =
List.pick (fun (name,nr) ->
let n = rand.Next(10)
if nr = n
then Some name
else None
) IfancyHerList
This is the general solution to pick that also works with tuples of other sizes. `fst` and `snd` only work with tuples that has exactly two elements.
Besides that you probably want to use `List.tryPick` instead of `List.pick`. `List.pick` throws an exception if it cannot find an element. On top variables should start with a lower-case. Upper-case values are used for Types/Classes.
So here is a complete working example:
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!"
Addendum
Your `List.pick` call returns quite a lot `None` and doesn't pick an entry. The reason is that you generate the random number inside the lambda function you pass to `List.pick`.
Your current "flow" of your code is like this. You go through the list. First picking `("Sara",1)`. You generate a random, let's say `5`. `1` and `5` doesn't match so the next entry `("Saima", 2)` will be used. But then you generate again a new random number, let's say `3` and the next entry is picked because `3` and `2` are not equal. This can go on without every picking any entry. Even if you change the random generation to `rand.Next(6)`.
So a general advice is that you shouldn't add side-effects to lambda expressions. I assume you want to generate one random number and then pick it from the list. Its easy to change by extracting the random call outside the lambda.
let myGirlFriend =
let n = rand.Next(10)
List.tryPick (fun (name,nr) ->
if nr = n
then Some name
else None
) ifancyHerList
So a general advice, avoid side-effects in Higher-Order functions.
Problem
I am working on a small project and am trying to learn F# the functional way ,for some strange reason I am unable to generate a random number and as such unable to get a random date. here is my F# code ``` 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 ``` The let n = rand.Next(10) does generate a random number but not in match block any suggestion would be most welcome thanks