在此blog entry by Jim Duey中,他提供了您想要使用monad的原因列表。他的一个原因是:
那么monadic解决方案可能有哪些线索呢?在我看来,无论何时复制和粘贴代码来定义与现有代码类似的新功能,都可能存在潜在的monad。
这实际上非常类似于使用Clojure样式宏的理由。
在这个presentation by Aaron Bedra中 - 他在编写redis驱动程序以生成json时讨论了宏的用例。在幻灯片66上 - 他展示了一个这样的例子。
(defmacro defcommand
[name params]
(let [p (parameters params)]
`(defn ~name ~params
我的问题是 - 在为redis调用而不是宏生成json时,可以使用Monads来解决重复代码的问题吗?
假设
答案 0 :(得分:2)
随时复制和粘贴代码以定义新功能 这类似于现有的
我会创建一个更高阶的函数来摆脱复制粘贴,就像那样简单。
现在,Macro或Monad甚至是一个简单的高阶函数解决了一个目的,但处于不同的概念层面。目的是“抽象出系统中的共同模式”。 您可以在系统中看到出现模式的不同概念级别为:
我知道这听起来非常“抽象”,但是一旦你练习了很多关于如何抽象系统中的一般模式的思考,你最终会得到关于哪种模式使用哪种工具的直觉。
答案 1 :(得分:1)
Monads和宏在不同的抽象层次上运行。
我认为宏是“代码猴子”:任何时候我发现自己写了很多样板文件,我花一点时间思考宏是否可以帮助。
另一方面,Monads是非常强大的抽象,通常用于在纯粹的功能设置中隔离和组合副作用。 (我不是莫纳德的专家,所以请耐心等待。)最重要的是,我认为他们正在解决根本上不同的问题。
如果我们采用您提供的示例,编写Redis驱动程序,访问网络的任何函数都可以通过monad进行抽象 - 在这种情况下,IO和Maybe(或Either)monad都可以。但不是因为重复,而是因为你的功能有副作用。
现在这就是clojure中的Monads可能变得比它值得更难的地方:如果你想组成两个monad,你需要使用monad transformers。显然,这不是由clojure强制实施的,因为它是一种动态语言,所以人们可以认为用动态语言调试组合的monadic代码可能非常困难。像Haskell这样的静态类型系统在这里会有很大的帮助。
因此,虽然redis驱动程序绝对可以用monadic风格编写,但我相信Aaron在演示中所做的是避免重复,为此,我相信宏更适合Clojure。
我希望这有用。
修改强>:
我还应该节点Clojure中的monad在没有Haskell启发的 do 符号的情况下几乎没有用,它基本上可以通过宏实现,从而进一步证明了宏处于不同的抽象层次。