|
锁定老贴子 主题:Ruby DSL
该帖已经被评为良好帖
|
|
|---|---|
| 作者 | 正文 |
|
最后更新时间:2006-09-11
http://forum.javaeye.com/viewtopic.php?p=128602#128602
potian 写道 macro没有利用任何反射能力,和类型也没有关系 Lisp macro(我只知道Common Lisp)的macro主要是开放编译器内部的结构,把词法分析、语法分析和语义分析和执行中间割裂(不过S-Expression非常简单,基本上没有语法),Lisp的S-expression只管形式正确,而Lisp Form才管语义,用户编写的macro扩展的过程是把s-expression翻译成Lisp Form,经过Lisp的编译,然后才被执行。也就是说同一个macro针对不同的数据可能产生不同的Lisp Form(或者说不同的Lisp代码),执行效率也非常高。这是我讲的对同一个类的同一个方法,第一次执行,我们用Ruby的instance_eval 动态根据不同对象生成它自己的singleton method的过程,第2次执行就类似于已经“编译”了。 虽然和你讲的东西都有关系,但我表达的主题不再这些东西上。这并不是动态语言的特性,也不是函数型语言的特性,也不是反射的问题。虽然都有关系。 我不太喜欢看到评论的时候把Ruby/PhP/Python这样列一遍,他们是不同的,只浮在这个层次,那讨论没有任何意义 另外:http://wiki.rubytao.com/RubyTAO/page/show/RubyBlock+vs+LispMacro ---- 补充 http://www.randomhacks.net/articles/2005/12/03/why-ruby-is-an-acceptable-lisp ---- Creating DSLs with Ruby http://www.artima.com/rubycs/articles/ruby_as_dsl.html 中文翻译: 用Ruby 创建领域特定语言(DSL) http://uncutstone.blogdriver.com/uncutstone/1196082.html ---- Agile India 2006 http://202.53.78.202/agile2005/agileindia2006/index.htm --- blog,里面的讨论还算心平气和 http://pluralsight.com/blogs/dbox/archive/2006/05/07/22985.aspx 引用 "DSL" mechanisms in Ruby i'm trying to get the zen of building DSLs using Ruby. After reading a dozen or so pieces referenced by my favorite search engine, I have a feeling I'm still not quite getting it. I grok the various forms of eval (eval, module_eval and instance_eval) as well as the extremely cool Binding feature. I've also seen BlankSlate for eviscerating an object of the methods it picks up from Object. At the end of the day, however, it looks like the whole Ruby/DSL thing is just inventive use of eval + some clever string munging, both of which are pretty doable in Javascript or Python (or even (gasp) C# using the CodeDOM compiler). I'd love nothing more than for the Ruby folks to point me in the right direction. I met someone at the MS Tech Summit last month who's writing a book on this - perhaps he reads my blog and will give me the clue(s) I need. ---- comments One of the aspects that makes Ruby nice for DSLs (IMHO) is the flexibility on use of parentheses in invocations. It seems like a trivial thing, but parentheses are more for machines than for people. ---- 还有很多回复。值得一看。 http://jimweirich.umlcoop.net/articles/buildingwithrake/index.html http://www.martinfowler.com/articles/rake.html ----- 另一个火药味十足的blog讨论。充满了误解和攻击。 被屏蔽了,需要代理。 引用 Everything Old is New Again - The Ruby DSL hype Update: I've received a few mails asking how to go about creating dsl s "the right way" in Ruby. If you are in Bangalore, I suggest you attend the Ruby DSL talk at the Agile India 2006 by my friends Badri and Sudarshan (both Thoughtworkers). Such things are best learned by demonstration than reading about it and the Badri and Sudarshan are probably the best people in Bangalore to learn from. If you are not in Bangalore find someone who knows and ask him to teach you. :-) [Rant] These things have been true from the dawn of programming languages 1. A language with a built in eval function allows you to transform code into a parse tree at runtime. 2. To the degree that the language has a uniform/flexible syntax, this transition between code and data is painless 3. All language transforms consist of two steps . First you convert a string into a data structure called a "syntax tree" . This is called parsing. Then various transformations can be done on this data structure to produce the effect you want. Thus the string "2 + 3" can be converted into a datastructure like "{ operator: "+", operand1:"2", operand2:"3"}". Then you can define various transforms that work on (or "visit" in oo terms) the components of the data structure and do whatever you want. e.g : (pseudocode) def print(anAst) puts anAst.operand1,anAst.operator,anAst.operand2 end def printReversePolish(anAst) puts anAst.operand1,anAst.operand2,anAst.operator end def evaluate(anAst) return anAst.operand1 + anAst.operand2 end anAst = parse("2 + 3") print(anAst) => 2 + 3 printReversePolish(anAst) => 2 3 + evaluate(anAST) => 5 and that is all there is (conceptually) to any langauge transform. 4. Ruby "DSL" s allow people who haven't studied the fundamentals of computer science to think they are discovering something new and amazing. Yes, Ruby allows a somewhat seamless mixing of "pure" ruby and "dsl" code, but this is just as true for any langauge with a built in eval and clean syntax. (lisp, forth, even smalltalk). The built in "eval" takes care of the parsing (as long as the syntax does not vary too widely from ruby syntax) To understand ruby "dsl" s, ignore all the hype (and the forthcoming stream of books explaining how ruby's 'dsl ability' is the next silver bullet that will save enterprise programmers , give their arid lives meaning, and solve world hunger), understand how interpreters work (read "The Essentials Of programming Languages") and meditate on these concepts in ruby - class eval, object_eval, method_missing. if you understand the basics of how languages work, ruby's "dsl" is some (very) old wine in some sparkling new bottles. # The next time someone tries to tell you how he created this uber cool "dsl" in ruby AND that this takes some fundamentally new technique, laugh in his face. Ok , biting your tongue and walking away quietly is almost as good. DSLs like any other programming technique, when used appropriately gives some beneficial effects. But it is no panacea and a casual perusal of the net will reveal a bunch of atrocious dsls . Beware the hype and snake oil. [end Rant] ---------- Comments: I agree with your main point but you've missed what makes people excited about Ruby DSLs. It's not that you can parse some text into an AST and then interpret the AST, it's that you can define a DSL *without* having to parse text into an AST. Any wierdy-beardy Smalltalk or Lisp programmer will tell you that this has been around for a long, long time. In fact, most experienced programmers will tell you that defining languages in which to express the problem and it's solution is the very essence of programming. Yes laugh in their faces. But point them at Abelson and Sussman's Structure and Interpretation of Computer Programs, Paul Graham's On Lisp or any number of books about Smalltalk or functional programming. # posted by Anonymous : 5:02 PM you say , "But point them at Abelson and Sussman's Structure and Interpretation of Computer Programs, Paul Graham's On Lisp or any number of books about Smalltalk or functional programming." which part of "read 'essentials of programming languages' don't you understand? you say "t's not that you can parse some text into an AST and then interpret the AST, it's that you can define a DSL *without* having to parse text into an AST." again which part of 'The built in "eval" takes care of the parsing (as long as the syntax does not vary too widely ffrom ruby syntax)" don't you understand?' And of course you twist my words. I said "The next time someone tries to tell you how he created this uber cool "dsl" in ruby AND that this takes some fundamentally new technique, laugh in his face" note the three letters in bold? the "AND"? hopefully you learned what "and" meant in primary school? It is not the designing or use of dsls which warrant derision , but the claim that is a fundamentally new technique, which exposes ignorance of basic CS. This is exactly the kind of clueless reaction I was warning readers against. Must be nice that you are protected by your anonymity form your own stupidity. Read the damn post before posting vapid rebuttals. Regards, # posted by Ravi : 5:27 PM I see that the usual anonymous idiots have already surfaced :-) You are right to excoriate anyone who claims that ruby's dsl is a fundamentally new programming tecnique. It is no such thing, at least not to people who have had a basic computer science education, let alone any experience with lisp or smalltalk. However, it may be "new" for someone whose only experience in programing is confined to the j2ee or dotNet stacks. If prisoners who've been clapped in irons appear bewildered or ecstatic on being released into the prison courtyard for some exercis in the sunlight, perhaps that is all right :-) I think your problem is that you consistently overestimate the intelligence and programming skill of the average enterprise programmer. Herein the UK, the very best programmers don't work on banking software, they get hired by google. Expecting the average database drone to understand compilers and language processing and compiler theory may be too optimistic :-).Let them part with their money and buy the "Enterprise DSL With Ruby" style books. The book authors have to eat :-) EOPL is an awesome book btw. Your reccomendation is well thought out. If there is one book that cuts through "dsl" hype (or any other buzzwords about languages), EOPL is it. # posted by Joe Williams : 8:25 PM Who is this Joe Williams, who derides the average enterprise programmer ? Provide a link please.Let me read your posts ! Kindly mention your worthiness before ridiculing others. And yeah, Do you work for Google ? I am happy to stay anonymous as i neither work for google nor ridicule the average !! # posted by Anonymous : 1:08 AM dear Anonymous Idiot, You might want to at least make sure your post makes sense before submitting it. "I am happy to stay anonymous as i neither work for google nor ridicule the average" This kind of claptrap as a substitute for logic almost guarantees you are a bad programmer my anonymous friend. If you want to stay anonymous, do so. That has nothing to do with "work for google" or "ridicule the average". No field of work which requires application of logic, would hire you if the above is sample of your thinking. Read up on the "Ad Hominem" fallacy. Criticize what people say, not who they are. As for me, I don't have a blog (so you can't "read my posts") or a web page of my own. Last I checked, neither was mandatory to surf the web (and post blog comments). And I am a scientist, not a programmer. Now to my comments. I said "Expecting the average database drone to understand compilers and language processing and compiler theory may be too optimistic". Now which part of this statement do you disagre with. Why? If you have a logical counter argument, (vs "Joe Williams doesn't have a blog nyah nyah") let us hear it. # posted by Joe Williams : 7:53 AM whoops. This is degenerating into commenters calling each other names again. "Anonymous" did post a reply here is about the only publishable sentence "The gist of what i said is that posting a comment under the garb of anonymity is no different from posting one with a non blogger name." The rest came perilously close to insulting whole nations. ("Englishmen... "). None of that on this blog please. Anyway I am not very sure I agree with the idea that what id people chose is particularly important *as long as* they make sensible arguments. There are good reasons to avoid a blogger id (or prefer "anonymous"). Having said that someone who puts his name on a comment (even without a blogger id) is preferred to one who stays 'anonymous', especially if he/she also writes to me offline or is otherwise known to me. I had hoped that 'anonymous' would take up joe's challenge to identify precisely that he objected to in his *main* argument(== "you can't expect the average enterprise programmer to understand compiler theory" ) and kick start a good discussion. I don't care (much) what id people use. I do care what they post here using that id makes logical sense and targets a good discussion. oh well, # posted by Ravi : 9:53 AM Anonymous, You are so cool and absolutely stupid !! Why do you get so personal, when someone ridicules the average idiot. You stay anonymous, yet give clues to your self.. :) Bwaaahaahaa -) "Never argue with an idiot. A third person can't make out the difference" # posted by Anonymous : 10:20 PM Joe said: "You are right to excoriate anyone who claims that ruby's dsl is a fundamentally new programming tecnique." I'd maintain that Ravi is right to contradict or correct them. As to 'excoriate'? Well, that's a question of politeness and decency. I believe the tone of Ravi's post borders on smug. But since I am commenting on the style of the post and am engaging in a variety of 'ad hominem', I guess I am just about as guilty as he is Anyways, the _content_ of Ravi's post is dead-on, and lucid. It boils down the essence of the metasystems out there, and I'll probably use the same wording when explaining the topic to others. I do have an itch, which cannot be scratched by the typical CS/math analysis of the situation. That itch is the question: why do certain languages permit embeddable DSLs better than others. For a very long while, I had accepted the conventional wisdom that ONLY very-simple syntactical systems with consistent and thorough paradigms could produce these internal DSLs. Smalltalk and Lisp are the poster children of this philosophy: lisp for its near-zero syntax to AST impedance, and Smalltalk for its consistency and access to the Compiler & Stack as objects..... But then Ruby proved that it could be done too. And by 'done' I mean 'done easily' and in a way that seems to encourage programmers to use it. There's no better indicator to success than results: there are clearly more embeddable DSLs in the Ruby world than in a lot of the big enterprise languages. So what is it about Ruby that permits this? It seems to take the opposite tact than a lisp; indeed a lisp purist would certainly disparage its philosophy: tons and tons of syntactic sugar. And yet it has gotten a lot of the same power. (don't get me wrong, when push comes to shove, Lisp will always when out in expressive power) Just something to think about... Daniel Eklund # posted by Daniel Eklund : 12:52 AM "Not all of us have come to programming via academia or with any strong CS background. " I haven't anyway :-). I majored (if spending four years running after girls and rarely attending class can be called "majored") in Industrial engineering and have no formal training in CS and am very much a self taught programmer. Having said that, I get irritated when *basic* computer science is "rediscovered" and worse, repackaged as the next silver bullet(as is beginning to happen with ruby dsls). "But, since he qualifed it with [rant] I'll assume Ravi just wants to get it off his chest" Oh Absolutely. I was doing some technical oversight for a venture capitalist here and someone essentially repackaged html as a ruby "dsl" and wanted funding because of his "cutting edge technology." [hit head on wall] Ruby *is* a marvellous language. "DSL" is a valuable technique to have in your arsenal. But DSLs are NOT a "fundamentally new" technique. It just appears that way to ignoramuses. "why do certain languages permit embeddable DSLs better than others" I would say presence of eval + (relative) simplicity of syntax + the language would enable this. To make it *easy* though some part of the language substarte would need to be exposed in the language itself. Ruby is very much a "son of smalltalk" and though the syntax is not as regular as that of smalltalk or lisp , the uniform use of objects throughout and modelling the language substrate as objects (ruby's weird notion of "metaclass" notwithstanding) enables the meta hackery, imo. Thanks Daniel for a lucid comment. 声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
|
| 返回顶楼 | |
|
最后更新时间:2006-07-13
Below is a blog entry copied from my blog:
Simple Design: "DSL" Reloaded I have been silent about DSL for a while. Now, I am back:) After being thinking for several months, I realized most of time, people don't need domain specific language, they just need the code read more nicely. Then, I come up a idea such kind of requirement doesn't need to involve heavy implementation such as grammar, parser or compiler, it could be simple, and it should be simple! So, is Ruby or Smalltalk the right selection? I have to say, I don't think so. The reason why I am not very keen about the idea using Ruby as the environment to embed so called "DSL"( I still refer to the nicely looking code as DSL, sorry about that), is because the language is not invented to support hosting DSL. Method missing or closure or initial block are not intended to use this way: [code:1]publishing agreement dated '9/20/2005' with_author 'Joe W. Author', social('555-493-3920') for_title 'DSLs for Dummies' report do calculate 'Royalties', as net_retail_sales.during(last_six_months) * 20.percent end [/code:1] We are using Ruby too tricky!!! We are not using it, we are hacking it. The side effect is understanding the inner mechanism behind nice code becoming harder and harder, which is leading us to a dangerous direction. That reminds me of similar experience of C++. After introducing template into C++, I think except STL and several other excellent framework addressing some critical issue (mostly performance), others are simply too smart to be useful. Tons of frameworks inside Boost are just trying to make the code looking nicer... My point is if the language did not support the way of writting code we want, don't hack it using powerful trick to hack it even if the father of the language encourage you to do so. (I don't know the attitude of Matsumoto, but I do know Bjarne speaks a lot about extending C++ using framework). If not hacking a flexible scripting language, what can we choose to implement the so called DSL? The one thing I am sure if we need to write complex grammar for a new DSL (actually a English-like language), we are going the wrong direction. Because human language is too complex to be handled by formal grammar specification. So, I like the philosophy behind embeded DSL(Ruby again...or Smalltalk). The DSL is still embeded in a GPL, but the GPL should support hosting DSL so the implementation doesn't need to be tricky. The initial idea came into my mind back to this Feb. But at that time, I thought what we need is a new lightweighted GPL, but it still need to be weak typed, mordern featured scripting language just like Python, Ruby. Part of the reason is I had another nice idea about how to implement a weak typed scripting language effciently in JVM, but I didn't have passion to carry it into reality. This lead me to a not-that-simple-design... Sadly or luckily... I have to say, after several months, I realized it should be more simple than a new scripting language. Then, what is the simplest desing? How about this: [code:1]assertThat(characterSet, contains('a')); compared with assert_$1$_contains_$2$(characterSet, 'a'); then fommatted to: assert characterSet contains a [/code:1] what we need is a Eclipse plugin to write and read java file in a different view. further more we can that Eclipse displaying inner class like a closure. and $this$ could aslo be a part of the method name to support: [code:1]list.add(item); list.add_$1$_to_$this$(item); add item to list [/code:1] |
|
| 返回顶楼 | |
|
最后更新时间:2006-07-13
我不想讨论的地方就在这里
如果真正要研究Ruby DSL的情况, 1 首先我们必须分析出目前有几种Ruby的DSL(我大致归类有4类),每种DSL实现的基本要素和基本过程是什么 2 什么样的实用情况下会需要什么样的DSL,是不是这些种类我们都需要, 3 对使用者成本如何、有什么好处,或者有什么坏处 4 对开发这种DSL的人需要用到什么Ruby的哪些技术,这些技术又是如何影响DSL的开发和维护的,是不是需要大量的精力开发和维护,会不会太复杂 尽管不可能完整地一下子列出来,但是不把这些问题想清楚,或者不讨论这些问题,套上一个大帽子讨论或者发表一通感想,我认为没多大意义,也不可能深入。 |
|
| 返回顶楼 | |
|
最后更新时间:2006-07-13
同意potian的看法。DSL的受众不同,应用领域不同,其实现会很不一样。相应的评价标准也就不一样。很多时候就是因为大家不是谈着一回事而出争执不休。所以很有必要对于DSL给个分类,然后没一个取一个清晰的名字,赋予清晰的意图和涉众。不然都戴着DSL的帽子来讨论,的确是没有意义。
我目前最感兴趣的是让QA或者StakeHolder能够用很好看的语法来描述验收测试脚本。而且这些验收测试脚本理想地是在操纵系统的UI。这是我比较看好的方向。 |
|
| 返回顶楼 | |
|
最后更新时间:2006-07-14
我们项目已经使用自制QA Testing DSL一段时间了,第一版是用ruby dsl实现的,但是应用效果不好,现在改用antlr + reflection + jsr 223 scripting api实现的jvm脚本.
脚本大致是这个样子的: happy path begin user login goodhope as 'a@a.com' with password 'password'. user goes to holding area of game 'MURed'. assert could see 'some text' on top of this page. assert that items are shown as a list. user selects 2 items 1 pet and 300 money. user packs those items to a bundle. assert should show a confirm page. assert bundle title is 'some thing'. end 语法是简化且修改过的smalltalk语法,去掉了keyword message的':',允许在方法名里是用空格。在parser的实现上我采用了自己一直想尝试的一种作法,我称之为literal white space,也就是像'that' 'this' 'thoes' 'a' 'an'这类的单词和空白等价,可以写出但更接近自然语言的代码。 我们创造了一种叫做agile dsl refining的dsl构造方法,ruby dsl成为一个很好的kick off工具,但是最终dsl被实现成什么样子,这个还是要看项目的需要了,不一定就是ruby dsl。 |
|
| 返回顶楼 | |
|
最后更新时间:2006-07-17
不太理解为什么一定要贴近自然语言。
自然语言的二义性有些不是在语法和语义的层面能够解决的。语言的表达能力(对一个东西能不能表达,花多大代价表达)太强未必是好事情。 对这类扩展方式实现dsl的另一个想法,我估计即使这个玩意儿会流行开来(我不是抱很大希望),也会经历一个优胜劣汰的标准化过程。语言设计的进入成本太低会直接抬高沟通成本 |
|
| 返回顶楼 | |
|
最后更新时间:2006-07-17
hehe, 能另开个帖子介绍下 :antlr + reflection + jsr 223 scripting api实现的jvm脚本么?对这几样东西结合在一起很感兴趣,不过其中antlr感觉不是一个平民级的工具呀,我基本停留在看计算器+-*/语法的水平,看hsql的解释就觉得挺吃力了
|
|
| 返回顶楼 | |
|
最后更新时间:2006-07-17
charon 写道 不太理解为什么一定要贴近自然语言。
自然语言的二义性有些不是在语法和语义的层面能够解决的。语言的表达能力(对一个东西能不能表达,花多大代价表达)太强未必是好事情。 对这类扩展方式实现dsl的另一个想法,我估计即使这个玩意儿会流行开来(我不是抱很大希望),也会经历一个优胜劣汰的标准化过程。语言设计的进入成本太低会直接抬高沟通成本 类自然语言的DSL在我是当作行为艺术来看待的,我猜阁下见了我在java里写的Literal style programming + 水印括号一定会疯掉。因为从实际意义上来讲,完全的nonsense,但是这种style是我欣赏的一种艺术风格。 另外在DSL的时代根本不会有什么标准的语言,都是看受众怎样了,这个风格是QA主导加上一些我的尝试得到的结果。换另外一个人来自然要理解/交流上半天。同样这也是我看来行为艺术的一种,专门为non-DEV写一门语言,而不是教会他们一些通用技术。 |
|
| 返回顶楼 | |
|
最后更新时间:2006-07-18
[quote="raimundox"]我们项目已经使用自制QA Testing DSL一段时间了,第一版是用ruby dsl实现的,但是应用效果不好,现在改用antlr + reflection + jsr 223 scripting api实现的jvm脚本.
脚本大致是这个样子的: happy path begin user login goodhope as 'a@a.com' with password 'password'. user goes to holding area of game 'MURed'. assert could see 'some text' on top of this page. assert that items are shown as a list. user selects 2 items 1 pet and 300 money. user packs those items to a bundle. assert should show a confirm page. assert bundle title is 'some thing'. end [quote] 不太明白, Testing DSL是指测试脚本吧。写测试脚本和写Test Case 然后用Test suit集成相比有什么优势? Testing DSL是一种新的语言,学习它比学习程序语言有什么优势? 这样问:在什么情况下,就是做什么样的项目的时候需要开发Testing DSL? |
|
| 返回顶楼 | |
|
最后更新时间:2006-07-18
[quote="javavsnet"][quote="raimundox"]我们项目已经使用自制QA Testing DSL一段时间了,第一版是用ruby dsl实现的,但是应用效果不好,现在改用antlr + reflection + jsr 223 scripting api实现的jvm脚本.
脚本大致是这个样子的: happy path begin user login goodhope as 'a@a.com' with password 'password'. user goes to holding area of game 'MURed'. assert could see 'some text' on top of this page. assert that items are shown as a list. user selects 2 items 1 pet and 300 money. user packs those items to a bundle. assert should show a confirm page. assert bundle title is 'some thing'. end [quote] 不太明白, Testing DSL是指测试脚本吧。写测试脚本和写Test Case 然后用Test suit集成相比有什么优势? Testing DSL是一种新的语言,学习它比学习程序语言有什么优势? 这样问:在什么情况下,就是做什么样的项目的时候需要开发Testing DSL?[/quote] testing dsl不是给程序员用的,是给QA/Supporting people用的。 |
|
| 返回顶楼 | |











