Clojure 函数与方法的设计哲学

Clojure design philosophy of functions vs methods

经常被引用

"It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures." — Alan Perlis

这是在 Clojure 及其库中经常观察到的东西,例如

gist这里,Rich解释了clojure.xml的设计原理,一旦XML文件被读取,它就被转换成地图,然后你就拥有了所有的可根据需要操作这些地图的功能,并且您可以将这些功能与其他地图一起使用

我无法理解这些函数是如何实现的,以操纵代表 XML 的地图,以便在其他任何地方使用?

我的意思是我写的 100 个函数不会特定于 XML 域(即特定于 XML 的地图模式),所以这些 fn 的唯一重用如果地图遵循相同的模式

我错过了什么吗?

来自linked gist

Look at the way clojure.xml processes XML - it deals with an external entity, a SAX parser fronting some XML source, gets the data out of it and into a map, and it's done. There aren't and won't be many more functions specific to XML. The world of functions for manipulating maps will now apply. And if it becomes necessary to have more XQuery-like capabilities in order to handle XML applications, they will be built for maps generally, and be available and reusable on all maps. Contrast this with your typical XML DOM, a huge collection of functions useful nowhere else.

我写的 100 个函数不是特定于 XML 域吗?

没有

因为您不会再与 XML 打交道了。 XML 只是一种标记语言。在其他语言生态系统中(比如 Java),当有人提到 XML 时,它意味着标记语言和(几乎总是)它的扩展和围绕它们构建的工具。 Clojure(至少 clojure.xml)处理 XML 的方式是读取数据,然后在 Clojure 的原生映射中继续处理它。


值得注意的是(截至目前)clojure.xml 只包含一个函数,parse。这意味着它不支持序列化为 XML,也不支持 XML 数据元素的就地编辑。

我认为您将 XML 与 XML 文件的特定实例混淆了。

给定一个特定的 XML 文件,例如:

<xml>
<node1>One</node1>
<node2>Two</node1>
<node3>
  <node31>
    ThreeOne
  </node31>
  <node32>
    ThreeTwo
  </node31>
</node1>
</xml>

确实,例如,您可能希望拥有从 node3 下的子节点获取值的逻辑。因此,也许您有一个名为 get-three-node-child-values 的函数。鉴于另一个 XML 具有不同的结构,没有像上面的 XML 那样有子节点的 node3,该函数将不可重用。

但这不是 Rich 所说的被重用的功能。被重用的函数是您用来实现 get-three-node-child-values 逻辑的函数。因为如果你有一个 XML 对象,那么 XML 对象需要有一个方法来获取节点 3,另一个方法来获取该节点的子节点,另一个方法来获取节点的值那个节点。所有这些方法仅适用于 XML Class 对象,并且必须为此编写。但是如果把XML变成Map,就根本不需要这些方法,也不需要实现。由于 Map 已经具有导航和循环遍历其节点的方法。

希望这样更清楚。