我正在尝试编写一个函数“dom_rank r1 r2”,根据两张扑克牌的相对等级返回一个布尔值(等级是我定义的类型,它有值“Six”,“Seven”,“Eight” “.....”King“,”Ace“)。如果r1是King而r2是Jack,则r1大于r2并且函数返回true,如果r1是Six而r2是Ten,则函数返回false。据我所知,我可以列出两种卡输入的所有可能性(我只处理六A牌,这有三种不同的可能性)但我正在尝试编写更简单的代码。该方法类似于:
let dom_rank r1 r2 = match r1, r2 with
| Ace, _ -> true
| King, (Queen || Jack || Ten ........) -> true
我在布尔表达式“(Queen || Jack || Ten ........)”的开头遇到语法错误。为什么我不能以这种方式列出r2的几种可能性?有没有办法在Ocaml中编写这个表达式?
答案 0 :(得分:5)
“||” operator是一个布尔运算符,你必须用简单的“|”分隔模式,如下所示:
| King, (Queen | Jack | Ten | ... ) -> true
但是,使用这种方法,你仍然会在很长一段时间内写下“六”这个词。 一个好的方法是巧妙地使用通配符:
match r1, r2 with
| Ace, _ -> true
| _, Ace -> false (* at this point, neither card is an ace *)
| King, _ -> true
| _, King -> false
| Queen, _ -> true
| (* and so on *)
这样,每个卡片排名只有两个模式,并且没有键入两次以上的卡片名称(非卡片名称可以复制粘贴)
不太安全但方便的方法是检查您的类型定义是否正确顺序:
type rank = Six | Seven | Eight | ... | Ace
let () = assert ( Six < Eight )
根据这个定义,相对于标准比较运算符,卡应该处于良好的顺序(参见模块Pervasives)。确保进行一些测试,因为对该类型的任何修改都可能会破坏您的订单。
答案 1 :(得分:1)
正如你自己所说,||
是一个布尔运算符。 Queen
,Jack
等不是布尔值。因此,您不能对它们应用布尔运算符(更不用说您不能将任意表达式用作match
中的模式)。
您可以做的是将每个旁边的多个模式分隔为|
,如下所示:
| King, Queen | King, Jack| King, Ten |... -> true
当然,这并不像你需要每次拼出King一样简洁。您可以通过使用嵌套模式匹配而不是在元组上匹配来避免它们:
let dom_rank r1 r2 =
match r1 with
| Ace -> true
| King->
(match r2 with
| Ace -> false
| _ -> true)
| ...
| Seven ->
(match r2 with
| Six, Five, Four, Three, Two -> true
| _ -> false)
另一种方法是定义一个函数,将每个等级映射到一个整数,然后将dom_rank
定义为:
let dom_rank r1 r2 = int_of_rank r1 >= int_of_rank r2
这应该减少了很多重复,在我看来是最好的版本。