4

我读了ESR的一篇名为“如何成为黑客?”的文章。几年前(链接可以在我的个人资料中找到),Eric建议学习LISP。好吧,我正在学习LISP很长一段时间,我非常喜欢它,所以我决定使用它编写一个Web应用程序。在LISP中使用依赖注入(以及IoC容器)的要点

由于我使用Spring一段时间,我认为使用IoC容器和依赖性注入来编写分离的组件并将它们粘合在一起是一个好主意。我在Google上进行了一次强力搜索,结果发现在LISP中没有这样的想法。我想念什么?在LISP中有没有很好的实现这个概念,或者出于某种原因没有意义使用它,这对我还不清楚?

+2

Common Lisp是动态类型的,具有全功能的匿名函数,OO基于泛型函数。我没有足够的IoC/DI模式经验足以确定这是一个完整的答案,但是它们是否不属于语言本身? – Ramarren

+0

这是我希望得到答案的问题。 :) –

+1

@Ramarren,依赖注入只是意味着软件构建块本身并不寻求它们的依赖关系,而是“从外部”接收它们。在我看来,这样的设计模式不能被语言特征所包容,当然不能被动态类型或匿名函数包含。 *可以包含的将是IoC容器,因为完全可以用手组装对象图。也许Lisp非常容易,人们根本不需要任何额外的库来为它们做。 (我很高兴用Objective-C做DI。) – zoul

回答

18

'控制反转'在Lisp中被广泛使用。这是非常简单的,因为函数和闭包是第一类对象。

依赖注入是微不足道的。类和函数可以通过符号和头等类来配置。

您通常不需要政府间海洋学委员会或DI Common Lisp中的一个“框架”,因为很多的功能配置和参数应用程序和库是内置的。

“一流”的意思,有些事情存储在变量中,作为参数传递或作为结果返回。

在像Common Lisp这样的语言中,函数和类是第一类对象。此外,通过后期绑定解耦,您可以使用符号作为它们的名称。 Common Lisp对象系统知道元类和符号是类的名称。即使泛型函数和方法都是对象并且有元类。

如果concurrent-secure-server是一个类,default-response是一个函数,比如,你可以这样做:

(make-instance 'web-services 
       :server-class 'concurrent-secure-server 
       :default-response-function 'default-reponse) 

以上使用符号的名称为类和函数。如果函数获得新版本,则Web服务可能稍后调用新版本。

或者:

(make-instance 'web-services 
       :server-class (find-class 'concurrent-secure-server) 
       :default-response-function #'default-reponse) 

在上述情况下,我们通过类对象和功能对象。

Common Lisp中的软件模块可以有全局变量,您可以用正确的信息设置:

(defvar *default-server-class* 'concurrent-secure-server) 

另外,您可以设置这些在像下面的槽。

(defclass server-object() 
    ((default-response-function 
     :initarg :default-response-function 
     :initform *server-default-response-function*))) 

(defvar *my-server* 
    (make-instance 'server-object 
        :default-response-function 'my-default-response-function)) 

你甚至可以创建对象,然后在配置阶段改变他们的类。 Common Lisp对象系统允许您更改类并使现有对象得到更新。

如果创建一个实例,你可以只要你想灵活:

  • 你可以在课堂上传递
  • 你可以在参数

像这样通过:

(let ((my-class 'foo-class) 
     (my-args `(:response-function ',*some-reponse-function))) 
    (apply #'make-instance my-class my-args)) 

有时你会看到Lisp库在运行时计算这样的参数列表。

您可以在运行时配置Lisp应用程序的另一件事是通过泛型函数。通用函数允许:before,:after和:around方法 - 它们甚至允许您自己的自定义调用方案。因此,通过使用自己的继承自其他类和mixin类的类,通用函数被重新配置。这就像你有内置面向方面编程的基本机制。

对于那些对这些更高级的面向对象概念感兴趣的人,有一些Xerox PARC的文献,这些问题在CLOS创建时已经被研究过。它被称为“开放实现”,那么:

http://www2.parc.com/csl/groups/sda/publications.shtml

在开放实现方法,模块允许客户在模块自身的实施战略独立控制。这使得客户可以调整模块的实施策略以更好地满足他们的需求,有效地使模块更具可重用性,并且客户端代码更加简单。这种控制通过精心设计的辅助界面提供给客户。

你不需要的一件事:XML。 Common Lisp是它自己的配置语言。例如可以通过宏来编写扩展以实现更简单的配置。加载这些配置可以通过LOAD轻松完成。

+0

这正是我想要的,谢谢! –

+0

现在答案中的链接只是重定向到主要的parc网站。原始内容仍然可以通过backback机器访问:https://web.archive.org/web/20110906111530/http://www2.parc.com/csl/groups/sda/publications.shtml –

3

实际上IoC是大多数Web框架的构建原则,不仅在Java或Lisp中。 考虑到DI,正如Rammaren所指出的那样,它是动态语言(如Lisp)中的隐式模式。如果您比较SpringRestas(支持良好的CL Web框架之一)中的Hello World应用程序,您可以看到自己的情况。你会看到,除了在Lisp中不需要花哨的类型/类/接口声明的东西之外,它们有相同的模式。