函数式编程中的多个源文件,目录结构和命名空间

时间:2011-03-10 14:40:10

标签: functional-programming lisp arc-lisp

我很惊讶地看到Hacker News的源代码只是一个包含功能定义的平面列表的大文件。 Git Hub - news.arc

这是函数式编程的典型吗?在OOP项目中常见的深层目录结构中有很多短文件来源是不常见的吗?

FP中的模块是否与OOP中的命名空间相同?

3 个答案:

答案 0 :(得分:5)

有许多功能编程语言(FPL),它们非常不同。和Lisp方言一样(如Scheme,Common Lisp,Logo,Arc等)。

它们通常不是围绕类(或类似概念)组织的,并且类通常不与命名空间混淆。

在一些面向对象的语言中,程序由许多类组成,类层次结构(或类似的东西)被映射到目录结构,每个类是一个或多个文件。这导致由许多文件组成的软件系统和作为层次结构浏览这些文件/类的IDE。 (这与原始的Smalltalk不同,后者的代码由浏览器访问,而不是根据文件检索。)

例如,在Common Lisp中,类不是名称空间,方法不附加到单个类(因为有多个方法)。有一个名为'package'的独立构造,它为Lisp符号提供名称空间。典型的软件系统由包含若干相关功能的文件组成。通常,更大的功能单元会获得自己的命名空间。

例如,图形工具包可能有多个名称空间:ui-backend,ui-user,ui-system,ui-drawing,ui-animation。 ui-drawing命名空间可用于多个文件:ui-draw-2d-objects.lisp,ui-draw-3d-objects.lisp,ui-draw-macros.lisp等。单个文件ui-draw-2d-objects.lisp将捆绑绘制2d对象(线条,多边形,圆形,位图等)所需的所有类,方法和变量。

然后开发系统负责提供导航。但通常导航不是分层的,而是基于搜索和检索符号。那么大文件是多么重要。更重要的是,文件对正确的功能进行分组,并在内部进行组织,以便以某种方式识别相关功能。

如果我想要例如识别所有矩形绘图函数,那么我将使用REPL。

在LispWorks中,绘图原语位于“GP”或“GRAPHICS-PORTS”包中。然后,我可以让LispWorks告诉我“GP”包中包含“draw-rect”的所有符号。

CL-USER 10 > (apropos "draw-rect" "GP")
GRAPHICS-PORTS::%DRAW-RECTANGLE (defined)
GRAPHICS-PORTS::DRAW-RECTANGLE-BOUNDS (defined)
GRAPHICS-PORTS::%DRAW-RECTANGLES (defined)
GRAPHICS-PORTS::DRAW-RECTANGLES-BOUNDS (defined)
GRAPHICS-PORTS:DRAW-RECTANGLES (defined)
GRAPHICS-PORTS:DRAW-RECTANGLE (defined)

上面的列表告诉我,每个符号都有一个定义的功能,而单个冒号的符号是'导出的'。

然后我可以使用这些符号来查找更多信息:参数列表,源代码,文档等。 Common Lisp甚至提供标准功能,如DOCUMENTATION,DESCRIBE和ED。

因此,这里的开发不是基于组织到某个类层次结构的许多小文件,而是基于模块和命名空间的层次结构,每个命名空间捆绑存储在一个或多个文件中的大量功能。然后,IDE负责支持非分层浏览和搜索。

答案 1 :(得分:4)

不,模块化编程在FP中也很常见。适用于模块化的一般原则。

例如,在Haskell中,您可以说

import qualified Parsec as P

它为您提供了名称空间P中的Parsec解析库。

模块和命名空间是否与“OOP中的命名空间相同”取决于您的函数语言和OOP语言。 (ML模块与其他语言略有不同。)

答案 2 :(得分:2)

实施语言为Arc,其中succintness是主要设计目标。 news.arc包含在Arc发行版中,可以通过将有用的应用程序打包到单个源文件中来充当该succintness的演示。

这种打包并不一定表示函数式编程中的常见做法,尽管@Rainer指出(+1),但在函数式编程环境中,文件边界通常不那么重要。