在 Lua 中有一个用于将“self”发送到函数的简短符号,所以a.withdraw(a, 100.0)
可以写成a:withdraw(100.0)
. 难道不应该对 OCaml 做一个类似的扩展,让像这样List.length l
写l::length
和List.map (fun e -> e + 1) l
写l::map (fun e -> e + 1)
吗?
4 回答
几个月前,Fabrice Le Fessant 在 ocaml bugtracker 上提出了这个问题:PR#6012 object-like notation for module functions,灵感来自他在wxOCaml库中的工作(请参阅此 PDF 中的设计说明)。
功能请求引发了讨论(请参阅 PR#6012 链接进行讨论),但我认为共识是这不是一个好主意。人们不喜欢添加特定的语言特性来支持使模块编程类似于对象编程。
我认为你可以将这个想法分解成更小的部分,每个部分都非常有趣,但是需要更多的工作才能被充分理解以集成到成熟的编程语言中。例如,您暗示某种形式的代码推断。
List
是一个 ocaml 模块而不是一个 ocaml 对象。在编写时,List.length
您调用length
属于模块列表的函数(将模块视为命名空间或库,以获得第一直觉)。
从文档中,
模块的主要动机是将相关定义(例如数据类型的定义和对该类型的相关操作)打包在一起,并为这些定义实施一致的命名方案。这可以避免名称用完或意外混淆名称。
此外,对于一个对象,您需要在使用它之前创建一个(使用 new)(在其上调用函数 f,例如,myobject # f
),
一个例子,来自这里的文档,
我们现在创建一个新的点 p,点类的实例。
# let p = new point;;
val p : point = <obj>
我们现在调用 p 的一些方法:
# p#get_x;;
- : int = 0
如果您查看此语法目录,您会发现我在 wxOCaml 上下文中编写的用于执行此操作的 camlp4 语法扩展(它位于 wxOCaml 的分支“wx-syntax”中)。
当前的语法是
module x -> M in E
你可以在哪里使用
x->f
代替
M.f x
在表达式 E 中。我认为后一种语法实际上很好,但我建议通过以下方式更改第一个语法:
let module x -> M in E
取悦压头。语法文件“pa_wx.ml”很短且易于修改,例如,您可以在第 563 行的“drawing.ml”中看到生成的代码。
不是很优雅,因为 OCaml 值和它们的类型都不属于模块。即使我们知道表达式的完整类型,我们也不知道默认情况下应该从哪个模块获取函数。
在代表 的示例l->length
中List.length l
,编译器需要知道我们的想法是l
属于模块List
(它甚至没有为内置类型提供类型别名'a list
)。或者我们的意思是Batteries.List.length
。
因此,需要声明“l 使用模块列表”。