Nemerle Deep Dive (Владислав Чистяков, ADD-2011)/Стенограмма

Материал из 0x1.tv

Nemerle-deep-dive-2012-04-29-14h53m00s255.png

Здравствуйте, меня зовут Владислав Чистяков, я представляю здесь коммьюнити нового языка программирования Nemerle, и буду рассказывать о нем. На самом деле рассказ будет разделен на две части, в этом зале пройдет только такая, общая презентация, из которого можно будет узнать, что это такое, грубо говоря, на верхнем уровне, и посмотреть, что с этим можно делать. А остальная, большая часть докладов пройдет в другом зале, в малом, это будет дольше, там можно будет задавать серьезные вопросы, показывать код и так далее.

Nemerle-deep-dive-2012-04-29-14h56m36s41.png

Что такое Немерле, зачем он нужен и откуда он появился. Nemerle родился как соединение лучших черт, из трех языков программирования, ну, с небольшой натяжкой, ведь большинство возможностей не стопроцентно заимствованы, а просто похожи на оригинал.

Основной источник заимствования — это C#. Из C# взята система типов, если кто знает такое название — номинативная, это когда тип определяется именем, а не какими-то другими атрибутами.

Из C# позаимствованы естественно позаимствованы классы, перечисления, структуры, ну и так далее, т.е. верхняя часть языка, как можно назвать.

Из ML позаимствованы выражения, т.е. внутренняя часть методов, тот самый код, который мы с вами все время пишем, и такой тип данных, как variant. В ML он назывался discriminated union, это нечто похожее на объединение в C, если кто-то не знаком с ML-подобными языками.

Операторы позаимствованы из С, но также можно сказать, что они позаимствованы из C#, это ведь язык, который является наследником.

Все остальное в языке сделано на базе макросов. Макросы, идея макросов, взята из LISP, но макросы Nemerle очень отдаленно похожи на макросы Лиспа, почему — я расскажу в последствие.

Nemerle-deep-dive-2012-04-29-15h10m27s172.png

Давайте так, сделаем такой простой эксперимент, проведем… поднимите руки те, кто по крайней мере, в общих чертах знает C#? Большинство, я так понимаю.

Ну тогда следующий кадр будет вам понятен, это ничего не делающая программа на C#, демонстрирующая общие элементы языка. Всем видно?

Nemerle-deep-dive-2012-04-29-15h15m42s5.png

Обратите внимание на подсветившиеся красненьким фрагменты, это фрагменты, которые на Nemerle будут не нужны, их можно будет удалить.

Nemerle-deep-dive-2012-04-29-15h17m41s142.png

Вот, как будет эта программа выглядеть, если ее переписать на Nemerle. У нас изменились скобочки, через которые описываются параметры типов, изменилось описание параметров и возвращаемых значений функций, пропал return, (вот назад вернемся — все видели?). Появился module вместо статического класса, фактически это просто синоним, чтобы не писать лишней статики на уровне методов. И не нужно указывать тип при создании объекта, можно сказать что это (def) это аналог var, но на самом деле он вводит неизменяемую переменную, т.е. переменную, которую можно один раз определить, и больше не использовать, т.е. биндинг/байндинг.

Nemerle-deep-dive-2012-04-29-15h15m42s5.png

Кроме того, стали не нужны операторы new (new Test<int>) для создания объекта, теперь это просто функция с именем типа, и не нужно указывать параметры типов, потому, что Nemerle выводит их сам, автоматически, даже в конструкторе и более сложных конструкциях.

Nemerle-deep-dive-2012-04-29-15h17m41s142.png

Очень многие задают вопрос, зачем надо было так менять синтаксис, но тут ответов в общем-то два.

  • Первый резон для изменения синтаксиса — это то, что авторы языка были очень неравнодушны к MLю, и они позаимствовали из него все, что они посчитали более удобным и красивым. Вкусовщина, можно сказать.
  • Второй резон, это то, что язык расширяемый, большая часть конструкций языка сделана на макросах, поэтому языку очень важно иметь регулярную грамматику, чтобы конструкции языка парсились без каких-то там хитрых изысков. Например, в C#, есть как минимум четыре места, которые очень тяжелы для парсинга, соответственно там пишутся очень сложные ручные … или используются весьма мощные генераторы парсеров. По-факту, сегодня все используемые production-парсеры сделаны вручную, или по крайней мере, с ручным участием.
