【发布时间】:2016-04-09 12:50:12
【问题描述】:
在使用守卫管理模式匹配时,除了抛出异常之外,还有什么替代方法?
[<Literal>]
let Objective = 33
let (|NotGame|IsGame|) p =
match p with
| LessThanGame v when v < Objective -> NotGame v
| Game v when v >= Objective -> IsGame v
警告:
此表达式的模式匹配不完整
我不希望编译器有任何抱怨。
结果,我不想做的是:
let (|NotGame|IsGame|) p =
match p with
| LessThanGame v when v < Objective -> NotGame v
| Game v when v >= Objective -> IsGame v
| _ -> failwith "idk..."
我宁愿这样做:
let (|NotGame|IsGame|) p =
match p with
| LessThanGame v when v < Objective -> NotGame v
| Game v when v >= Objective -> IsGame v
| _ v -> IsGame v
完整的代码在这里:
// ***********
// Game of 33
// ************************************************************
(*Types*)
// ************************************************************
type Player =
| Player1
| Player2
type Shot =
| TwoPointer
| ThreePointer
| FoulShot
| TwoFoulShots
| ThreeFoulShots
type PlayerScore = {Player:Player; Points:Points}
and Points =
| LessThanGame of int
| Game of int
type Posession = Posession of Player
[<Literal>]
let Objective = 33
// ************************************************************
(*Active Patterns*)
// ************************************************************
let (|NotGame|IsGame|) = function
| LessThanGame v when v < Objective -> NotGame v
| Game v when v >= Objective -> IsGame v
| _ -> failwith "idk..."
// ************************************************************
(*Functions*)
// ************************************************************
let makeShot shot (shooter, defender) =
let ballHandler = shooter.Player
let points = shooter.Points
let shotValue = match shot with
| TwoPointer | TwoFoulShots -> 2
| ThreePointer | ThreeFoulShots -> 3
| FoulShot -> 1
match points with
| NotGame p -> if p + shotValue < Objective then
{ Player=ballHandler; Points=LessThanGame (p + shotValue) }, defender
else { Player=ballHandler; Points=Game (p + shotValue) }, defender
| IsGame p -> { Player=ballHandler; Points=Game p }, defender
let startGame =
let player1Score = { Player=Player1; Points=LessThanGame 0 }
let player2Score = { Player=Player2; Points=LessThanGame 0 }
(player1Score, player2Score)
// ************************************************************
(*Client*)
// ************************************************************
let player1Score, player2Score = startGame
let player1, player2 = (player1Score, player2Score) |> makeShot TwoPointer
let shooter, defender = player2, player1
let final = (shooter, defender) |> makeShot ThreePointer
|> makeShot FoulShot
|> makeShot ThreePointer
|> makeShot TwoFoulShots
|> makeShot ThreePointer
|> makeShot ThreeFoulShots
|> makeShot ThreePointer
|> makeShot ThreePointer
|> makeShot ThreePointer
|> makeShot ThreePointer
|> makeShot ThreePointer
分辨率:
正如 Guy Coder 所建议的,我使用 if/else 条件作为替代。因此,这消除了我抛出异常的需要。
// ************************************************************
(*Types*)
// ************************************************************
type Player = | Player1 | Player2
type Shot =
| TwoPointer| ThreePointer
| FoulShot | TwoFoulShots | ThreeFoulShots
type PlayerScore = {Player:Player; Game:Game}
and Game =
| Underway of int
| AlmostGame of int
| GameTime of int
[<Literal>]
let Objective = 33
[<Literal>]
let MaxFoulShots = 3
let (|Underway|AlmostGame|Game|) (score,shot) =
let shotValue = match shot with
| FoulShot -> 1
| TwoPointer | TwoFoulShots -> 2
| ThreePointer | ThreeFoulShots -> 3
match score, shotValue with
| Underway s,v -> if (s + v) <= (Objective - MaxFoulShots)
then Underway (s + v)
else AlmostGame (s + v)
| AlmostGame s,v -> if ( (s+v) < Objective )
then AlmostGame (s + v)
else Game Objective
| GameTime s,v -> Game s
// ************************************************************
(*Functions*)
// ************************************************************
let makeShot shot (shooter, defender) =
match (shooter.Game, shot) with
| Underway p -> { shooter with Game=Underway p }, defender
| AlmostGame p -> { shooter with Game=AlmostGame p }, defender
| Game p -> { shooter with Game=GameTime p }, defender
let startGame =
let player1Score = { Player=Player1; Game=Underway 0 }
let player2Score = { Player=Player2; Game=Underway 0 }
(player1Score, player2Score)
// ************************************************************
(*Client*)
// ************************************************************
let player1Score, player2Score = startGame
let player1, player2 = (player1Score, player2Score) |> makeShot TwoPointer
let shooter, defender = player2, player1
let final = (shooter, defender) |> makeShot ThreePointer
|> makeShot FoulShot
|> makeShot ThreePointer
|> makeShot TwoFoulShots
|> makeShot ThreePointer
|> makeShot ThreeFoulShots
|> makeShot ThreePointer
|> makeShot ThreePointer
|> makeShot ThreePointer
|> makeShot ThreePointer
|> makeShot ThreePointer
|> makeShot FoulShot
|> makeShot FoulShot
|> makeShot ThreeFoulShots
【问题讨论】:
-
一旦你有一个什么时候编译器停止检查并发出警告,除非你有一个通配符。无法真正修复,我认为昨天有一个骗局
-
约翰,不同之处在于我有一个附加到联合案例的值。昨天的问题没有附加数据。相反,该值只是一个 int 而不是 union case。
-
哦,_v 的事情也做不到。仍然是重复的
-
scott wlaschin 建议在您拥有正在执行的代码时不要抛出异常。因此,此代码不执行 I/O。有什么建议吗?
-
如果我正确理解您的问题,您正试图将输入分类为两个存储桶,条件为
less than。如果是这样,那么放弃模式匹配,只使用if语句。没有规则说必须对所有决策使用模式匹配才能发挥作用。我看到的另一种方式是您尝试在分类的同时进行输入验证。让输入验证处理问题,分类不会有这些异常情况。
标签: f#