我需要在我的一个函数中检测到一个可交换模式。我认为写下面的内容可以完成这项工作:
let my_fun a b = match a,b with
(*...*)
| a,b
| b,a when is_valid b -> process b (***)
(*...*)
这不起作用,Ocaml抱怨此子模式未使用
标有(***)
的行的警告。
1)有人可以向我解释这个警告试图说什么以及为什么这不起作用?
2)考虑到我现在想要哪个参数 if then else
?
is_valid
的情况下优雅地写出这个呢?
2)是否可以仅使用模式匹配来获得预期的功能而不重复when is_valid b -> process b
,如下所示?
let my_fun a b = match a,b with
(*...*)
| a,b when is_valid b -> process b
| b,a when is_valid b -> process b
(*...*)
编辑:
在我的具体示例中,a
和b
是成对的。这个函数有点复杂,但下面将说明这个案例:
let f a b = match a,b with
| (a1,a2),(b1,b2)
| (b1,b2),(a1,a2) when b1 = b2 -> a1 + a2
调用f (1,1) (1,2)
会导致模式匹配失败。我知道理解为什么(感谢下面的答案),如果我对每个元素都有不同的构造函数,我理解如何使它工作(如在Ashish Agarwal的答案中)。你能建议一种方法让它适用于我的情况吗?
答案 0 :(得分:7)
匹配首先匹配模式,如果成功,则通过从该模式匹配的附加环境评估条件。由于a,b
将始终绑定,因此这是唯一使用的情况,并且编译器正确报告从未使用b,a
。你必须重复这一行,
let my_fun a b = match a,b with
| a,b when is_valid b -> process b
| b,a when is_valid b -> process b
如果您没有对变量执行匹配,但是对某些变体执行匹配,则可以使用您的方法,例如,
let my_fun a b = match a,b with
| a, `Int b
| `Int b, a when is_valid b -> process b
编辑:使用一个后卫作为子表达式来考虑多个模式,
let my_fun a b = match a,b with
| ((a,b) | (b,a)) when is_valid b -> process b
您会在patterns的定义中看到这一点。它实际上是一种模式,由模式组成,匹配。
答案 1 :(得分:4)
对于你的第一个问题,要意识到的是你只有一个模式((a,b) | (b,a))
,恰好是一个“或”模式。匹配从“左”到“右”以“或”模式进行。由于(a,b)
将匹配任何内容,因此第二部分将永远不会被使用。
对于您的第二个问题,我没有看到问题,但这取决于a
和b
的类型。这是一个例子:
type t = A of int | B of float
let my_fun a b = match a,b with
| A a, B b
| B b, A a when b > 0. -> (float_of_int a) +. b
| … -> (* other cases *)
它也适用于更简单的类型:
let my_fun a b = match a,b with
| 1,b
| b,1 when b > 0 -> b + 1
| … -> (* other cases *)
如果您仍然无法使用此功能,请告诉我们您正在使用的a
和b
的类型。