我想知道是否已经存在一些Ocaml的命名约定,特别是对于构造函数的名称,变量的名称,函数的名称以及记录标签的名称。
例如,如果我想定义类型condition
,你建议明确地声明它的构造函数(例如Condition_None
),以便直接知道它是{{1}的构造函数}?
另外,您如何命名此类型的变量? condition
或c
?我总是犹豫使用a_condition
,a
或an
。
要声明一个函数,是否有必要给它一个名称,允许从其名称推断出参数的类型,例如the
?
另外,我在我的程序中使用了很多记录。如何命名记录以使其看起来与普通变量不同?
有很多方法可以命名,我希望找到一个有着良好品味的传统方法,坚持下去,这样我就无需在命名前思考。这是一个公开的讨论,任何建议都将受到欢迎。谢谢!
答案 0 :(得分:5)
您可能对Caml programming guidelines感兴趣。它们涵盖变量命名,但不回答您的确切问题。
关于构造函数命名空间:理论上,您应该能够将模块用作命名空间,而不是在构造函数名称中添加前缀。例如,您可以使用Constructor
模块并使用Constructor.None
来避免与None
类型的标准option
构造函数混淆。然后,您可以使用open
或ocaml 3.12的本地开放语法,或者在有用时使用模块别名module C = Constructor
然后使用C.None
,以避免使用长名称。
在实践中,人们仍然倾向于使用短前缀,例如类型名称大写的第一个字母CNone
,以避免在操作具有相同构造函数名称的两个模块时出现任何混淆;这经常发生,例如,当您编写编译器并且有几个传递操作具有相似类型的不同AST类型时:解析后Let
形式,后键入Let
形式等。
关于你的第二个问题,我赞成简洁。推断意味着类型信息在大多数情况下都是隐式的,您不需要在命名约定中强制使用显式注释。从上下文中可以明显看出 - 或者说不重要 - 操纵什么类型,例如。 remove cond (l1 @ l2)
。如果在remove
子模块中定义了Condition
值,则效果更差。
编辑:记录标签与总和类型构造函数具有相同的作用域行为。如果您在{x: int; y : int}
子模块中定义了Coord
条记录,则可以访问模块外部foo.Coord.x
的字段,或使用别名foo.C.x
或Coord.(foo.x)
3.12的“本地开放”特征。这与sum构造函数基本相同。
在3.12之前,您必须在记录的每个字段上编写该模块,例如。 {Coord.x = 2; Coord.y = 3}
。从3.12开始,您可以限定第一个字段:{Coord.x = 2; y = 3}
。这也适用于模式位置。
答案 1 :(得分:4)
如果您想要命名约定建议,请查看标准库。除此之外,你会发现许多人都有自己的命名惯例,由你来决定信任谁(只是保持一致,即选择一个,而不是很多)。标准库是所有Ocaml程序员共享的唯一内容。
通常,您会在模块中定义单个类型或一组密切相关的类型。因此,您没有名为condition
的类型,而是拥有一个名为Condition
的模块,其类型为t
。 (你应该给你的模块一些其他名称,因为标准库中已经有一个名为Condition
的模块!)。从列表中删除条件的功能是Condition.remove_from_list
或ConditionList.remove
。例如,请参阅标准库中的模块List
,Array
,Hashtbl,
Map.Make`等。
有关定义多种类型的模块的示例,请查看Unix
。这是一个特殊情况,因为这些名称大多来自预先存在的C API。许多构造函数具有短前缀,例如O_
为open_flag
,SEEK_
为seek_command
等;这是一个合理的约定。
没有理由在名称中编码变量的类型。编译器不会使用该名称来推断类型。如果变量的类型对于来自上下文的临时读者不清楚,则在定义时添加类型注释;这样,提供给读者的信息将由编译器验证。