2013-12-18 1 views
4

Интересно, способен ли Dart выполнять закрытие во время выполнения с поддержкой такого делегата, на что способен Groovy? См. Этот пример для лучшего понимания: A Groovy DSL from scratch in 2 hours.Поддерживает ли Dart письменные встроенные DSL?

У меня есть DSL, написанная в Groovy для легкого определения записей в библиотеке 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" 
    } 
} 

Вы можете удивиться: почему это не может быть выражено в JSON? С такой DSL я могу сделать намного больше, чем выражать данные. Поскольку он встроен, вы можете делать что-либо внутри DSL, что действительно на главном языке (в данном случае Groovy). Вы можете сделать цикл for, если вам нужно определять одно и то же несколько раз только с разными значениями, вы можете использовать выражения GString, вызывать базу данных, получать доступ к файлам и т. Д. С помощью DSLD IDE знает вашу концепцию так же, как если бы она всегда был частью языка, он может предложить вам инструменты помощи. Это очень выразительно и интуитивно понятно.

Аналогичная вещь для Дарта - это то, что я ищу.

+0

Домен специфический язык - где код написан на одном языке, а ошибки даны в другом :) –

+0

Не могли бы вы подробнее рассказать об этом? :) Я использую DSL в настоящее время только для небольших задач. Но, возможно, я должен быть более осторожным, прежде чем рассматривать его для чего-то большего. Есть ли какая-либо статья о недостатках DSL? – NagyI

ответ

4

Dart не имеет встроенной поддержки для DSL. Тем не менее, вы можете использовать method cascades и operator overloading для получения базовых DSL в некоторых случаях.

Для вашего примера необходимы только каскады метода. Вы можете увидеть некоторые хорошие примеры перегрузки оператора в parsers library и Fuzzy 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')); 

Loops не может быть добавлен в этом, но вы можете определить методы, которые принимают данные и функции для создания полей на основе этих данных :

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

Спасибо! Похоже, это самое близкое, что мы можем сделать с Дартом прямо сейчас. – NagyI

0

Вы должны изучить sweet.js, которые предоставляют гигиенические макросы для JavaScript. Вы можете написать макросы, чтобы принять DSL, который вы хотите. При компиляции вы получаете файл JavaScript, который вы должны включить. Затем вы можете использовать DSL непосредственно из JavaScript или Dart.

+2

Спасибо. Я посмотрю, но мне не нравится идея, что я должен смешать Javascript и Dart для этого. Мне нравится держать этот чистый Дарт, если это возможно. – NagyI

 Смежные вопросы

  • Нет связанных вопросов^_^