I'm learning F#, starting with baby steps. Is there a way to write this code in a more succint way, while keeping the same semantics? Maybe by using a Seq
or something like that?
let rec repeatingPrompt predicate (message:string) =
Console.WriteLine(message)
let value = Console.ReadLine()
if predicate value then
value
else
repeatingPrompt predicate message
-
\$\begingroup\$ Hi, welcome to Code Review! I hope you receive great answers! \$\endgroup\$Tunaki– Tunaki2016年04月13日 16:04:11 +00:00Commented Apr 13, 2016 at 16:04
2 Answers 2
You can use Seq.initInfinite
and Seq.find
to do this, though I'm not sure it's actually better:
let repeatingPrompt predicate (message:string) =
let prompt _ =
Console.WriteLine(message)
Console.ReadLine()
Seq.initInfinite prompt |> Seq.find predicate
-
\$\begingroup\$ thank you. Why do you think it is not so useful to do this? Would you have done something along the lines of what I wrote? \$\endgroup\$Grubl3r– Grubl3r2016年04月13日 20:35:34 +00:00Commented Apr 13, 2016 at 20:35
-
1\$\begingroup\$ @Grubl3r Possibly. Both versions are about the same length, but the
Seq
version is harder to understand, since you need to know whatinitInfinite
andfind
do. \$\endgroup\$svick– svick2016年04月13日 21:35:12 +00:00Commented Apr 13, 2016 at 21:35
I like svick's answer but wanted to show an alternate way without using Seq
module.
It's not very different of yours (not really an improvement), but functional programming tend to favor pattern matching over if
tests so maybe it's more "idiomatic".
I also replaced the use of Console with the already available (without opening System) stdin
and stdout
but that's anecdotic
let rec repeatingPrompt predicate message =
stdout.WriteLine (message: string) // you can put the type here too
match stdin.ReadLine () with
| value when predicate value -> value
| _ -> repeatingPrompt predicate message