Nemerle-deep-dive-2012-04-29-15h42m48s114.png

Ну вот, здесь объясняется, что является чем, обратите внимание, return например, не нужен. Почему не нужен return — потому что любой блок кода, последнее значение является его возвращаемым.

Одна из особенностей языка, это то, что любая конструкция в усиляемом языке является выражением, т.е нет так называемых statement-ов(…), т.е. если в C# if например, это statement, то в Nemerle if — это выражение. Но если это выражение возвращает void, т.е. ничего не возращает, то оно аналогично стейтменту C#. И так как этого выделения нет, многие операции делаются проще, и удобнее. Например, вы можете использовать try/catch прямо из выражения, вам не нужно какие-то там лишние переменные вводить, что-то там еще делать, вы можете прямо в середине выражения написать try/catch, обработать ошибочку, и прямо там суммирование с чем-то, если у вас там какие-то целочисленные вычисления.

Nemerle-deep-dive-2012-04-29-16h00m33s3.png

Кроме того, Nemerle поддерживает так называемый indent-синтаксис, в стиле python-а или F#-а, F# правда позже появился, значительно. Что некоторым очень нравится, так как значительно визуально сжимает код, может сравнить (см. предыдущий слайд-код), это один и тот же код, только записанный в indent-стиле, и в обыкновенном.

Nemerle-deep-dive-2012-04-29-16h06m57s220.png

Я немножко сейчас отойду от своей презентации, потому что у нас времени не так много в этом зале, и мне придется сокращать.

Nemerle-deep-dive-2012-04-29-16h11m24s65.png

Я попробую своими словами объяснить… ну давайте я расскажу для начала, почему я сказал, что ядро все из ML-я, а потом, объясню, зачем этот язык был создан, и что он дает.

Итак, вот весь список доступных выражений в языке, на экране перед вами. Всем видно, можно прочесть? Ну давайте, я прочитаю, по быстренькому.

Оператор match. Если кто-то программировал на функциональных языках, то практически в любом функциональном современном языке, ну кроме LISPа, наверное, есть оператор match. Это такой switch на стероидах. Т.е. это такой switch, который позволяет не только перейти к какому-то индексу, строке, а позволяет разобрать структуру объектов. Т.е. если у вас есть какая-то сложная структура объектов, то он может прямо…, паттерн…, узнать в этой структуре. Если у вас есть какое-то деревце, ну например, DOM/XML, то вы можете прямо паттерном определить, какой-то там набор объектов и так далее. Очень мощная структура, оператор очень мощный, позволяет в некоторых случаях серъезно упростить решения задач, или сделать их по-другому.

Блоки выражений. Это такие же блоки, как в C#, только они могут возвращать значения, из себя.

Именованные блоки, это замена return-у, на презентации в другом зале я это продемонстрирую, это интересная штука. Они позволяют, например, выйти из трех циклов сразу, и более того — сразу возратить значение какой-то переменной. Это такая структурированная замена break-у. Совершенно безопасная, очень удобная, при этом, собственно, очень мощная.

Связывание def. В отличие от C#, Nemerle пропагандирует функциональное программирование, и поэтому он подталкивает к созданию неизменяемых переменных. По факту, когда вы пишите даже обыкновенный C#-код, большинство переменных могут быть неизменяемые, когда они задаются один раз, а дальше только используются.

Естественно, Nemerle поддерживает и обычное итеративное программирование, поэтому, в язык введена конструкция mutable. Это полный аналог var из C#, т.е. создание переменной, значение которой можно переопределить дальше.

Обработка исключений «throw, try/catch/finally». Это то же самое, как и в C#, только c одним условием, что его можно использовать не только как statement С#, но и внутри выражений. Если у вас есть какое-то вычисление, вы можете защитить кусочек этого вычисления, и вернуть значение по дефолту.

Набор операторов. Фактически весь набор операторов, который здесь присутствует, это полный набор операторов языка. Возможно я здесь что-то забыл, но не думаю, что больше трех каких-то операторов. На самом деле в языке можно использовать огромное количество операторов, даже больше чем в C#, но все остальные операторы сделаны в виде макросов, и являются синтаксическим сахаром, а не базовыми вещами.

