下面的F#code ++工程,如我所料,印刷`匹配为A:
The following F# code works as I expected, printing `Matched as 'A':
let (|Char|_|) convf = function
| LazyList.Nil -> None
| LazyList.Cons (x, _) -> Some (convf x)
let test = function
| Char System.Char.ToUpper x -> printfn "Matched as %A" x
| _ -> printfn "Didn't match"
test (LazyList.of_list ['a'])
不过,如果我更改字符
从部分活跃的方式,以一个完整的活动模式如下:
However, if I change Char
from a partial active pattern to a complete active pattern as follows:
let (|Char|NoChar|) convf = function
| LazyList.Nil -> NoChar
| LazyList.Cons (x, _) -> Char x
let test = function
| Char System.Char.ToUpper x -> printfn "Matched as %A" x
| NoChar System.Char.ToUpper -> printfn "Didn't match"
test (LazyList.of_list ['a'])
那么code编译失败,给下面的错误信息:错误FS0191:只有激活模式返回只有一个结果是可以接受的参数
这个例子可能看起来有点做作,但它是一个活跃的格局我试图在Prolog的词法分析器我一直在我的业余时间使用的简化版本。我可以很容易地重写我的code,以避免这个问题,但我很好奇,为什么这样的code是不允许的。
This example may look somewhat contrived, but it's a simplified version of an active pattern I tried to use in a Prolog lexer I've been working on in my spare time. I can easily rewrite my code to avoid this problem, but I'm curious about why this sort of code is disallowed.
更新:的较新版本的F#似乎已经改名为这个错误:
Update: the newer versions of F# seem to have renamed this error:
错误FS0722:只有激活模式返回只有一个结果是可以接受的参数
NB。这正是Brian说,但在一个更清晰的方式希望说明。的
我记得登录precisely这个问题上的错误,并IIRC这是唐赛姆不得不说的事。
I recall logging a bug on precisely this issue and IIRC this is what Don Syme had to say on the matter.
一个多情况下,主动模式是从一些输入值的转换功能分为多个输出值中的一个。在你的榜样,任何字符转换为字符的情况下或NoChar情况。
A multi-case active pattern is a conversion function from some input value into one of several output values. In your example, any character is converted to the Char case or the NoChar case.
这样做的好处是,F#编译器调用多情况下,主动模式功能,一次就可以大致判断明年评估哪种模式匹配规则。
The benefit of this is that the F# compiler calls the multi-case active pattern function once and can then generally determine which pattern match rule to evaluate next.
然而,如果你让一个参数,那么你需要评估多情况下,主动模式的每一个模式匹配规则。
If you allow a parameter however, then you need to evaluate the multi-case active pattern for every pattern match rule.
所以,想象一下以下
match input with
| Alpha "foo" -> ...
| Bravo "bar" -> ...
在评估(|阿尔法|布拉沃|)富返回布拉沃,那么第一个规则不匹配。 Likeways(|阿尔法|布拉沃|)栏中的返回阿尔法,那么第二条规则就不是非此即彼匹配。所以,你真的没有多的情况下主动模式。就在paramterized,局部活跃格局。 (由于一些输入的预期图案情况下也不会打了。)
When evaluating (|Alpha|Bravo|) "foo" returned 'Bravo', then the first rule wouldn't match. Likeways (|Alpha|Bravo|) "bar" returns 'Alpha', then the second rule wouldn't match either. So you don't really have a multi-case active pattern. Just a paramterized, partial active pattern. (Because for some inputs the expected pattern-case won't be hit.)
因此,当用不构成一个整体非常有意义的语言的一个角落里遇到,实际上可更清晰的部分,参数化的活动模式。该功能未添加到语言
So when confronted with a corner of the language that doesn't make a whole lot of sense, and in fact can be made much clearer by the partial, parameterized active pattern. The feature wasn't added to the language.