2011-03-18 45 views
7

我想运行一个关于Clojure的会话。你能推荐一个可以用Clojure的函数式编程优雅地解决的问题吗?你能指出涵盖这个主题的资源吗?什么是Clojure的优秀展示?

+0

什么样的会话?您是否在寻找可以在一小时,一天,一周内解释的问题和解决方案?有很多可能性。 – 2011-03-18 15:57:00

+0

我们有一个公司广泛的定期展示活动来展示新技术。它的目的是作为一个2小时的会议。 – spa 2011-03-19 18:57:37

回答

12

很多使用Clojure的论点似乎与它处理并发的,但我不会在这里触及这个问题。

我将列出一些我不得不周一周与Java交流的问题,以及我如何在Clojure中解决这些问题。

不变性

在Java中实现不变性是非常非常难。除了遵循严格的编码习惯之外,您还必须非常仔细地选择您的框架和库。此外,作为副作用,您将编写大量代码来制作干净且可用的API,或者强制客户端处理它。

final Person person = personDao.getById(id); 
// I would like to "change" the person's email, but no setters... :(

在Clojure中你基于不可变的数据结构,以便所有的对象都是不可变默认情况下,并且由于这个模型的Clojure您的数据提供了其对这些结构的操作强大的功能。

(let [person   (get-by-id person-dao id) 
     person-with-email (assoc person :email email)] 
    ; Use person-with-email... 

转换

在Java中你有一个域类Person与领域idnameemailsocialSecurityNumber等。您正在创建一个Web服务来检索数据库中所有人员的姓名和电子邮件。您不想公开您的域名,因此您创建了一个类别PersonDto,其中包含nameemail。这很容易,所以现在你需要一个函数来将数据从Person映射到PersonDto。大概是这样的:

public class PersonPopulator { 
    public PersonDto toPersonDto(Person person) { 
     return new PersonDto(person.getName(), person.getEmail()); 
    } 

    public List<PersonDto> toPersonDtos(List<Person> persons) { 
     List<PersonDto> personDtos = new ArrayList<PersonDto>(); 
     for (Person person : persons) { 
      personDtos.add(toPersonDto(person)); 
     } 
     return personDtos; 
    } 
} 

好清楚,没有那么糟糕,但如果你想要把更多的数据的DTO?那么toPersonDto中的构造函数代码会增长一点,不用担心。如果有两种不同的使用情况,一种是上述情况,另一种情况下我们只想发送电子邮件?那么我们可以离开name空(坏主意)或创建一个新的DTO,也许PersonWithEmailDto。所以我们会创建一个新类,一些新的方法来填充数据......你可能会看到这是怎么回事?

Clojure的,动态类型语言,不变的数据结构,可以让我做到这一点:

(defn person-with-fields [person & fields] 
    (reduce #(assoc %1 %2 (get person %2)) {} fields)) 

(person-with-fields {:id 1 
        :name "John Doe" 
        :email "[email protected]" 
        :ssn "1234567890"} :name :email) 
; -> {:email "[email protected]", :name "John Doe"} 

而且操作人员名单:

(map #(person-with-fields % :name :email) persons) 

还增加了临时数据到人会很容易:

(assoc person :tweets tweets) 

而这会打破一切。在Java中,如果你的对象是不可变的,他们可能没有setter,所以你必须编写大量的样板才能修改一个字段(new Person(oldPerson.getName(), oldPerson.getEmail(), tweets)),或者创建一个全新的类。可变对象提供了一个很好的API(oldPerson.setTweets(tweets)),但难以测试和理解。

测试

很多Java代码是基于一些国家,即使没有必要为它。这意味着你可以模拟这种状态,这通常意味着额外的样板,如果你还没有创建可测试性的代码,就会变得更加困难。另一方面,没有嘲讽的测试通常很慢,并且依赖于数据库访问或时间或其他确实会不时出现的错误。

在编写Clojure时,我注意到我实际上并不需要那么多的状态。绝大多数情况下,当我从“外部”检索某些内容时,无论是数据库还是某种Web服务。

摘要

我的代码是一个管,从一端我得到一些数据,该数据然后在经过滤的管变化,转化或与一些其它数据连接它,直到它到达的端部管道。在管道内部,不需要真正改变数据,但是很多情况下强大的函数和不可变的数据结构都是有用的,这就是为什么Clojure使用这样的代码创造奇迹的原因。

+0

哇,很好的例子。 – defhlt 2012-08-09 10:06:44

+0

我喜欢这个总结。这正是我在Clojure工作三个月的感觉。 – 2014-02-01 17:40:40

1

几个月前我遇到了同样的问题,我们决定在Clojure中解决'蒙娜丽莎'的问题。结果是this presentation。基本上我们表明,Clojure对于解决“代码作为数据”提供优雅解决方案的问题非常酷。例如在遗传算法中。

相关问题