Естественно в языке есть вызов функций/методов/индексов, без этого никуда.

Приведение типов. Приведений типов в целом два. Точнее одно из них не совсем приведение типов и называется «уточнение типов». Смысл в том, что это скорее подсказка компилятору, что вы здесь, намерены… считаете, что в этом месте должен быть такой-то тип, например, там int. Вы можете в любом месте программы, в выражении, в if-е, еще где-то там, поставить двоеточие, т.е. написать выражение, двоеточие, и тип. И соответственно, компилятор попытается проверить, что там действительно получается тип int, если у него есть какие-то сомнения, он примет вашу сторону, если он не сможет вывести int, он выдаст ошибку времени компиляции.

Второе приведение типов — это так называемый «ножик-оператор» → выражение, потом оператор, потом тип. Смысл его в том, что это именно динамическая проверка типов. Если вы пытаетесь статически к чему-то привести, например к (???)-стриму, то вам сразу, во время компиляции выдадут сообщение об ошибке, что так нельзя. Соответственно, если нужно сделать какой-то там непонятный ?cast, то нужно привести cначала что-то к object-у, а потом приводить к нужному типу.

Смысл разделения на два оператора в том, что это дает большую надежность коду. Некоторые проверки, некоторые приведения типов в C#, являются грубо говоря затыканием ошибок, т.е. они могут маскировать ошибки. С вот этими двумя операторами такого не получается, они более безопасны.

Литералы. Всем понятно, что они должны быть числовые, строковые, литералы списков (квадратные скобочки и в них значения), литералы массивов (тоже самое, только спереди идет ключевое слово array), литералы символов.

checked — как в C#-е, позволяет задать семантику целочисленных вычислений, с переполнением или без, соответственно, генерировать исключение при переполнении или нет.

Доступ к члену, понятное дело, через точку.

И все. Все остальное в языке, это макросы. При этом язык полностью воспроизводит все конструкции C#, причем с заделом. Есть в нем конструкции, которых, во-первых, нет в C#, во-вторых, многие конструкции, которые есть в C# сделаны более интересно, поддерживают больше возможностей, и соответственно, есть возможность создавать свои собственные конструкции, с помощью универсальных макросов.

Nemerle-deep-dive-2012-04-29-17h19m53s208.png
Nemerle-deep-dive-2012-04-29-17h21m33s28.png

Так, про это я немножно поговорил…

Nemerle-deep-dive-2012-04-29-17h23m21s32.png

Теперь, давайте, грубо говоря, перейдем к тому, что такое макросы, и что с их помощью можно делать.

Nemerle-deep-dive-2012-04-29-17h26m04s108.png

Макросы, грубо говоря, можно разделить на два части. Макросы, которые расширяют язык, позволяя ввести в языке какие-то новые конструкции, и как-то упростить свою личную жизнь, более красиво писать код. Например, если кто-то переходил с Java на C#, обратил внимание, что есть очень удобная конструкция using. Собственно такая конструкция using, она в Nemerle сделана с помощью макросов, и вы можете делать такие конструкции буквально в мгновение ока. Кроме того, макросы могут быть могут быть не синтаксическими. Макросы могут просто изменять поведение кода, или генерировать код в процессе компиляции. При этом макросы могут быть двух уровней:

  • уровня выражения, в выражении макрос будет выглядеть в виде какой-то синтаксической конструкции, или похожим на вызов функции. При этом он будет все-таки не вызовом функции, а будет именно макросом, раскрываться в какой-то другой код, во время компиляции. Но все же, выглядеть он будет, как вызов функции.
  • второй вариант — это метаатрибуты, так называемые. Синтаксически, это такие же, как в С#, атрибуты, но вместо того, чтобы превратиться в метаданные при компиляции, эти атрибуты превращаются в вызовы макросов.

