问题描述
比方说我写这段代码:
# type t = A of int * int
let f = function A (i1, i2) -> print_int i1;;
type t = A of int * int
val f : t -> unit = <fun>
完美,有效.
现在,假设我有这个很棒的功能:
Now, let's say I have this wonderful function :
# let print_couple (i1, i2) = print_int i1; print_int i2;;
val print_couple : int * int -> unit = <fun>
所以,正如您所期望的,我想写以下内容
So, as you expect, I'd like to write the following
# let f = function A (_ as c) -> print_couple c;;
好吧,我不能
Error: The constructor A expects 2 argument(s),
but is applied here to 1 argument(s)
我想知道是因为_
还是括号(我对此深信不疑,但我想穷举一下)?
I wondered, is it because of the _
or the parenthesis (I seriously had doubts about that but I wanted to be exhaustive) ?
# let f = function A _ -> failwith "Fight me"
let g = function A (_) -> failwith "1o1";;
val f : t -> 'a = <fun>
val g : t -> 'a = <fun>
不,不是...
哦,也许我必须告诉编译器我知道我有两个参数:
Oh, maybe I have to show the compiler I know I have two arguments :
# let f = function A ((_, _) as c) -> print_couple c;;
Error: The constructor A expects 2 argument(s),
but is applied here to 1 argument(s)
但是...如果我写
# let f = function A (_, _) -> failwith "Puppey style";;
有效.那为什么呢,既然编译器知道我要几个,而且我甚至想把它给他,它为什么总是失败呢?是不是通过写A (_ as c)
我是在命名第一个参数,无论如何?很奇怪,不是吗?
It works. Then why, since the compiler knows that I'm expecting a couple and I'm even trying to give it to him it keeps failing ? Is it that by writing A (_ as c)
I'm naming, no matter what, the first argument ? It's strange, isn't it ?
我的意思是,如果我写
# let rec f = function
| [] -> ()
| hd :: tl -> print_couple hd; f tl;;
val f : (int * int) list -> unit = <fun>
对于这个列表是关联列表还是整数列表,编译器不会打扰我吗?那么,对我期望同样的行为感到奇怪吗?
The compiler won't bother me about this list being an association list or an integer list ? Then is it strange from me to expect the same behaviour from
# match a with
| A c | A (_ as c) | A ((_, _) as c) -> ()
?
推荐答案
OCaml的怪癖是,像您对A
的定义那样的构造函数在语法上看起来像一对,但不是一对.
It's a quirk of OCaml that a constructor like your definition of A
takes what syntactically looks like a pair, but is not a pair.
# type t = A of int * int;;
type t = A of int * int
# A (3, 4);;
- : t = A (3, 4)
# let z = (3, 4) in A z;;
Error: The constructor A expects 2 argument(s),
but is applied here to 1 argument(s)
如果将构造函数定义为实际使用一对,则可以提供一对:
If you define the constructor as actually taking a pair, you can supply a pair:
# type u = B of (int * int);;
type u = B of (int * int)
# B (3, 4);;
- : u = B (3, 4)
# let z = (3, 4) in B z;;
- : u = B (3, 4)
这有点令人困惑,但这只是OCaml的工作方式.您需要为诸如A
之类的构造函数提供专门带括号的参数.
This is somewhat confusing, but it's just the way OCaml works. You need to supply specifically parenthesized arguments to a constructor like A
.
与_
匹配时不需要提供明确的括号也令人有些惊讶:
It's also a little surprising that you don't need to supply explicit parentheses when matching against _
:
# let A _ = A (4, 5);;
#
(当然,这仅在较大模式中有用.)
(This is only useful as part of a larger pattern, of course.)
这篇关于OCaml:作为模式匹配中的关键字时,行为异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!