Dart 支持编写嵌入式 DSL 吗?

Nag*_*gyI 4 dsl dart

我想知道 Dart 是否能够在运行时执行闭包,并且具有 Groovy 所具备的委托支持?请参阅此示例以更好地理解:2 小时内从头开始的 Groovy DSL

我有一个用 Groovy 编写的 DSL,用于轻松定义 MARC 库记录。我希望能够通过将定义调用绑定到程序中的委托类来本地处理类似的 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"
   }
}
Run Code Online (Sandbox Code Playgroud)

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

我正在寻找 Dart 的类似功能。

Pix*_*ant 5

Dart 没有任何内置的 DSL 支持。但是,在某些情况下,您可以使用方法级联运算符重载来实现基本 DSL。

对于您的示例,仅需要方法级联。您可以在解析器库模糊逻辑库中看到一些运算符重载的好示例。

以下是代码的方法级联版本可能如下所示:

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'));
Run Code Online (Sandbox Code Playgroud)

不能在其中添加循环,但您可以定义接受数据的方法和基于该数据创建字段的函数:

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]));
Run Code Online (Sandbox Code Playgroud)

这些示例使用以下支持类:

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);
}
Run Code Online (Sandbox Code Playgroud)

由于我不熟悉 MARC 记录,因此我对所有字段使用了相当无用的字段名称 a 和 b,请随意将它们更改为合适的名称。另外,我确信我根据您的代码片段对结构所做的一些假设是错误的,但它们应该很容易改变。