А макрос — это всего лишь функция, на том же самом языке, Nemerle, который позволяет получить доступ у компилируемому проекту, причем, получить доступ в виде синтаксического дерева, с которым довольно удобно работать, у которого есть специальный срез для этой обработки, и собственно, как-то проанализировать этот проект, что-то в нем прочитать, что-то узнать, что-то новое сгенерировать. В принципе, он позволяет, в том числе заменять реализацию тел методов, но в основном, макросы, предназначены для генерации нового кода. Кроме того, макросы можно использовать для контроля за кодом. То есть, если у вас есть какие-то там корпоративные правила, хотя бы например, какая-то замена FxCop → можно проверять наименования, причем очень сложным образом, можно отслеживать… вплоть до порядка объявления переменных. Все что в коде есть, можно отследить с помощью макросов, и выдать диагностические сообщения, вплоть до сообщений об ошибках.

Nemerle-deep-dive-2012-04-29-18h17m24s204.png
Nemerle-deep-dive-2012-04-29-18h18m54s36.png
Nemerle-deep-dive-2012-04-29-18h20m22s226.png
Nemerle-deep-dive-2012-04-29-18h23m58s241.png

Это я уже буду на другом докладе рассказывать…



Nemerle-deep-dive-2012-04-29-18h25m08s146.png

Сейчас мы перейдем к тому, что соотвественно, что макросы могут.

Как я уже говорил, макросы можно разделить на две большие группы: прикладные библиотеки, DSL-и и фреймворки, и на расширения языка.


Nemerle-deep-dive-2012-04-29-18h27m55s122.png

Вот такие прикладные библиотеки уже сделаны сейчас, идут в поставке компилятора, и их можно использовать. Поднимите руки, те, кто программировал на F#. Понятно, двое человек.

Тогда я в двух словах расскажу. В F#-е есть такая замечательная, на самом деле, возможность, так называемых computation expressions. Они позволяют, творить в языке небольшую магию. Есть в функциональном языке, очень непонятная для простых смертных вещь, «монада». Вещь трудна для изучения, понимания, и даже на самом деле, использования. Но позволяет делать иногда очень красивые вещи. Единственная проблема, то, что монады — это паттерн функционального программирования, и в истинно функциональном языке они встраиваются непосредственно в язык. Например, Haskell имеет прямую поддержку для монад. И там, на монадах сделано очень многое, ведь монады в Haskelle, это заодно и средство борьбы с их ленивым выполнением. В Haskell все вычисления откладываются до сих пор, пока они физически не потребуются в программе. Монада — это средство связать несколько вычислений в цепочку, и тем самым, добиться оперативности. Кроме того, монады, это красивое средство скрывать поток связанных вычислений, и поэтому на их базе можно создавать очень красивые вещи. Например, асинхронные вычисления «как будто последовательные», это какие-то генераторы. Ну все наверное знают, в C# есть такая штука, итератор называется. Ключевое слово yeild-return в каком-то методе, превращается в конечный автомат, который генерирует последовательность, и позволяет несколько раз выходить из функций, как бы виртуально.

Вот, computation expression позволяет делать все то же самое, но на уровне буквально одного-двух выражений. Т.е. вы можете в одном методе, объявлять 200 таких вот генераторов, они вам будут генерировать отдельные последовательности. На монадах можно делать очень многое, а computation expressions это такой сахар над ними, позволяющий создать так называемые builderы, для реализации самых разных паттернов использования.

В C# эта штука захардкожена физически, в Nemerle она была реализована в качестве макросов, причем… это было довольно-таки смешно → зашел парень на форум, «что у вас есть?».

Мы говорим: — «макросы». А он говорит, «я тут изучил F#, там есть computation expressions». А мы — «Макросы! Да, это не одно и то же, но на этом можно сделать второе». Ладно, говорит он, попробую.

Обычно ведь как — «Все встают и уходят», в смысле — «Поспорили и разошлись». Но парень оказался упорный, буквально через два дня, он пришел, с такой вот обалденной радостью, и говорит, что вот там, у меня, получилось и даже очень нравится, потому, что это расширяемо, в отличие от F#, где это забито в язык, раз и навсегда. Естественно, с первого раза у него не все здорово получилось, помогли ребята, у которых было побольше опыта в создании макросов, и через неделю, буквально, у нас были computation expression, которые теперь можно использовать в своих программах для реализации сложных workflow, потому что computation expression можно даже переключать между потоками. У вас вычисление идет например, в одном потоке, предположим в бекграунд-потоке, и вас надо переключится и что-то вывести на экран. На экран, во многих библиотеках можно выводить исключительно из GUI-потока. Вы конечно можете использовать разные дурные средства, которые позволяют, там, передать сообщение синхронно, еще что-то там. Но в данном случае, просто можно написать небольшой вызов, так называемый «переключатель контекста», и дальнейшее выполнение пойдет в рамках GUI-потока. Соответственно, точно также можно переключится обратно, и продолжить асинхронные вычисления.

