了解Clojure部分

Understanding Clojure partial

我正在阅读Clojure编程书。 我在一个关于偏子的例子中,它像这样:

1
(def only-strings (partial filter string?))

关键是,如果我编写了下一个函数:

1
(defn only-strings [x] (filter string? x))

我可以得到相同的结果:

1
2
user=> (only-strings [6 3"hola" 45 54])
("hola")

在这里使用局部的好处是什么? 还是只是为了简单地展示它们? 有人可以给我一个例子,其中部分会有用。 非常感谢。


最终这归结为个人风格问题,您使用部分功能所做的任何事情都可以使用匿名函数完成,尽管有时partial使它更漂亮。将前几个参数应用于可变函数是一个示例:

1
2
3
4
user> (def bigger+ (partial + 7 42))
#'user/bigger+
user> (bigger+ 1 2)
52

相比:

1
2
3
4
user> (def bigger+ (fn [& nums] (apply + 7 42 nums)))
#'user/bigger+
user> (bigger+ 1 2)
52

当然,如果您觉得第二个更好,您可以自由选择第二个。


在这种情况下,partial的好处是您可以修复第一个参数并将其绑定到string?

这就是partial的全部。预定义第一个参数,如您和您在Arthur的示例中所见。

1
2
3
4
(def foo (partial + 1 2))

(foo 3 4)    ; same as (+ 1 2 3 4)
;=> 10

在这种情况下,使用局部我将前两个参数绑定到12

为什么这会有用?

您可能要在带有两个参数的函数上使用mapapply。这将是非常糟糕的,因为map和apply具有一个函数,该函数需要一个参数。因此,您可以修复第一个参数并为此使用partial,您将获得一个只需要一个参数的新函数。因此它可以与地图一起使用或应用。

在我的一个项目中,我遇到了这种情况。我考虑过使用partial或匿名函数。因为在一种情况下只需要它,所以我使用了lambda。但是,如果您不止一次需要它,那么比定义带有partial的新函数将非常有用。


这是一个例子:
(请参阅DEFN和DEF之间的区别)

1
2
3
4
5
(defn addDomain [domain user] ( str user domain))  
(def buildEmail (partial addDomain"@domain.com"))
(buildEmail"info")  

;;"[email protected]"


如果您想要一个有关如何使用部分函数的示例,那么有一个在Java世界中很常见的真实示例,其中Java和Spring重新创建了部分函数应用程序(尽管很笨拙)。

假设您有一个在Spring中配置的单例组件FooService,它已配置了单例范围,并向其中注入了一些东西,例如BarDao。 FooService有很多业务方法,例如retrieveBarsForSomeReason()。

当应用程序启动时,它会读取应用程序上下文,该上下文将实例化FooService并将BarDao作为实例变量注入其中。稍后,应用程序将调用FooService上的方法,并将这些方法调用BarDao作为其工作的一部分。

因此,这不是一个真正的对象,这里没有任何面向对象,服务对象上的方法基本上是函数。注入状态(在此示例中为BarDao)等效于使用partial绑定对象,因此您不必在以后的调用中将其包括在内。