Lisp-family:如何逃避面向对象的java式思维?

art*_*ter 11 lisp scheme functional-programming clojure racket

背景故事:我在Java中做了很多大型且相对复杂的项目,在嵌入式C编程方面有很多经验.我已经熟悉了scheme和CL语法,并用racket编写了一些简单的程序.

问题:我已经计划了一个相当大的项目,并希望在球拍中做到这一点.我听说过很多的"如果'获取’口齿不清,你会成为一个更好的程序员"等,但每一次我尝试计划或编写一个程序我还是"分解"的任务与接口熟悉的有状态的对象时.
是否有针对lisp的"设计模式"?如何"获得"lisp-family"mojo"?如何逃避面向对象约束你的思考?如何运用强大的宏观设施推动的功能性编程思想?我尝试在github上研究大项目的源代码(例如Light Table)并且更加困惑,而不是开悟.
EDIT1(不那么暧昧的问题):关于这个主题是否有很好的文献,你可以推荐或者是否有用cl/scheme/clojure编写的高质量的开源项目,可以作为一个很好的例子吗?

Gre*_*ott 6

多年来,许多"范例"已经形成:结构化编程,面向对象,功能等等.更多内容将会出现.

即使在一种模式不合时宜之后,它仍然可以很好地解决首先使它受欢迎的特定问题.

因此,例如,使用OOP进行GUI仍然很自然.(大多数GUI框架都有一堆由消息/事件修改的状态.)


球拍是多范式的.它有一个class系统.我很少使用它,但是当OO方法对问题有意义时它是可用的.Common Lisp有多种方法和CLOS.Clojure有多种方法和Java类互操作.

无论如何,基本的有状态OOP~ =在闭包中改变一个变量:

#lang racket

;; My First Little Object
(define obj
  (let ([val #f])
    (match-lambda*
      [(list)         val]
      [(list 'double) (set! val (* 2 val))]
      [(list v)       (set! val v)])))

obj           ;#<procedure:obj>
(obj)         ;#f
(obj 42)
(obj)         ;42
(obj 'double)
(obj)         ;84
Run Code Online (Sandbox Code Playgroud)

这是一个伟大的对象系统吗?不.但它可以帮助您看到OOP的本质是使用修改它的函数封装状态.你可以轻松地在Lisp中做到这一点.


我得到的是:我不认为使用Lisp是关于"反OOP"还是"支持功能".相反,它是一种很好的方式来使用(并在生产中使用)编程的基本构建块.您可以探索不同的范例.您可以尝试诸如"代码是数据,反之亦然"之类的想法.

我不认为Lisp是某种精神体验.至多,它就像Zen,而satori意识到所有这些范例都只是同一枚硬币的不同侧面.他们都很精彩,他们都很糟糕.指向解决方案的范式不是解决方案.等等等等等等.:)


我的实际建议是,听起来你想要完善函数式编程的经验.如果你必须第一次在一个大项目上这样做,这是具有挑战性的.但在这种情况下,尝试将程序分解为"维持状态"与"计算事物"的部分.后者是你可以尝试专注于"更具功能性"的地方.寻找编写纯函数的机会.将它们连在一起.了解如何使用高阶函数.最后,将它们连接到应用程序的其余部分 - 这可以继续是有状态的,OOP和命令式.那是好的,现在,也许永远.


stc*_*ang 6

比较面向对象与 Lisp 中的编程(以及一般的“函数式”编程)的一种方法是查看每个“范式”为程序员提供的功能。

在这一推理中,一个观点是着眼于数据的表示,OO 风格使扩展数据表示更容易,但使对数据添加操作变得更加困难。相比之下,函数式风格更容易添加操作,但更难添加新的数据表示。

具体来说,如果有Printer接口,有了OO,添加一个新的实现该接口的HPPrinter类是很容易的,但是如果你想给一个现有的接口添加一个新的方法,你必须编辑每一个实现该接口的现有类,如果类定义隐藏在库中,这将更加困难并且可能是不可能的。

相比之下,在函数式风格中,函数(而不是类)是代码单元,因此可以轻松添加新操作(只需编写一个函数)。但是,每个函数都负责根据输入的种类进行调度,因此添加新的数据表示需要编辑所有对此类数据进行操作的现有函数。

确定哪种风格更适合您的领域取决于您是否更有可能添加表示或操作。

这当然是一个高层次的概括,每种风格都开发了解决方案来应对提到的权衡(例如面向 OO 的混合),但我认为它仍然在很大程度上成立。

这是一篇著名的学术论文,它在 25 年前捕捉到了这个想法。

以下是最近一门课程(我教过的)的一些笔记,描述了相同的哲学。

(请注意,该课程遵循如何设计程序课程,该课程最初强调功能方法,但后来过渡到 OO 风格。)

编辑:当然,这仅回答了您的部分问题,并没有解决宏的(或多或少正交)主题。为此,我参考了Greg Hendershott 的优秀教程

  • 这并不真正适用于像 Common Lisp 对象系统这样的东西,由于开放类的混合、多重继承、平凡的混合、没有接口、方法组合、多方法等,它很容易添加类或方法。等等。 (3认同)