Еще больше интересно то, что эти асинхронные вычисления можно связывать. Одно это computation expression можно связать с другим, другое еще с чем-то и создать граф вычислений, причем они будут друг от друга зависеть, и можно будет не боятся, что что-то там произойдет, вся связь идет, грубо говоря, на уровне вызовов между функциями, … как бы без залезания внутрь объяснить… В общем, это позволяет дожидаться одним вычислением других, продолжать вычисление в других потоках и так далее. Очень широкие возможности по асинхронному выполнению, что может быть использовано как для распараллеливания вычислений, так и для создания каких-то workflow.

К примеру, вот у вас есть сайт, на котором нужно реализовать какой-то wizard. Идеалогия wizarda, когда человек на каждой страничке по кнопочке продвигается вперед, но может отменить, и вернуться назад. Вот computation expression, если в продукт попала синхронизация состояний (?? 23:10), что в общем-то несложно, позволяет синхронизовать состояние такого workflow, сохранять, соответственно откатываться вперед и назад, взяв объект, который находился в состоянии до перехода.

Также, XML-литерал, это очень простой макросик, который был написан буквально за два дня. И он в язык вносит возможность написания XML-литералов прямо внутри кода. Причем эти литералы, они генерируют во время компиляции X-элемент, т.е. это не работа с текстом, не текстовая замена, это именно живые XML-литералы, если кто-то использовал Visual Basic или SCALA, он собственно, может себе представить, что это такое. Кроме того, в XML-литералах поддерживаются так называемые сплайсы, куда можно передать какие-то выражения, от текстов, до опять таки, XML-элементов (X-элемент, X-атрибут, X-name, и так далее). И они собственно будут проверены во время компиляции, что они подходят для этого места, и соотвественно, корректность XML. При этом, разумеется, совершенно невозможно туда запихнуть текст, который потом развернется в какую-нибудь бяку типа яваскрипта, или испортит что-то где-то. Кроме того, в этих же XML-элементах сделаны такие элементы, как циклы, которые позволяют генерировать наборы элементов, и условные включения элементов, можно написать такой маленький when, и если условие истинно, то элемент появится, в зале C я потом все это продемонстрирую.

Самый пожалуй мощный на сегодня макрос, это Nemerle.PEG, макрос-генератор парсеров в идеалогии PEG. PEG — это относительно новая, хотя на самом деле забытая старая технология создания парсеров без (???) 25:40, что делает парсер очень расширяемым, очень гибким.

Кроме того, наш парсер поддерживает неограниченность (???) 25:45, и очень большое количество оптимизаций, что позволяет, с писать одной стороны пользовательский парсер с очень сложным языком, на самом деле я не знаю компьютерных языков, которых нельзя было им распарсить, только если они очень сложно контекстно зависимы, и то, контекстно зависимые языки, такие как C++, можно спокойно парсить, причем довольно просто. При этом он показывает весьма высокую скорость, соответственно, наши тесты показывают 3-4 мегабайта в секунду, … т.е. мегабайтные файлы редактируются, без всяких там оптимизаций и так далее.

Очень мощный парсер, на самом деле на нем тот же XML держится, XML-литералы сделаны на (???) 26:40 … фактически.

Один фреймворк, на самом деле скорее, не рабочий такой фреймворк, а, скорее экспериментальный (указывает на Nemerle.WUI.Reactive), только проба пера, это Nemerle.WUI.Reactive, который позволяет создавать динамические web-приложения, прямо на статически типизированные языки, я это тоже, продемонстрирую в зале C.

Можно в принципе показать, действительно красиво, давайте отвлечемся на секундочку, я просто запущу и покажу результат:

(демонстрация на 41:20)

Nemerle-deep-dive-2012-04-30-13h56m24s63.png

