-
Notifications
You must be signed in to change notification settings - Fork 5
/
2011-10-29-RuProjectKepler.tex
466 lines (340 loc) · 35.9 KB
/
2011-10-29-RuProjectKepler.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
\documentclass[hyperref={bookmarks=false}]{beamer}
\usepackage[utf8]{inputenc}
\usepackage[english,russian]{babel}
\usepackage[parfill]{parskip}
\usepackage{color}
\usepackage{listings}
\hypersetup{pdfauthor={Eugene Burmako},pdfsubject={Project Kepler},pdftitle={Project Kepler}}
\title{Project Kepler}
\definecolor{linkblue}{RGB}{49,57,174}
\definecolor{dkgreen}{rgb}{0,0.6,0}
\definecolor{gray}{rgb}{0.5,0.5,0.5}
\definecolor{mauve}{rgb}{0.58,0,0.82}
\lstdefinelanguage{scala}{
morekeywords={abstract,case,catch,class,def,%
do,else,extends,false,final,finally,%
for,if,implicit,import,match,mixin,%
new,null,object,override,package,%
private,protected,requires,return,sealed,%
super,this,throw,trait,true,try,%
type,val,var,while,with,yield,
macro},
sensitive=true,
morecomment=[l]{//},
morecomment=[n]{/*}{*/},
morestring=[b]",
morestring=[b]',
morestring=[b]"""
}
\lstdefinelanguage{nemerle}{
morekeywords={abstract,and,array,as,base,catch,%
class,def,delegate,enum,event,extern,false,%
finally,fun,implements,interface,internal,is,macro,%
match,matches,module,mutable,namespace,new,null,%
out,override,params,partial,private,protected,public,%
ref,sealed,static,struct,syntax,this,throw,%
true,try,type,typeof,using,variant,virtual,%
void,volatile,when,where,with},
sensitive=true,
morecomment=[l]{//},
morecomment=[n]{/*}{*/},
morestring=[b]",
morestring=[b]'
}
\lstset{frame=tb,
language=scala,
aboveskip=3mm,
belowskip=3mm,
showstringspaces=false,
columns=flexible,
basicstyle={\small\ttfamily},
numbers=none,
numberstyle=\tiny\color{gray},
keywordstyle=\color{blue},
commentstyle=\color{dkgreen},
stringstyle=\color{mauve},
frame=single,
breaklines=true,
breakatwhitespace=true
tabsize=3
}
\AtBeginSection[]
{
\begin{frame}
\frametitle{План}
\tableofcontents[currentsection]
\end{frame}
}
\begin{document}
\title{Проект ``Кеплер'': макросы для Скалы}
\author{Евгений Бурмако}
\institute{EPFL, LAMP}
\date{29 октября 2011}
\maketitle
\section{Проект ``Кеплер''}
\begin{frame}[t]
\frametitle{Проект ``Кеплер''}
\textbf{Цель:} Реализовать макросы, типобезопасный механизм метапрограммирования времени компиляции для Скалы.
\textbf{Идеи:} В основном из Немерле, хотя будет интересно поэкспериментировать с некоторыми замечательными моментами из Scheme, MetaML и Template Haskell.
\textbf{Участники:} \text{\color{linkblue}\href{mailto:eugene.burmako@epfl.ch}{Евгений Бурмако}} (ваш покорный слуга), \text{\color{linkblue}\href{mailto:christopher.vogt@epfl.ch}{Кристофер Фогт}} (автор Scala Integrated Query), \text{\color{linkblue}\href{mailto:stefan.zeiger@typesafe.com}{Штефан Цайгер}} (автор ScalaQuery).
\textbf{Статус:} В процессе написания спецификации Scala Improvement Proposal, некоторые аспекты уже обсуждаются в рамках SIP \text{\color{linkblue}\href{https://docs.google.com/document/d/1NdxNxZYodPA-c4MLr33KzwzKFkzm9iW9POexT9PkJsU/edit?hl=en_US}{``String interpolation and formatting''}}.
\end{frame}
\begin{frame}[t]
\frametitle{В двух словах}
Уже очень долгое время макросы в популярных языках программирования ассоциируются с макросами С/С++. Неудивительно, что многие автоматически воспринимают слово ``макрос'' в штыки.
В отличие от макросов препроцессора, наши макросы:
\begin{itemize}
\item Представляют собой код на полноценной Скале
\item Работают с высокоуровневыми и типизированными деревьями выражений
\item Выполняются в контексте компилятора, поэтому имеют доступ ко всей семантической информации, доступной компилятору
\item Не изменяют синтаксис Скалы
\end{itemize}
Наши макросы напоминают макросы Лиспа, доработанные для поддержки богатого синтаксиса и статической типизации.
\end{frame}
\begin{frame}[t]
\frametitle{Прежде, чем мы начнем}
Мне крайне интересно услышать ваши комментарии, предложения и критику. Дизайн макросов только-только начал обретать твердые очертания, поэтому его можно подточить для поддержки ваших проектов и сценариев использования.
За всего лишь месяц жизни проекта уже было пару случаев, когда я вносил в черновик спецификации значительные изменения для поддержки тех или иных сценариев, о которых я узнавал в процессе дискуссий. Пожалуйста, не стесняйтесь и пишите мне на \text{\color{linkblue}\href{mailto:eugene.burmako@epfl.ch}{eugene.burmako@epfl.ch}}.
Кроме того, все нижеописанное является крайне экспериментальным и может быть в любой момент изменено на $180^{\circ}$. На текущий момент проект ``Кеплер'' \emph{просто} является моей будущей диссертацией, поэтому ни Scala Solutions, ни TypeSafe никак с ним не связаны.
\end{frame}
\section{Макросы за 15 минут}
\begin{frame}[t, fragile]
\frametitle{Макросы на микро-уровне}
\begin{lstlisting}[language=nemerle]
macro printf(format : string, params parms : array[expr])
{
def (evals, refs) = make_exprs(parse(format), parms);
def seq = evals + refs.Map(x => <[ Write($x) ]>);
<[ { ..$seq } ]>
}
printf("Value = %d", 123 + 877)
{
def _N_1812 = (123 + 877 : int);
Console.Write("Value = ");
Console.Write(_N_1812)
}
\end{lstlisting}
\end{frame}
\begin{frame}[t]
\frametitle{Макросы}
Это был довольно сложный фрагмент кода (кстати, код этот написан на Немерле). Давайте подробно рассмотрим концепции, относящиеся к макросам:
\begin{itemize}
\item \texttt{Printf} - макрос. Его тело представляет собой метакод, т.е. код, который исполняется во время компиляции.
\item В качестве аргументов \texttt{printf} принимает набор выражений времени компиляции, т.е. узлов AST. Возвращаемое значение тоже является AST.
\item Когда компилятор встречает вызов макроса, он исполняет метакод (т.е. тело макроса) и вставляет \emph{[splice]} его результат (т.е. сгенерированный код) в место вызова.
\item Несмотря на то, что макросы исполняются на этапе компиляции и не имеют доступа к значениям времени выполнения, они могут вызывать произвольные функции и методы, в том числе и стандартную библиотеку.
\end{itemize}
\end{frame}
\begin{frame}[t]
\frametitle{Квазицитаты}
Генерация кода обычно весьма нудное занятие, но в рассматриваемом примере нам удалось воспользоваться весьма элегантной техникой:
\begin{itemize}
\item Прикольные скобки \texttt{<[ ... ]>} задают квазицитаты \emph{[quasiquotations]}, фрагменты кода, которые можно удобно композировать и декомпозировать.
\item Большие фрагменты кода можно собирать из маленьких при помощи так называемого сплайсинга \emph{[splicing]}. Выражения \texttt{\$x} и \texttt{..\$seq} являются сплайсами.
\item Квазицитаты возвращают значения времени компиляции. Отметим важный факт, который резюмирует все, что мы на текущий момент знаем про макросы: возвращаемое значение макроса из примера (последняя строчка в теле макроса) - квазицитата, т.е. AST. Все сходится!
\end{itemize}
\end{frame}
\begin{frame}[t, fragile]
\frametitle{Сопоставление с образцом}
Квазицитаты также находят применение в сопоставлении с образцом для удобной декомпозиции абстрактных синтаксических деревьев. Например, некий гипотетический оптимизатор может выглядеть следующим образом:
\begin{lstlisting}[language=nemerle]
match (e) {
...
| <[ $x * 1 ]> => <[ $x ]>
}
\end{lstlisting}
Будучи использованными с левой стороны сопоставления с образцом, сплайсы задают именованные ``отверстия'' в квазицитатах.
Очень красивый трюк, правда? Но он не исчерпывает феерию синтаксических чудес на сегодня. О еще более захватывающих вещах можно почитать \text{\color{linkblue}\href{http://xeno-by.livejournal.com/56221.html}{в моем блоге}}.
\end{frame}
\begin{frame}[t]
\frametitle{Гигиена}
За кадром остались детали разбора строки формата и сборки кусочков выходной строки. Во всех подробностях реализацию можно посмотреть \text{\color{linkblue}\href{http://rsdn.ru/article/nemerle/NemerleStingFormating.xml\#EPCAE}{в статье Влада Чистякова}}, но пока что мы остановимся на одном интересном фрагменте.
Для того, чтобы в сгенерированном коде сослаться на переменные, доступные в месте вызова, в метакоде написано \texttt{<[ \$(expr : usesite) ]>}. Зачем все так усложнять?
Все это нужно потому, что макросы Немерле являются гигиеничными, т.е. они переименовывают генерируемые переменные и ссылки на переменные для того, чтобы предотвратить случайные пересечения имен.
Чаще всего это как раз то, что нужно, поэтому гигиена включена по умолчанию, но иногда (например, для реализации строковой интерполяции) это мешает, поэтому при желании гигиену можно обойти.
\end{frame}
\begin{frame}[t, fragile]
\frametitle{Макросы на макро-уровне}
\begin{lstlisting}[language=nemerle]
[Usage(Phase.BeforeInheritance, Targets.Class)]
macro Serializable (t : TypeBuilder)
{
t.AddImplementedInterface (<[ ISerializable ]>)
}
[Serializable]
class S {
public this (v : int, m : S) { a = v; my = m; }
my : S;
a : int;
}
\end{lstlisting}
\end{frame}
\begin{frame}[t]
\frametitle{Кодогенерация}
Макросы верхнего уровня, которые применяются путем аннотирования сущностей программы, являются ответом Немерле на проблему дублирования кода.
Такие макро-аннотации крайне полезны для устранения копипасты, против которой бессильны ООП и ФП. Особенно приятно использовать подобные макросы тем, кто уже имеет опыт работы с текстовыми генераторами вроде T4 - ведь в данном случае все делается через квазицитаты, которые являются высокоуровневыми, типобезопасными и композируемыми.
При \text{\color{linkblue}\href{http://www.eecs.harvard.edu/~mainland/publications/mainland07quasiquoting.pdf}{соответствующей поддержке со стороны языка}} в квазицитатах можно задавать произвольные целевые языки (например, HTML), что делает макросы еще более соблазнительными.
\end{frame}
\begin{frame}[t]
\frametitle{Средства разработки}
Макросы содержат в себе немало магии, поэтому для работы с ними требуется надежная поддержка средств разработки:
\begin{itemize}
\item В силу того, что макросы изменяют порядок сборки (перед компиляцией основной программы, очевидно, необходимо скомпилировать используемые в программе макросы), средства сборки должны быть в курсе макросов.
\item Генерируемый код может понадобиться оттрассировать в отладчике. Отсутствие исходников не является существенной проблемой, ибо мы можем сгенерировать их из AST, но этот вопрос все равно надо обдумать.
\item Для того, чтобы обеспечивать правильную подсветку и анализ кода, IDE должны знать о макросах, причем макросы также должны знать об IDE и вести честную игру - быть реентерабельными, быть аккуратными с разделяемым состоянием.
\end{itemize}
\end{frame}
\begin{frame}[t]
\frametitle{Резюме}
\begin{itemize}
\item В отличие от печально известных макросов препроцессора C/C++, современные макросы работают с AST и тесно интегрированы в язык и компилятор, что делает их безопасными, выразительными и композируемыми.
\item Макросы исполняются на этапе компиляции, но при этом имеют доступ к рантайму и библиотекам языка. Таким образом, например, во время компиляции макрос может обратиться к базе данных.
\item Микро-уровень макросов предоставляет средства для виртуализации языка программирования и создания доменно-специфических языков. Макро-уровень позволяет автоматически сгенерировать части программы.
\item (Фанатам ASM и \texttt{Reflection.Emit} посвящается) Квазицитаты делают анализ и генерацию кода приятным и продуктивным занятием.
\end{itemize}
\end{frame}
\section{Сценарии использования}
\begin{frame}[t]
\frametitle{На микро-уровне}
\begin{itemize}
\item Разработка встроенных доменно-специфических языков. Одним из паттернов eDSL является перегрузка операций языка и протаскивание действий пользователя через весь DSL. Макросы позволяют избежать этой весьма хрупкой процедуры, так как они могут получить информацию о замысле пользователя непосредственно из AST.
\item Синтаксический сахар для монад. Важным частным случаем языковой виртуализации является do-нотация для монад. С помощью макросов ее можно реализовать без поддержки со стороны компилятора.
\item Встраивание внешних доменно-специфических языков. При помощи квазицитат в программу можно встраивать фрагменты кода на произвольных языках. Макросы- обработчики квазицитат могут обеспечить интеграцию этих языков с главным языком программирования (общий лексический контекст, услуги типизации и т.п.).
\end{itemize}
\end{frame}
\begin{frame}[t]
\frametitle{На макро-уровне}
\begin{itemize}
\item Генерация кода любых разновидностей. С точки зрения кодогенерации макросы верхнего уровня более продуктивны, чем текстовые генераторы, и гораздо более высокоуровневы, чем генераторы байт-кода.
\item Аспектно-ориентированное программирование. Традиционные парадигмы не способны справиться с некоторыми задачами декомпозиции и дедубликации кода. В результате возникли частные подходы к решению таких задач. Макросы предоставляют средства для склеивания аспектов приложения в общем случае.
\item Типы данных ``a la carte''. Часто бывает необходимо собрать класс из нескольких независимых кусочков. Для этого очень хороши трейты, но иногда их гибкости не хватает, например, для кастомизации \texttt{case}-классов.
\end{itemize}
\end{frame}
\begin{frame}[fragile, t]
\frametitle{Практический пример: LINQ}
\begin{lstlisting}[language=scala]
var db = new MyDbContext(connString);
var products = db.Products;
products.Where(p => p.Name.StartsWith("foo")).ToList()
\end{lstlisting}
Переменная \texttt{products} в этом примере имеет тип, унаследованный от \texttt{IQueryable<Product>}.
Метод \texttt{Where} доступен для всех коллекций стандартной библиотеки .NET, но для \texttt{IQueryable} он перегружен магическим способом, который говорит компилятору передать в него не функцию-фильтр, а ее представление в виде дерева выражений.
В процессе жизненного цикла запрос накапливает в себе информацию о вызванных методах типа \texttt{Where} и переданных в виде деревьев параметрах, после чего по просьбе программиста (\texttt{foreach}, \texttt{ToList} и так далее) преобразует эту информацию в запрос к конкретному источнику данных.
\end{frame}
\begin{frame}[t]
\frametitle{Постановка задачи}
LINQ - неувядаемая классика нашего времени, так сказать, де-факто стандарт в области виртуализации запросов в мейнстримных языках программирования, поэтому хочется иметь что-то подобное в стандартной библиотеке Скалы.
В следующем разделе презентации мы увидим как при помощи макросов можно реализовать не только LINQ, но и кое-что поинтереснее - причем все это исключительно средствами языка, т.е. без внесения изменений в компилятор.
Кроме независимости от компилятора полученное решение исправит некоторые фундаментальные ограничения LINQ, например, проблемы с композируемостью - все это благодаря строгости и ортогональности концепции макросов.
\end{frame}
\section{Легковесные макросы для Скалы}
\begin{frame}[t, fragile]
\frametitle{LINQ на макросах}
\begin{lstlisting}[language=scala]
class Queryable[T, Repr](query: Query) {
macro def filter(p: T => Boolean): Repr = <[
val b = $this.newBuilder
b.query = Filter(query, ${reify(p)})
b.result
]>
}
val products = db.products
products.filter(p => p.Name.startsWith("foo")).toList
\end{lstlisting}
\end{frame}
\begin{frame}[t]
\frametitle{Макро-определения}
Как можно заметить, вызов макроса \texttt{filter} в предыдущем примере неотличим от вызова обычного метода. Это неудивительно, ведь \texttt{macro def} читается как ``макрос, который может использоваться везде, где бы использовался \texttt{def}''.
Сигнатура макроса также прозрачно интегрирована в целевой язык программирования. Макросы исполняются во время компиляции, поэтому они принимают на вход и возвращают исключительно нетипизированные AST. Однако спецификации типов позволяют компилятору проверить корректность макроса и как можно раньше сообщить о возможных ошибках.
Кроме того, внутри макроса у программиста есть доступ ко всем переменным, которые составляют область видимости, в том числе к \texttt{this} и к неявным переменным. Для внимательных: да, в макросах перегружен метод \texttt{implicitly[T]}.
\end{frame}
\begin{frame}[t]
\frametitle{Легковесные, но не убогие}
Из-за своей легковесности макросы могут казаться ограниченным хаком, но это не так. На самом деле, макросы - полноценные граждане языка и рантайма.
С одной строны, легковесность является синтаксическим сахаром, за которым скрывается обычная функция, которая принимает на вход несколько AST и возвращает AST на выход. С другой стороны, в процессе компиляции макросы преобразуются в обычный байткод, который может быть использован при сборке другой единицы компиляции.
Наконец, макросы могут использовать произвольные функции/методы и загружать любые библиотеки. За примером далеко ходить не надо - \texttt{reify} из предыдущего листинга является обычной функцией \texttt{AST $\Rightarrow$ AST}. Кстати, а что будет, если вместо \texttt{\$\{reify(p)\}} написать \texttt{reify(\$p)}? Подсказку посмотреть в \text{\color{linkblue}\href{https://raw.github.com/xeno-by/kepler/master/papers/SID101-QuasiQuotations.pdf}{черновике спецификации квазицитат}}.
\end{frame}
\begin{frame}[t]
\frametitle{Тайп провайдеры}
Языковая поддержка интегрированных запросов и фреймворк трансляции запросов хороши как вещи в себе, но кроме них еще необходим способ отображения сущностей источника данных на классы нашего языка программирования.
Это хорошо известная проблема в мире O/RM. Один из путей ее решения заключается в использовании текстовой кодогенерации, другой - в ручном кодировании классов. Сейчас мы рассмотрим альтернативный подход, который стремительно набирает известность: тайп провайдеры, разработанные в Microsoft Research.
Идея тайп провайдеров заключается в том, чтобы во время компиляции генерировать классы для сущностей источника данных (таблиц, сущностей XSD, записей LDAP). Если мы слышим ``время компиляции'', значит, можно применить макросы.
\end{frame}
\begin{frame}[t, fragile]
\frametitle{Тайп провайдеры на макросах}
\begin{lstlisting}[language=scala]
macro class MySqlDb(connString: String) = ...
type MyDb = MySqlDb("Server=127.0.0.1;Database=Foo;")
val products = new MyDb().products
products.filter(p => p.Name.startsWith("foo")).toList
\end{lstlisting}
\end{frame}
\begin{frame}[t]
\frametitle{Макро-типы}
$\hdots$ это не более, чем синтаксический сахар для старых добрых макросов, преобразующих AST в AST.
Этот вид макросов также принимает на вход AST и также возвращает AST, но возвращаемое выражение является не просто выражением языка, а полноценным определением класса. Здесь нет двойного дна - все действительно настолько просто.
В силу того, что макросы являются полноценными сущностями языка, разработчики могут повторно использовать и частично переопределять логику уже существующих макро-типов.
Также, благодаря прозрачности макросов, пользователи могут наследоваться от макро-типов и переопределять их функциональность в терминах объектно-ориентированной парадигмы.
\end{frame}
\begin{frame}[t]
\frametitle{Минимализм}
Вначале я хотел развить идею macro чего-то и дальше и поэтому обдумывал разные варианты: например, macro package или macro annotation. Мартин был сильно против раздувания языка, и это заставило меня задуматься. Выяснилось, что можно обойтись только определениями и типами.
Скажем, для генерации большого количества классов (например, \texttt{TupleN}) можно написать \texttt{macro object} и потом импортировать его в место использования. Для генерации классов в текущий пакет можно подмешать \texttt{macro trait} в \texttt{package object}.
Специальные макро-аннотации тоже имеют сомнительную ценность, ибо их можно заменить обычными аннотациями, а раскрытие макросов можно запускать, подмешивая в объявляющий класс специальный \texttt{macro trait}.
\end{frame}
\begin{frame}[t]
\frametitle{Резюме}
\begin{itemize}
\item Наши макросы прозрачно интегрированы в язык программирования. Макро-определения (\texttt{macro defs}) практически неотличимы от обычных определений, макро-типы (\texttt{macro types}) могут быть использованы почти везде, где используются обычные типы.
\item С помощью этих двух конструкций языка можно эффективно реализовать анализ кода, языковую виртуализацию, а также победить некоторые виды дубликации кода, с которыми не справляются традиционные парадигмы программирования.
\item Наконец, макро-типы вкупе в механизмом квазицитирования предоставяют высокоуровневый интерфейс к кодогенерации.
\end{itemize}
\end{frame}
\section{Заключение}
\begin{frame}[t]
\frametitle{Ссылки}
\begin{itemize}
\item Project Kepler, Compile-Time Metaprogramming for Scala\\
\text{\color{linkblue}\href{https://github.com/xeno-by/kepler}{https://github.com/xeno-by/kepler}}
\item Живой журнал на русском, обновляется чаще всего\\
\text{\color{linkblue}\href{http://xeno-by.livejournal.com/}{http://xeno-by.livejournal.com/}}
\item Блогспот на английском, ретрансляция из ЖЖ\\
\text{\color{linkblue}\href{http://xeno-by.blogspot.com/}{http://xeno-by.blogspot.com/}}
\item Сборник познавательных текстов по макросам\\
\text{\color{linkblue}\href{http://macros.xeno.by/}{http://macros.xeno.by/}}
\item Сайт языка программирования Немерле\\
\text{\color{linkblue}\href{http://nemerle.org/}{http://nemerle.org/}}
\end{itemize}
\end{frame}
\begin{frame}[t]
\frametitle{Благодарности}
Пользуясь случаем, хочу выразить благодарность создателям языка программирования Немерле за прекрасный источник вдохновения, а также Владу Чистякову, главному разработчику современного Немерле, за \text{\color{linkblue}\href{http://rsdn.ru/forum/nemerle/}{невероятно полезные дискуссии}} на тему метапрограммирования времени компиляции.
Признаться честно, я просто восхищен Немерле. Этот язык программирования - живое доказательство того, что возможно и практично иметь систему интегрированного в язык метапрограммирования в статически типизированном языке с синтаксисом. Кроме того, Немерле является тестовым стендом для \text{\color{linkblue}\href{http://code.google.com/p/nemerle-2/}{активных исследований в области макрологии}}, что делает его еще более интересным.
Наконец, большое спасибо всем, кто принимал участие в обсуждениях проекта ``Кеплер'' и своим взглядом со стороны помог сделать дизайн макросов лучше.
\end{frame}
\begin{frame}[t]
\frametitle{Обратная связь}
Хотел бы еще раз остановиться на том, как важно ваше мнение.
Если после просмотра слайдов у вас возникли интересные идеи, если вы знаете, как макросы помогли бы (или помогают) вам в ежедневной работе, не сочтите за труд поделиться мыслями по адресу \text{\color{linkblue}\href{mailto:eugene.burmako@epfl.ch}{eugene.burmako@epfl.ch}}.
Макросы для Скалы все еще в процессе дизайна, поэтому удачная мысль может радикально поменять ход проекта и изменить мир к лучшему. Или же, более банально, но не менее приятно: сделать конкретно ваш сценарий программирования более продуктивным.
\end{frame}
\begin{frame}[c, fragile]
\frametitle{}
\centering
{\Large Вопросы и ответы}\\
\centering
\text{\color{linkblue}\href{mailto:eugene.burmako@epfl.ch}{eugene.burmako@epfl.ch}}
\end{frame}
\begin{frame}[t, fragile]
\frametitle{Метаморфные макросы}
\begin{lstlisting}[language=nemerle]
macro Cons is Expr
syntax expr1 : 11 "::" expr2 : 10;
{
<[ @::(expr1, expr2) ]>
}
\end{lstlisting}
В отличие от обычных макросов, метаморфные макросы, работают на уровне парсера и грамматики языка программирования. Они могут добавлять новые синтактические конструкции или расширять уже существующие продукции грамматики.
Во второй версии языка команда Немерле планирует реализовать полностью весь синтаксис на макросах. Наряду с традиционными описанием грамматики DSL задания синтаксиса также будет включать информацию о типизации продукций. По сути, Немерле 2 будет метациркулярным метакомпилятором.
\end{frame}
\end{document}