gpt4 book ai didi

ocaml - 用元组作为参数定义异常

转载 作者:行者123 更新时间:2023-12-04 16:26:31 25 4
gpt4 key购买 nike

我试图在 OCaml 中定义一个异常,它接受一对列表作为参数。但是,这种情况行不通?

# exception Foo of string list * string list;; 
exception Foo of string list * string list
# let bar = (["a"], ["b"; "c"; "d"]);;
val bar : string list * string list = (["a"], ["b"; "c"; "d"])
# raise(Foo bar);;
Error: The constructor Foo expects 2 argument(s),
but is applied here to 1 argument(s)

但是,如果我这样做,它会起作用
# raise (Foo (["a"], ["b"; "c"; "d"]));;
Exception: Foo (["a"], ["b"; "c"; "d"]).

这是怎么回事?谢谢!

最佳答案

你看错了(虽然我不会责怪你:一开始这很令人惊讶)。在您看来,构造函数遵循语法 Name of type其中类型部分遵循正常的类型语法(让它包含元组)。

实际上,元组和构造函数遵循完全相同的语法:构造函数只是一个前面有名称的元组:

tuple/constructor == [name of] type [* type] [* type] ...

所以, *在构造函数定义中不是元组语法的一部分,它们是构造函数语法的一部分。您实际上将构造函数定义为 此名称,后跟 N 个参数 而不是 此名称,后跟一个元组参数 .

这种微妙的行为差异背后的原因是性能之一。现在,元组和构造函数在内存中表示如下:
[TYPE] [POINTER] [POINTER] [POINTER]

这是一个相当紧凑和有效的表示。如果构造函数的多个参数确实可以作为元组访问,这将需要运行时独立于构造函数来表示该元组(以便它可以独立寻址),因此它看起来像这样:
[TYPE] [POINTER]
|
v
[TYPE] [POINTER] [POINTER] [POINTER]

这将使用略多的内存,使用构造函数时需要两倍的分配,并降低模式匹配元组的性能(因为额外的取消引用)。为了保持最大性能, name of type * type使用第一个模式表示,您需要明确键入 name of (type * type)切断 *来自 of从而回到第二个模式。

请注意,这两种模式都是通过相同的模式匹配和构造语法访问的: name (arg,arg) .这意味着类型推断无法根据使用情况推断出模式。这对于通常在类型定义中定义的普通构造函数来说没有问题,但它会导致变体(不需要初步定义)自动回退到第二个版本。

关于类型的内存表示的附加阅读 here .

关于ocaml - 用元组作为参数定义异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3940345/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com