Вот, самый простой примерчик, все строится на идеологии…, есть такой паттерн «Model-View-View-Model». Идея его в чем заключается: что вы работаете не с данными приложения на странице, а вы как бы создаете такую сущность, как «View-Model», как модель для предоставления контента. Эта модель отражает те данные, которые у вас находятся в графическом интерфейсе, и которые выводятся на экран. Т.е. ничего лишнего. Когда вы на сервере такую модель выполняете, вы просто пихаете туда данные из базы данных, и вызываете метод сериализации в JSON. JSON передаете на клиента, он JSON съедает и заполняет внутреннюю Javascriptовую структуру. Эта внутренняя JavaScriptовая структура генерируется по вот этой модели.

Это класс с привычным синтаксисом описания тех же типов по другому, вот в данном случае есть «FirstName», «LastName», «FullName», и «FullName» это на самом деле конкатенация строк. В Nemerle есть такой макрос «бакс» ($), посмотрите, во что он разворачивается:

Nemerle-deep-dive-2012-04-30-14h08m44s89.png

Примерно такой же код генерирует C#, когда вы плюсом пользуетесь.

Этот макрос позволяет в строку вставлять вот такие включения. В итоге, у нас при вычислении этого свойства получится строка, в которой у нас сначала будет «FirstName», потом будет «LastName», и восклицательный знак после этого. Вот такая модель. Все это было бы наверно просто и понятно, если бы это работало в каких-нибудь WinForms-приложениях, еще где-то, но на самом деле, это используется в веб, вот это вот модель, и генерируеnся в том числе яваскрипт-код, который так называемый React-Ins поддерживает.

Nemerle-deep-dive-2012-04-30-14h15m59s65.png

Вот эта вот вьюшка (HelloWorldView), она работает с вот этой вот конкретной моделью, и в ней нет практически никакого кода, только файл. Если вы обратите внимание, то вот он код, какое-то поле текстовое, и у него есть такой-то тег, «data-bind», в котором «value», т.е. значение этого поля, связывается со свойством «FirstName». Второе поле связывается со свойством «LastName». А потом просто «span», т.е. грубо говоря просто текстовый блок, его текст связывается со значением «viewModel.FullName», которое, как мы видели, вычисляемое свойство, которое сконкатенирует значения двух других свойств.

Теперь запустим все это дело.

Nemerle-deep-dive-2012-04-30-14h24m45s194.png

Мы получим такой вот, интерактивный интерфейс:

Nemerle-deep-dive-2012-04-30-14h28m40s231.png

Который на самом деле работает на JavaScript, сейчас я вам его покажу:

Nemerle-deep-dive-2012-04-30-14h30m15s2.png

А Javascript этот компилируется макросом, во время компиляции:

Nemerle-deep-dive-2012-04-30-14h31m28s144.png

Естественно, перед этим срабатывают все проверки типов, у нас в IDE работает… сейчас еще раз покажу,…

Nemerle-deep-dive-2012-04-30-14h34m31s164.png

У нас в IDE работает, видите, весь интерфейс, работает complete code, нотификация, стандартные фишки intellisense:

Nemerle-deep-dive-2012-04-30-14h35m51s224.png

Мы можем писать приложение, буквально без программирования, вернее какое-то программирование потребуется, но все это программирование будет лежать внутри свойств и методов модели. И эта модель чудесным образом превращается в реактивную модель.

Т.е. если мы например, вернемся сейчас в броузер, то вы можете увидеть, как FirstName превратился не просто в какое-то свойство, а превратился на самом деле в некоторый объект «observable» при каких-то начальных значениях.

Nemerle-deep-dive-2012-04-30-14h39m25s135.png

Используется javascriptовый фреймворк Knockout, где вот эти вот «observable» рассылают автоматически уведомления о своем изменении, т.е. когда например, вводится binding с полем, то изменение поля, автоматически изменяет значение вот этого свойства.

Ну и как я сказал, это не готовый фреймворк, а только такой демонстрационный зачаток, но в принципе, планируется в дальнейшем развивать, если найдутся люди готовые этим заняться, кому это будет интересно, — я этим фреймворком не занимаюсь, я это сделал как демонстрацию. Дальнейшее развитие — автоматическая сериализация и передача JSONа, автоматическая валидация, то, что в обычных сложных фреймворках делается огромным объемом кода. Вот то, что я вам демонстрирую, было создано буквально за дня три. Чтобы это довести до ума, программисту, который хорошо знает макросы, понадобится где-то месяц. Зато в конце этого месяца человек будет иметь действительно мощный фреймворк, который практически ни от чего не зависит, кроме веб-сервера.

