2013-12-18 41 views
4

我不知道Dart是否有能力在运行时执行闭包,而这种委托支持Groovy的能力?请参阅此示例以获得更好的理解:A Groovy DSL from scratch in 2 hoursDart是否支持编写嵌入式DSL?

我有一个用Groovy编写的用于轻松定义MARC库记录的DSL。我希望能够通过将定义调用绑定到我的程序中的委托类来本地处理类似的Dart脚本。

record { 
    leader "00000nam a2200000 u 4500" 
    controlfield "001", "LIB001" 
    controlfield "005", "20120311123453.0" 
    datafield("100") { 
    subfield "a", "Author of record" 
    } 
    datafield("245", "0") { 
    subfield "a", "Title of record" 
    } 
} 

您可能想知道:为什么这不能用JSON表示?有了这样的DSL,我可以做的不仅仅是表达数据。因为它是嵌入式的,所以你可以在主机语言中有效的DSL内执行任何操作(本例是Groovy)。你可以做一个for循环,如果你必须多次使用不同的值定义同一个东西,你可以使用GString表达式,调用数据库,访问文件等等。有了定义好的DSLD,IDE就会知道你的概念,就像它是一样的始终是语言的一部分,它可以为您提供辅助工具。它非常富有表现力和直觉。

Dart的一个类似的事情是我正在寻找。

+0

域特定语言 - 其中代码是用一种语言编写的,错误在另一种语言中给出:) –

+0

请您详细说明这一点吗? :)我正在使用DSLs只用于小任务。但也许我必须更加小心,才考虑使用它来做更大的事情。有没有关于DSL的缺点的文章? – NagyI

回答

4

Dart没有任何对DSL的内置支持。但是,在某些情况下,您可以使用method cascadesoperator overloading来实现基本DSL。

对于您的示例,只需要方法级联。您可以在parsers libraryFuzzy Logic library中看到运营商超载的一些很好的示例。

这里是你的代码的方法级联版本可能是什么样子:

new Record() 
    ..leader = '00000nam a2200000 u 4500' 
    ..controlfield('001', 'LIB001') 
    ..controlfield('005', '20120311123453.0') 
    ..datafield('100', '', 
     new Subfield('a', 'Author of record')) 
    ..datafield('245', '0', 
     new Subfield('a', 'Title of record')); 

循环无法在此添加,但你可以根据这些数据定义方法接受数据和函数来创建领域:

List data = [ 
       ['a', 'Title of record'], 
       ['a', 'Something of record'] 
       ]; 
// Same record code from above with the addition of this line: 
    ..datafields('245', '', data, (e) => new Subfield(e[0], e[1])); 

的示例使用了以下支持类:

class Record { 
    String leader; 
    List<ControlField> controlFields = []; 
    List<DataField> datafieldList = []; 

    void controlfield(String a, String b) { 
    controlFields.add(new ControlField(a, b)); 
    } 

    void datafield(String a, String b, Subfield subfield) { 
    datafieldList.add(new DataField(a, b, subfield)); 
    } 

    void datafields(String a, String b, Iterable data, Subfield f(E e)) { 
    data.forEach((e) { 
     datafieldList.add(new DataField(a, b, f(e))); 
    }); 
    } 

} 

class ControlField { 

    String a; 
    String b; 

    ControlField(this.a, this.b); 
} 

class DataField { 

    String a; 
    String b; 
    Subfield subfield; 

    DataField(this.a, this.b, this.subfield); 
} 

class Subfield { 

    String a; 
    String b; 

    Subfield(this.a, this.b); 
} 

因为我不熟悉MARC记录,所以我已经在所有字段中使用了相当无用的字段名称a和b,随意将它们改为适当的。另外,我确信我根据代码片断对结构进行的一些假设是错误的,但它们应该很容易更改。

+0

不错,谢谢。它并没有解决我所有的标准,但这是一个好的开始。想象一下,我正在迭代一个集合,该集合将作者保存在另一个数据结构中,并根据此插入“245”数据字段。在Groovy中,我可以简单地在记录定义的中间做一个forEach。根据你的定义,我想我唯一的方法是单独创建数据字段定义,然后引用它。就像我会用Java那样做。这可以改进吗? – NagyI

+0

@NagyI哎呀,我忘了循环。我们可以做得比单独的数据字段定义好一点。我们可以有一个方法接受数据和一个函数来创建基于这些数据的字段,因此我们可以避免突破我们的方法级联。我编辑了我的帖子来说明这个例子。缺点是每次你想循环某些东西时都必须创建一个自定义方法。 –

+0

谢谢!看起来这是我们现在可以用Dart做的最接近的事情。 – NagyI

0

你应该看看为sweet.js提供卫生的JavaScript宏。你可以编写宏来接受你想要的DSL。编译后,您将获得必须包含的JavaScript文件。然后,您可以直接从JavaScript或Dart使用DSL。

+2

谢谢。我会看看,但我不喜欢这个想法,我必须混合Javascript和Dart。如果可能的话,我喜欢保持这种纯粹的飞镖。 – NagyI

相关问题