Nic*_*ner 4 f# fizzbuzz active-pattern
我正在尝试了解Active Patterns,所以我正在玩FizzBuzz:
let (|Fizz|_|) i = if i % 3 = 0 then Some Fizz else None
let (|Buzz|_|) i = if i % 5 = 0 then Some Buzz else None
let (|FizzBuzz|_|) i = if i % 5 = 0 && i % 3 = 0 then Some FizzBuzz else None
let findMatch = function
| Some Fizz -> "Fizz"
| Some Buzz -> "Buzz"
| Some FizzBuzz -> "FizzBuzz"
| _ -> ""
let fizzBuzz = seq {for i in 0 .. 100 -> Some i}
|> Seq.map (fun i -> i, findMatch i)
Run Code Online (Sandbox Code Playgroud)
这基本上是正确的方法,还是有更好的方法在这里使用活动模式?我不应该能够findMatch使用int而不是int选项吗?
Tom*_*cek 10
Daniel的第一个解决方案可以简化,因为您实际上不需要为其定义单独的活动模式FizzBuzz.案例可以描述为Fizz和Buzz匹配,可以在模式语言中很好地表达:
let findMatch = function
| Fizz & Buzz -> "FizzBuzz"
| Fizz -> "Fizz"
| Buzz -> "Buzz"
| _ -> ""
let fizzBuzz = [ for i in 0 .. 100 -> findMatch i ]
Run Code Online (Sandbox Code Playgroud)
模式Fizz & Buzz匹配,如果两者Fizz并Buzz匹配.这取决于模式首先匹配的事实,因此在这种情况下顺序是相关的.我还将你的最后一行缩短为我喜欢的风格,并且缩短了一些(但意见各不相同).
或者,如果您不想定义太多单用途活动模式,您还可以编写参数化活动模式,以测试输入是否可被任何指定数字整除:
let (|DivisibleBy|_|) by n = if n%by=0 then Some DivisibleBy else None
let findMatch = function
| DivisibleBy 3 & DivisibleBy 5 -> "FizzBuzz"
| DivisibleBy 3 -> "Fizz"
| DivisibleBy 5 -> "Buzz"
| _ -> ""
Run Code Online (Sandbox Code Playgroud)
你的findMatch功能应该是:
let findMatch = function
| FizzBuzz -> "FizzBuzz" (* should be first, as pad pointed out *)
| Fizz -> "Fizz"
| Buzz -> "Buzz"
| _ -> ""
Run Code Online (Sandbox Code Playgroud)
你可以重写最后几行:
let fizzBuzz = Seq.init 100 (fun i -> i, findMatch i)
Run Code Online (Sandbox Code Playgroud)
你的活动模式很好.一种替代方法是使用完整的活动模式:
let (|Fizz|Buzz|FizzBuzz|Num|) i =
match i % 3, i % 5 with
| 0, 0 -> FizzBuzz
| 0, _ -> Fizz
| _, 0 -> Buzz
| _ -> Num i
Run Code Online (Sandbox Code Playgroud)