Вернемся к докладу.

Кроме того есть еще библиотека, более традиционная, «Nemerle on Rails», где-то аналог «Ruby on Rails», который собственно эмулирует его работу. Там есть так называемая миграция баз данных, поддержка какого-то движка HTMLя, не помню…

Nemerle-deep-dive-2012-04-30-14h52m33s90.png

Кроме того, есть множество мелких макросов. «$-строки» я вам уже показывал. Это все макросы, которые входят в стандартную библиотеку. Например, макрос «Record» позволяет автоматически сгенерировать конструкторы, для всех полей классов. Некоторые поля можно просто проигнорировать, туда можно дать какой-то другой атрибут, и эти поля будут исключены. Все остальные попадут в список полей конструктора → наверное все уже устали писать каждый раз класс-конструктор, который запихивал все значения параметров в поля, так вот, макрос «Record» одним написанием атрибута над классами, решает эту проблему.

Есть макросы, которые позволяют автоматизировать разные паттерны проектирования, т.е. вместо того, чтобы выписывать этот паттерн под копирку, вы можете применить атрибут, класса, метода или еще чего-то и реализовать такие паттерны как «абстрактная фабрика», «aggregate», «proxy», «sigleton». И естественно, вы можете создавать какие-то свои макросы, которые решают какие-то ваши прикладные задачи, в соотвествии с какими-то паттернами.

Макрос «late» — это нечто похожее на «dynamic» из четвертого сишарпа, но на самом деле он создан задолго до появления «dynamic-ов» в C#, и позволяющий без синтаксического оверхеда динамически вызывать методы. Т.е. пишите макрос late, далее, какой-то динамически типизированный код, далее этот код компилируется только синтаксически, и все вызовы происходят уже динамически.

Применение макроса «Memoize» к методу позволяет «меморизировать» его состояние для конкретных значений параметров, что позволяет иногда очень сильно повысить производительность, и упростить код.

На самом деле макросов намного больше.

Nemerle-deep-dive-2012-04-30-15h11m18s83.png

Есть такие макросы, как автоматическая генерация структурного сравнения, «CompareTo» пишется автоматически, просто перебором полей. Естественно, он не очень умный, он за вас не сможет узнать, есть ли какие-то поля, которые не надо применять в сравнении, но тем не менее, если вам нужна такая быстрая и тупая релизация сравнений по всем полям, то вы его применяете и буквально сразу получаете реализацию без таких-вот…

То же самое с хеш-кодом, есть макрос для регэкспов, есть так называемый «list comprehension», типа очень маленького компактного LINQ-а, но со специализированным синтаксисом для списков.

Макросов в библиотеке много, перечислить их в докладе невозможно, главное — понять, что это не железно прибитые к языку вещи, а расширяемые конструкции, которые может делать любой из вас, если потратить несколько месяцев на изучение системы макросов.

Сам язык понятен C# программистам, ну может для начала потратят пару дней и изучат прочтением пары статей.

Для более глубокого изучения нужен опыт — ведь никто не научился программировать по книжке или статье, только реальное программирование может этому научить. Но зато, потратив месяц-два на изучение, производительность труда вырастает очень серьезно. Можно просто решать какие-нибудь задачи, которые раньше решались очень тяжело.

Я думаю, что мое время уже истекло, поэтому, спасибо за внимание, еще скажу, что через час, в зале C будет расширенная версия моего доклада, где можно будет задавать вопросы, посмотреть на код — я будут показывать все то же самое в виде кода, и соответственно в конце моего доклада будет еще отдельный большой, ну нормальный такой доклад, по Nemerle.PEG, вот этому самому генератору парсеров, который на самом деле уникальный, аналогов ему на самом деле нет. Cпасибо за внимание!


Ответы на вопросы начались с 38:35, и там тоже было интересно. В частности, по результам этого обсуждения стартовал эпический тред в духе «Менеджеры против гиков» («Тчортовы гики, вы рискуете чужим баблом!»).