Sco*_*rod 1 f# pattern-matching
以下行不编译:
| IsNeither -> sprintf "%i" // ???
Run Code Online (Sandbox Code Playgroud)
这是该行所属的功能:
let run = function
| IsFizzBuzz -> "Fizz Buzz"
| IsFizz -> "Fizz"
| IsBuzz -> "Buzz"
| IsNeither -> sprintf "%i" // Doesn't compile
Run Code Online (Sandbox Code Playgroud)
这是整个程序: 模块Temp
let (|IsFizz|IsBuzz|IsFizzBuzz|IsNeither|) = function
| n when n % 3 = 0 &&
n % 5 = 0 -> IsFizzBuzz
| n when n % 3 = 0 -> IsFizz
| n when n % 5 = 0 -> IsBuzz
| n -> IsNeither
let run = function
| IsFizzBuzz -> "Fizz Buzz"
| IsFizz -> "Fizz"
| IsBuzz -> "Buzz"
| IsNeither -> sprintf "%i" // Doesn't compile
let result = [1..16] |> List.map(run)
Run Code Online (Sandbox Code Playgroud)
我仍然可以使用签名上的"函数"语法提取值吗?
例:
let (|IsFizz|IsBuzz|IsFizzBuzz|IsNeither|) = function
Run Code Online (Sandbox Code Playgroud)
通过使用as关键字,有一种解决方案不需要您重新定义模式:
let run = function
| IsFizzBuzz -> "Fizz Buzz"
| IsFizz -> "Fizz"
| IsBuzz -> "Buzz"
| IsNeither as n -> sprintf "%i" n
Run Code Online (Sandbox Code Playgroud)
这很好地适用于活动模式,匹配有区别的联合案例等.一个突出的用例是类型检查,你有匹配的匹配 | :? string as s
最简单的解决方案是使值成为模式的一部分.
let (|IsFizz|IsBuzz|IsFizzBuzz|IsNeither|) = function
| n when n % 3 = 0 &&
n % 5 = 0 -> IsFizzBuzz
| n when n % 3 = 0 -> IsFizz
| n when n % 5 = 0 -> IsBuzz
| n -> IsNeither n
let run = function
| IsFizzBuzz -> "Fizz Buzz"
| IsFizz -> "Fizz"
| IsBuzz -> "Buzz"
| IsNeither n -> sprintf "%i" n
Run Code Online (Sandbox Code Playgroud)
有一个neither案例表明并非所有值都可以划分为"域",因此部分活动模式可能是更好的选择.
与AND模式相关联,它可以简化代码(以某些更改为代价)
// common code extracted and inlined (optional)
let inline isDivisibleBy divisor dividend =
if dividend % divisor = LanguagePrimitives.GenericZero
then Some ()
else None
let (|Fizz|_|) = isDivisibleBy 3
let (|Buzz|_|) = isDivisibleBy 5
let run = function Fizz & Buzz -> "FizzBuzz"
| Fizz -> "Fizz"
| Buzz -> "Buzz"
| x -> string x
let result = List.map run [1 .. 16]
Run Code Online (Sandbox Code Playgroud)
沿着这条道路走下去,人们甚至可以摆脱那些,Fizz并Buzz有利于一般将军IsDivisibleBy
let inline (|IsDivisibleBy|_|) divisor dividend =
if dividend % divisor = LanguagePrimitives.GenericZero
then Some ()
else None
let run = function IsDivisibleBy 3 & IsDivisibleBy 5 -> "FizzBuzz"
| IsDivisibleBy 3 -> "Fizz"
| IsDivisibleBy 5 -> "Buzz"
| x -> string x
let result = List.map run [1 .. 16]
Run Code Online (Sandbox Code Playgroud)
或者甚至那样,如果你仍然想要那些Fizz,Buzz你仍然可以做到
let (|Fizz|_|) = (|IsDivisibleBy|_|) 3
let (|Buzz|_|) = (|IsDivisibleBy|_|) 5
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
122 次 |
| 最近记录: |