Предметно-ориентированный язык
Предметно-ориентированный язык (англ. domain-specific language, DSL — «язык, специфический для предметной области») — компьютерный язык, специализированный для конкретной области применения (в противоположность языку общего назначения, применимому к широкому спектру областей и не учитывающему особенности конкретных сфер знаний). Построение такого языка и/или его структура данных отражают специфику решаемых с его помощью задач[1]. Является ключевым понятием языково-ориентированного программирования.
Строго говоря, деление языков программирования на языки общего назначения и предметно-ориентированные весьма условно, особенно, если учесть, что формально любой протокол или формат файлов является языком. Существует масса языков общего назначения, применяемых в качестве предметно-ориентированных для определённых задач, и наоборот, предметно-ориентированных языков, применяемых в качестве языков общего назначения. Так, язык ML, породивший целое семейство языков общего назначения (включая Haskell), — изначально разрабатывался в качестве DSL для системы автоматического доказательства теорем LCF. Примером, показывающим условность классификации, служит язык БНФ (и компилятор с него Lex/Yacc): с одной стороны, это яркий пример метаязыка, с другой — он предназначен для одной конкретной задачи.
Терминология
Простейшие предметно-ориентированные языки, используемые в одном конкретном приложении, часто называют «мини-языками»[2].
Мартин Уорд (англ. Martin Ward)[3] в работе «Language Oriented Programming»[4] (которая считается отправной точкой развития ЯОП), использовал термины «problem oriented» и «domain oriented», но в англоязычном научном сообществе прижился термин «domain-specific», причём именно «domain-specific language», а не «domain-specific programming language». В русскоязычной литературе по программированию встречаются варианты «доменно-специфичный», «проблемно-ориентированный», «предметно-ориентированный».
Фаулер[5] и Дмитриев[6] определяют понятие DSL как «урезанный язык программирования (в большинстве случаев неполный по Тьюрингу)».
Примеры
Ведущие исследователи языково-ориентированного программирования (Мартин Уорд, Пол Хьюдак, Валид Таха и другие) приводят следующие примеры предметно-специфичных языков в качестве классических[4][7][8]:
- TeX/LaTeX для подготовки (компьютерной вёрстки) текстовых документов;
- Perl для манипулирования текстами;
- SQL для СУБД;
- Tcl/Tk для графического интерфейса пользователя;
- HTML и SGML для разметки документов;
- Verilog и VHDL для описания аппаратного обеспечения;
- Mathematica и Maple для символьных вычислений;
- AutoLisp для компьютерного моделирования (САПР);
- Prolog для задач, сформулированных в терминах исчисления предикатов;
- ML и Haskell для задач, сформулированных в терминах функций (Haskell временами определяется как DSL для денотационной семантики).
По мнению Валида Тахи, с позиции ЯОП Microsoft Excel оказывается едва ли не наиболее широко применяемым в мире языком программирования[8].
Другими примерами предметно-ориентированных языков служат языки управления базами данных (помимо SQL здесь, к примеру, можно назвать язык FoxPro), командные языки операционных систем (языки интерактивной командной оболочки, прежде всего Unix Shell, языки пакетных заданий, такие как язык JCL и др.)[9], неполные по Тьюрингу языки структурирования данных (XML, .ini, .conf), язык вики-разметки, языки моделирования (UML, GPSS), Erlang для многопользовательских серверов, функционирующих в бесперебойном режиме.
Существуют языки программирования, встроенные в систему управления ресурсами предприятия (язык ABAP в SAP/R3, языки систем Галактика, Парус, 1С, Инфо-Бухгалтер) и применяемые для их дополнения специфичными для конкретной организации модулями. Использование встроенного языка упрощает программирование специфичных задач, поскольку в языке изначально присутствуют понятия предметной области. Некоторые[какие?] геоинформационные системы и САПР также имеют встроенные языки программирования.
Другие примеры:
- G-код — язык программирования устройств с числовым программным управлением (ЧПУ);
- ЯМБ.
Встраиваемые языки
Временами компьютерные языки реализуются зависимым образом, то есть «внутри» транслируемого языка, без которого эти языки не только не способны исполняться, но и зачастую не образуют целостную символьную систему и не обладают Тьюринг-полнотой. Такие языки называются «встраиваемыми предметно-специфичными языками» (англ. embedded DSL, EDSL; иногда DSEL) или просто «встраиваемыми языками» (embedded language)[7][10], а также «языками, реализованными поверх или на основе данного языка».
Текстовые языки
В дополнение к традиционному делению языков на интерпретируемые и компилируемые, встраиваемые языки вводят ещё несколько видов реализации языка:
- чистое встраивание[7];
- использование макросредств языка (и нередко отождествление их с термином «метапрограммирование»), которое, в свою очередь, подразделяется на[11]:
С другой стороны, можно рассматривать реализацию встраиваемого языка как «реализацию без трансляции», подразумевая, что DSL будет являться синтаксическим и семантическим подмножеством языка, в который он встраивается[11].
Язык, используемый в качестве базового для реализации другого, часто называют метаязыком.
Основных причин для разработки встраиваемых текстовых языков три:
- ввод в исходный язык дополнительных возможностей, расширяющих спектр эффективно решаемых задач или синтаксически упрощающих решение часто встречаемых задач;
- интенсивное повторное использование компонентов транслятора базового языка: парсера, механизма типизации, реализации тривиальных вещей (таких как арифметика чисел), оптимизатора и др. Это обеспечивает кратное снижение трудоёмкости реализации придуманного языка, а также высокий уровень качества реализации при использовании безопасного языка в качестве базового;
- получение возможности эффективно смешивать свойства разных самостоятельных языков в единых фрагментах кода, формируя мультипарадигменный язык широкого профиля, исключая необходимость межъязыкового взаимодействия и расширяя возможности оптимизации.
Наиболее частыми примерами языков первой группы могут служить реализации объектно-ориентированных возможностей в функциональных[12] или процедурных[13] языках, и классическим примером служит язык CLOS. Следует отметить, что термин «язык» здесь используется не всегда — временами говорят просто о «реализации в языке новых возможностей» или о «расширении языка подсистемой, нацеленной на решение определённых задач», и нет строго деления на «библиотеки» и «встраиваемые языки», так как формально любой API, протокол или структура данных может рассматриваться в качестве языка[14]. Так, например, неотъемлемой частью языка Lisp является встроенный не полный по Тьюрингу язык S-выражений.
Вторая группа встраиваемых языков наиболее полно представлена в сообществе языка Haskell, и потому сам Haskell временами определяют как «DSL для денотационной семантики»[7]. Примерами могут служить Elm и другие языки, представляющие функциональную реактивную парадигму, а также язык Curry. Временами также встречается похожее выражение в отношении Лиспа: «Lisp — это не язык, а среда для разработки языков». Примером языка, реализованного поверх Лиспа, может служить Qi. Масса встраиваемых мини-языков реализована в языке OCaml посредством модуля CamlpX компилятора. Язык Rebol также проектировался для программирования посредством интенсивной реализации встраиваемых мини-языков. В диалекте Лиспа Scheme посредством языка S-выражений реализован не полный по Тьюрингу язык SXML, воплощающий протокол XML встраиваемым образом.
Встраиваемый язык может иметь самодостаточную полную по Тьюрингу семантику, но тем не менее вместо независимой реализации повторно использовать компоненты базового языка (третья группа, смешение первых двух). Ярким примером является язык Schelog[15], реализующий семантику Пролога внутри диалекта Лиспа Scheme посредством продолжений, и превращающий Пролог из «самостоятельного» языка во встраиваемый. Традиционной учебной или «спортивной» задачей для многих функциональных языков служит реализация поверх рассматриваемого языка какого-либо другого, чаще всего языка логики предикатов первого порядка[16].
В контексте метаязыков самостоятельные языки временами называют «языками первого класса» (по аналогии с сущностями первого класса в языках), а встраиваемые — «объектными языками».
В подавляющем большинстве случаев встраиваемые языки имеют лишь одну поддерживаемую реализацию, и различия в результирующем машинном представлении кода на них зависят лишь от используемого транслятора базового языка. Однако, бывают и исключения — например, язык Concurrent ML (CML), расширяющий Standard ML конструкциями для явного параллелизма, имеет две принципиально различные реализации.
Визуальные языки
Один из языков (базовый или встраиваемый) может быть визуальным, что нередко применяется в пользовательском программировании (англ. end-user development). Типичными примерами таких пар могут служить AutoLisp — AutoCAD и VBA — Microsoft Excel. Подобные пары образуют целостную интерактивную систему, и с точки зрения пользователя невозможно (и не нужно) определить, являются ли визуальные инструменты надстройкой, имитирующей команды встроенного текстового языка, или же текстовый язык управляет визуальными инструментами. Действительные взаимоотношения в этих парах определяются разработчиком.
В паре Emacs — Emacs Lisp отношения более определённые. Лисп традиционно относится к метаязыкам, и в данном случае текстовый редактор надстраивается над ним как визуальный DSL, что и делает последний изменяемым и расширяемым.
В случае, когда оба языка являются визуальными, встраиваемые языки обычно называют иными терминами — плагинами, фильтрами и др., и не используют терминологию языково-ориентированного программирования. Формально же можно говорить, например, что для визуального мета-языка обработки графики Adobe Photoshop есть множество встраиваемых визуальных мини-языков (см. Photoshop plugin).
Функциональные и логические языки программирования выглядят неестественно в визуальном окружении, так как функциональное программирование и логическое программирование в чистом виде запрещают побочные эффекты, и для взаимодействия с GUI; их концептуальную целостность приходится нарушать. С педагогической точки зрения считается желательным преподавание программирования с использованием консольных средств, чтобы сосредоточить внимание студентов на основах алгоритмизации, а не эргономики и тем более не процедурных навыков использования тех или иных IDE[17].
Преимущества и недостатки
Преимущества и недостатки использования в конкретной задаче конкретного DSL вместо языка общего назначения определяются гораздо явственнее, чем преимущества и недостатки использования одного языка общего назначения вместо другого: в большинстве случаев уже разработанный DSL оказывается концептуально неприменим к одним задачам и даёт бесспорный выигрыш по большинству показателей качества в других, а некоторые подзадачи вообще остаются нерешёнными до разработки DSL[4].
Таким образом, вопрос о преимуществах и недостатках корректнее ставить в свете применения языково-ориентированной методологии вместо какой-либо другой при изначальном отсутствии готового DSL, сопоставляя потенциальный выигрыш от его использования с затратами на его разработку и сопровождение.
См. также
Примечания
- А. Я. Фридланд, Л. С. Чанамирова. Информатика и компьютерные технологии: основные термины : толковый словарь. — Астрель, 2003.01.01. — 270 с. — ISBN 9785170145461.
- Bentley - Little languages, 1986.
- Martin Ward’s Homepage
- Ward - Language Oriented Programming, 1994.
- Мартин Фаулер. Языковой инструментарий: новая жизнь языков предметной области. — 2005.
- Сергей Дмитриев (JetBrains). Языково-ориентированное программирование: следующая парадигма // = RSDN Magazine. — 2005.
- Hudak - Modular Domain Specific Languages and Tools, 1998.
- Taha - Domain-Specific Languages, 2008.
- Brett D. Hirsch. Digital Humanities Pedagogy: Practices, Principles and Politics. — Open Book Publishers, 2012. — 450 с. — ISBN 9781909254251.
- Mernik, 2012.
- Czarnecki, O’Donnell, Striegnitz, Taha - DSL implementation in metaocaml, template haskell, and C++, 2004.
- Bernard Berthomieu. OO Programming Styles in ML. — LAAS Report #2000111, Centre National De La Recherche Scientifique Laboratoire d'Analyse et d'Architecture des Systèmes, 2000.
- Cello — library that introduces higher level programming to C
- Хопкрофт, Мотвани, Ульман - Теория автоматов, языков и вычислений, 2001.
- Schelog, 2003.
- Paulson - ML for the Working Programmer, 1996.
- Игорь Головин, Андрей Столяров. Мультипарадигмальный подход к преподаванию программирования и роль свободного ПО // МГУ имени Ломоносова, Тезисы докладов II конференции разработчиков свободных программ "На Протве". — город Обнинск, 2005.
Литература
- Martin Ward. Language Oriented Programming. — Computer Science Department, Science Labs, 1994.
- Paul Hudak. Modular Domain Specific Languages and Tools. — IEEE Computer Society Press, Department of Computer Science, Yale University, 1998. Архивировано 17 октября 2013 года.
- Jon Bentley. Little languages. — CACM, 29(8):711–721, 1986.
- Walid Taha. Domain-Specific Languages. — Department of Computer Science, Rice University, 2008. Архивировано 24 октября 2013 года.
- Marjan Mernik. Formal and Practical Aspects of Domain-Specific Languages. — IGI Global, 2012. — ISBN 978-1-4666-2092-6.
- Джон Хопкрофт, Раджив Мотвани, Джеффри Ульман. Введение в теорию автоматов, языков и вычислений. — 2-е. — Cornell University, Stanford University: Addison-Wesley Publishing Company, Издательский дом «Вильямс», 2001. — 528 с. — ISBN 5-8459-0261-4 (рус.), 0-201-44124-1 (англ.).
- Lawrence C. Paulson. ML for the Working Programmer. — 2nd. — Cambridge, Great Britain: Cambridge University Press, 1996. — 492 с. — ISBN 0-521-57050-6 (твёрдый переплёт), 0-521-56543-X (мягкий переплёт).
- K. Czarnecki, J. O’Donnell, J. Striegnitz, W. Taha. DSL implementation in metaocaml, template haskell, and C++. — University of Waterloo, University of Glasgow, Research Centre Julich, Rice University, 2004. Архивировано 5 марта 2016 года.
Ссылки
- Dorai Sitaram. Programming in Schelog (недоступная ссылка) (2003). Дата обращения: 18 октября 2013. Архивировано 8 мая 2013 года.
- Compilers and interpreters implemented in Haskell .
- Stumbling Blocks For Domain Specific Languages .