简体   繁体   English

将Clojure宏用于DSL

[英]Use of Clojure macros for DSLs

I am working on a Clojure project and I often find myself writing Clojure macros for DSLs, but I was watching a Clojure video of how a company uses Clojure in their real work and the speaker said that in practical use they do not use macros for their DSLs, they only use macros to add a little syntactic suger. 我正在开发一个Clojure项目,我经常发现自己正在为DSL编写Clojure宏,但我正在观看Clojure视频,了解公司如何在实际工作中使用Clojure,而且发言人说在实际使用中他们不使用宏来实现他们的DSL,他们只使用宏来添加一点句法。 Does this mean I should write my DSL in using standard functions and then add a few macros at the end? 这是否意味着我应该使用标准函数编写我的DSL,然后在最后添加一些宏?

Update : After reading the many varied (and entertaining) responses to this question I have realized that the answer is not as clear cut as I first thought, for many reasons: 更新 :在阅读了这个问题的许多不同(和有趣的)回答后,我意识到答案并不像我最初想的那样明确,原因有很多:

  1. There are many different types of API in an application (internal, external) 应用程序中有许多不同类型的API(内部,外部)

  2. There are many types of user of the API (business user who just wants to get something done fast, Clojure expert) API的用户有很多种类(商业用户只想快速完成某项工作,Clojure专家)

  3. Is there macro there to hide boiler plate code? 是否有宏隐藏锅炉板代码?

I will go away and think about the question more deeply, but thanks for your answers as they have given me lots to think about. 我会离开并更深入地思考这个问题,但感谢你的回答,因为他们给了我很多思考。 Also I noticed that Paul Graham thinks the opposite of the Christophe video and thinks macros should be a large part of the codebase (25%): 另外我注意到Paul Graham认为与Christophe视频相反,并认为宏应该是代码库的很大一部分(25%):

http://www.paulgraham.com/avg.html http://www.paulgraham.com/avg.html

To some extent I believe this depends on the use / purpose of your DSL. 在某种程度上,我认为这取决于您的DSL的用途/目的。

If you are writing a library-like DSL to be used in Clojure code and want it to be used in a functional way, then I would prefer functions over macros. 如果您正在编写类似于库的DSL以在Clojure代码中使用并希望以功能方式使用它,那么我更喜欢基于宏的函数。 Functions are "nice" for Clojure users because they can be composed dynamically into higher order functions etc. For example, you are writing a functional web framework like Ring . 函数对于Clojure用户来说是“不错的”,因为它们可以动态组合成更高阶的函数等。例如,您正在编写像Ring这样的功能性Web框架。

If you are writing a imperative DSL that will be used pretty independently of other Clojure code and you have decided that you definitely don't need higher order functions, then the usage will be pretty similar and you can chose whichever makes most sense. 如果您正在编写一个命令式的DSL,它将独立于其他Clojure代码使用,并且您已经确定您绝对不需要更高阶的函数,那么使用情况将非常相似,您可以选择哪个最有意义。 For example, you might be creating some kind of business rules engine. 例如,您可能正在创建某种业务规则引擎。

If you are writing a specialised DSL that needs to produce highly performant code , then you will probably want to use macros most of the time since they will be expanded at compile time for maximum efficiency. 如果您正在编写需要生成高性能代码专用DSL ,那么您可能希望在大多数时间使用宏,因为它们将在编译时进行扩展以实现最高效率。 For example, you're writing some graphics code that needs to expand to exactly the right sequence of OpenGL calls...... 例如,您正在编写一些需要扩展到完全正确的OpenGL调用序列的图形代码......

Yes! 是!

Write functions whenever possible. 尽可能编写函数。 Never write a macro when a function will do. 当函数执行时,永远不要编写宏。 If you write to many macros you end up with somthing that is much harder to extend. 如果你写了许多宏,你最终会得到更难扩展的东西。 Macros for example cant be applied or passed around. 例如,宏不能应用或传递。

Christophe Grand: (not= DSL macros) Christophe Grand :(不是= DSL宏)

http://clojure.blip.tv/file/4522250/ http://clojure.blip.tv/file/4522250/

No! 没有!

Don't be afraid of using macros extensively. 不要害怕广泛使用宏。 Always write a macro when in doubt. 如果有疑问,请务必写一个宏。 Functions are inferior for implementing DSLs - they're taking the burden onto the runtime, whereas macros allows to do many heavyweight computations in a compilation time. 功能不如实现DSL - 它们将负担带到运行时,而宏允许在编译时进行许多重量级计算。 Just think of a difference of implementing, say, an embedded Prolog as an interpreter function and as a macro which compiles Prolog into some form of a WAM. 只需要考虑实现嵌入式Prolog作为解释器功能和将Prolog编译成某种形式的WAM的宏的区别。

And do not listen to those who say that "macros cant be applied or passed around", this argument is entirely a strawman. 并且不要听那些说“宏不能被应用或传播”的人,这个论点完全是一个稻草人。 Those people are advocating interpreters over compilers, which is simply ridiculous. 那些人提倡翻译编译器,这简直太荒谬了。

A couple of tips on how to implement DSLs using macros: 关于如何使用宏实现DSL的一些技巧:

  • Do it in stages. 分阶段做。 Define a long chain of languages from your DSL to the underlying Clojure. 定义从DSL到底层Clojure的长链语言。 Keep each transform as simple as possible - this way you'd be able to easily maintain and debug your DSL compiler. 保持每个变换尽可能简单 - 这样您就可以轻松维护和调试DSL编译器。
  • Prepare a toolbox of DSL components that you will reuse when implementing your DSLs. 准备一个DSL组件工具箱,在实施DSL时将重复使用。 It should include target languages of different semantics (eg, untyped eager functional - it is Clojure itself, untyped lazy functional, first order logic, typed imperative, Hindley-Millner typed eager functional, dataflow, etc.). 它应该包括不同语义的目标语言(例如,无类型的急切功能 - 它是Clojure本身,无类型懒惰功能,一阶逻辑,类型命令,Hindley-Millner类型渴望功能,数据流等)。 With macros it is trivial to combine properties of all that target semantics seamlessly. 使用宏,无缝地组合所有目标语义的属性是微不足道的。
  • Maintain a set of compiler-building tools. 维护一组编译器构建工具。 It should include parser generators (useful even if your DSLs are entirely in S-expressions), term rewriting engines, pattern matching engines, implementations for some common algorithms on graphs (eg, graph colouring), etc. 它应该包括解析器生成器(即使你的DSL完全在S表达式中也很有用),术语重写引擎,模式匹配引擎,图形上一些常见算法的实现(例如图形着色)等。

Here's an example of a DSL in Haskell that uses functions rather than macros: 这是Haskell中使用函数而不是宏的DSL的示例:

http://contracts.scheming.org/ http://contracts.scheming.org/

Here is a video of Simon Peyton Jones giving a talk about this implementation: 以下是Simon Peyton Jones的视频,介绍了这种实现:

http://ulf.wiger.net/weblog/2008/02/29/simon-peyton-jones-composing-contracts-an-adventure-in-financial-engineering/ http://ulf.wiger.net/weblog/2008/02/29/simon-peyton-jones-composing-contracts-an-adventure-in-financial-engineering/

Leverage the characteristics of Clojure and FP before going down the path of implementing your own language. 在沿着实现自己语言的道路前,充分利用Clojure和FP的特性。 I think SK-logic's tips give you a good indication of what is needed to implement a full blown language. 我认为SK-logic的提示可以很好地说明实现完整语言所需的内容。 There are times when it's worth the effort, but those are rare. 有时候值得付出努力,但这种情况很少见。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM