Multiple source files, directory structures and namespaces in functional programming
I was surprised to see that the source code for Hacker News is just one big file containing a fl开发者_开发问答at list of function definitions. Git Hub - news.arc
Is that typical for functional programming? Is it uncommon to have source in a lot of short files in a potentially deep directory structure as is common in OOP projects?
Are modules in FP the same thing as namespaces in OOP?
There are many Functional Programming Languages (FPL) and they are very different. As are Lisp dialects (like Scheme, Common Lisp, Logo, Arc and others).
Often they are not organized around classes (or similar concepts) and classes are often not conflated with namespaces.
In some object oriented languages programs are composed of a lot of classes, the class hierarchy (or something similar) gets mapped to the directory structure and each class is one or more files. This leads to software systems composed of many files and an IDE that browses these files/classes as a hierarchy. (this is different from the original Smalltalk, where code is accessed by browsers and not retrieved based on files).
In Common Lisp for example, classes are not namespaces and methods are not attached to single classes (since there are multi-methods). There is a separate construct called 'package' which provides namespaces for Lisp symbols. There a typical software system is composed of files which bundle several related functionalities. Typically a larger unit of functionality gets its own namespace.
For example a graphics toolkit may have several namespaces: ui-backend, ui-user, ui-system, ui-drawing, ui-animation. The ui-drawing namespace may be used in several files: ui-draw-2d-objects.lisp, ui-draw-3d-objects.lisp, ui-draw-macros.lisp and more. A single file ui-draw-2d-objects.lisp would bundle all classes, methods and variables needed to draw 2d objects (lines, polygons, circles, bitmaps, ...).
The development system then is responsible to provide navigation. But often the navigation is not hierarchical, but based on searching and retrieving symbols. Then it is not really important how large files are. It is more important that files group the right functionality and are internally organized such that related functionality can be identified in some way.
If I want for example to identify all rectangle drawing functions I would then use the REPL.
In LispWorks the drawing primitives are in the package "GP" or "GRAPHICS-PORTS". I can then ask LispWorks to tell me all symbols which contain "draw-rect" in the package "GP".
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)
Above list tells me that each of these symbols has a defined functionality and the ones with the single colon are 'exported'.
Then I can use these symbols to find more information: the argument list, the source code, the documentation and more. Common Lisp even provides standard functions like DOCUMENTATION, DESCRIBE and ED.
Thus developing here is not based on lots of small files organized to some class hierarchy, but as a hierarchy of modules and namespaces, with each namespace bundling a larger amount of functionality stored in one or more files. The IDE is then responsible to support non-hierarchical browsing and searching.
No, modular programming is quite common in FP as well. The same general principles of modularity apply.
In Haskell, for example, you can say
import qualified Parsec as P
which gives you the Parsec parsing library in the namespace P
.
Whether modules and namespaces are the "the same thing as namespaces in OOP" depends on your functional language and your OOP language. (ML modules are a bit different from other languages.)
The implementation language is Arc, in which succintness is a major design goal. news.arc
is included in the Arc distro, and may well be intended as a demonstration of that succintness by packaging a useful application in a single source file.
Such packaging is not necessarily indicative of common practice in functional programming, although as @Rainer points out (+1), file boundaries are often less important in functional programming environments.
精彩评论