在编写redis json驱动程序时monad可以替换宏吗?

时间:2013-11-17 04:36:36

标签: macros clojure monads

在此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来解决重复代码的问题吗?

假设

  • 我知道在Clojure中选择一个monad的宏是更惯用的。出于这个问题的目的,我选择忽略惯用的东西,只看一下可能的东西。

2 个答案:

答案 0 :(得分:2)

  

随时复制和粘贴代码以定义新功能   这类似于现有的

我会创建一个更高阶的函数来摆脱复制粘贴,就像那样简单。

现在,Macro或Monad甚至是一个简单的高阶函数解决了一个目的,但处于不同的概念层面。目的是“抽象出系统中的共同模式”。 您可以在系统中看到出现模式的不同概念级别为:

  • 相同的代码块 - 使用函数/高阶函数
  • 相同的代码块,但需要某种“编译时”预处理才能使其抽象化 - Macro
  • “具有某种背景的盒子里面的值”的模式,它符合monad法则 - Monads。 (也许,IO,List - 所有这些都是API模式,我们在一个带有某些上下文的框中看到一个值)

我知道这听起来非常“抽象”,但是一旦你练习了很多关于如何抽象系统中的一般模式的思考,你最终会得到关于哪种模式使用哪种工具的直觉。

答案 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 符号的情况下几乎没有用,它基本上可以通过宏实现,从而进一步证明了宏处于不同的抽象层次。