Веб-разработчики все чаще используют такие языки, как CoffeeScript и SCSS, которые компилируются в другие текстовые исходные языки, которые выполняются в браузере. Такие компиляторы от источника к источнику (также называемые транспиляторами [1] ) не новы, Cfront широко использовался в первые дни C ++ для генерации целевого C-кода. Но для меня есть разница, которая выбирает CoffeeScript и SCSS в качестве прозрачных компиляторов.
С большинством компиляторов вас не очень заботит то, что генерируется в нисходящем направлении. Пока это следует семантике исходного языка, это фактически большой кусок битов. Но если вы собираетесь генерировать JavaScript для браузера, с этим невежеством трудно справиться. Среды отладки в наши дни становятся довольно изящными, но все они с точки зрения триады HTML / CSS / JavaScript. Поэтому важно, чтобы вы понимали, как ваш язык ввода переводится в свою исполняемую цель.
Это ограничение оказывает большое влияние на исходный язык. Вы должны убедиться, что выходные данные очень четко соответствуют источнику. Когда я пишу этот CoffeeScript
$(window).on 'touchTap', (event) -> window.touchPanel.tap(event)
Я могу легко распознать полученный JavaScript в моем отладчике браузера
$(window).on('touchTap', function(event) { return window.touchPanel.tap(event); });
Это остается верным даже для более сложных фрагментов преобразования CoffeeScript, таких как поворот
runSetupBuild: (slide, positionClass) -> switch positionClass when 'current', 'next' @buildsFor(slide)?.setupBuild?.forwards() # ...
в
Infodeck.prototype.runSetupBuild = function(slide, positionClass) { var _ref, _ref1, _ref2, _ref3; switch (positionClass) { case 'current': case 'next': return (_ref = this.buildsFor(slide)) != null ? (_ref1 = _ref.setupBuild) != null ? _ref1.forwards() : void 0 : void 0; /* ... */
В этом преобразовании многое происходит, но все же соответствие довольно ясно. Если мне нужно отладить этот код, я могу легко увидеть, как он соответствует исходному CoffeeScript. Это суть того, что делает процесс компиляции прозрачным — намерение работать на языке вывода [2] .
Напротив, существуют компиляторы от источника к источнику, которые не ожидают, что вы будете работать на языке вывода, или не рассматривают видимость языка вывода как неудачный временный механизм. Они все еще могут быть полезны, и вы видите их в мире javascript с такими языками, как Dart, GWT и ClojureScript. Именно эта разница в намерениях и отличает прозрачный стиль переноса от более распространенного подхода. [3]
Тот факт, что вы должны работать над поддержанием прозрачности компиляции, накладывает ограничения на то, что вы можете делать на исходном языке. У вас нет той степени свободы в ваших языковых конструкциях, которую вы получаете с более непринужденной формой компиляции. Вы должны следовать базовой семантике целевого языка и придерживаться практически одинаковой структуры программы. Эти ограничения широко не обсуждались как особенность языкового дизайна.
CoffeeScript иллюстрирует, что, несмотря на эти ограничения, вы можете получить значительную разницу в синтаксисе между исходным и целевым языками. CoffeeScript гораздо больше похож на Python в синтаксисе, чем на C-подобный JavaScript. Такое синтаксическое изменение не всегда имеет место, действительно есть важное подмножество прозрачных языков компиляции, которые стремятся быть надмножеством целевого языка. SCSS и TypeScript вписываются в эту категорию — любое выражение CSS допустимо в SCSS. Использование языка надмножества делает переписку еще более ясной, и я чувствую, что она работает хорошо для CSS, где синтаксис CSS работает хорошо, но язык упускает некоторые удобные функции.
Некоторые говорят, что нет смысла использовать прозрачную компиляцию — если вы должны понимать целевой код для отладки, какова ценность использования другого источника? Для меня ценность заключается в нескольких направлениях. Прежде всего, это способ получить полезные языковые функции, которые отсутствуют в целевом языке. SCSS дает мне полезные возможности , такие как переменные (так что я могу сказать , $light-purple
вместо того , чтобы #f8c8fe
и изменить его в одном месте я должен хотеть , чтобы настроить его).
Более радикальные изменения синтаксиса, такие как CoffeeScript, требуют более строгого обоснования. Один из моих коллег очень хорошо выразился после завершения проекта. Он опытный программист JavaScript, и проект с самого начала написал хорошо дисциплинированный JavaScript. В результате он был очень доволен качеством кодовой базы JavaScript. Однако он все же пришел к выводу, что им лучше было бы работать с CoffeeScript, потому что легче понять, что происходит, когда вы читаете CoffeeScript, даже когда вы отлаживаете сгенерированный код JavaScript. Трансформация может не выглядеть такой большой проблемой для маленьких фрагментов, таких как те, что я показываю выше. Но это имеет большое значение, как только вы до сотен строк кода, не говоря уже о. [4]
1: Охота вокруг использования, мне кажется, что термин «транспортер» используется как синоним компилятора «источник-источник». Таким образом, транспортеры могут быть или не быть прозрачными. Я также видел термин «перевод из источника в источник», эквивалентный термину «компиляция из источника в источник».
2: Даже с непрозрачной компиляцией есть случаи, когда люди изучают результаты. Иногда встречаются странные поведения или ошибки, которые требуют, чтобы вы копались в выходных данных компилятора. Некоторым программистам нравится понимать, что делает компилятор, хотя это становится все менее распространенным, поскольку компиляторы и виртуальные машины становятся более сложными. Но такая деятельность является исключением.
3: интересно видеть, сдвинет ли разработка исходных карт языки как coffeescript от прозрачности.
4: я только сделал несколько сотен строк coffeescript, работая над моими информационными колодами, но я согласен с ним и буду продолжать использовать coffeescript для любых нетривиальных объемов javascript.