понедельник, 10 ноября 2008 г.

Nemerle - что это и где...

Наконец-то решил изучить поподробнее...

Итак, что мы имеем. Nemerle это язык для платформы .NET. Гибридный. С кучей современных возможностей.

Помимо стандартных возможностей предлагает следующие замечательные вещи:

0. Привычный мейнстрим синтаксис. Т.е. это не хаскел, нет. Рядовой C#/C++/Java разработчик может перейти на Nemerle прочитав пару статей.

1. Tuples (это которые кортежи). Очень сложно обьяснить тем кто не пользовался насколько часто это удобно и насколько это упрощает некоторые вещи.
Тем кто знаком с Python - ага, те самые.
В терминах C#3.0 это будет "анонимные гетерогенные массивы" или как-то так. Но с правильной типизацией и очень удобные в использовании.

2. Pattern Matching (сопостовление по образцу). Если по простому - это "switch on steroids". Опять таки...после некоторого времени писанины на языке у которого есть поддержка pattern matching возврат к "старым добрым" if и switch вызывает ломку.

3. Type Inference (вывод типов). Правильнее чем в C#3.0, мощнее, удобнее. Вообщем код начинает питоновский напоминать. Хотя не хаскел конечно, но это и не нужно. К слову - фанаты динамических языков часто упрекают языки со статеческой типизацией в излишней многословности. Так вот - благодаря этому самому type inference это не так. Опять же - после использования языка с развитым type reference возврат в привычную песочницу вызывает ломку.

4. List Comprehensions (как это будет по русски - затрудняюсь). Фича присутствует в Python/Ruby/Haskell/Groovy и возможно где-то еще, не знаю. Фича удобная, когда ее отнимают ломка не возникает но все равно с ней приятнее чем без нее.

5. Функциональные типы (functional types). Я в этом разбираюсь достаточно поверхностно. Но даже моего уровня хватает чтобы понять - делегаты зло, функциональные типы это правильно. Делегаты в C# это некоторое подобие именнованных функциональных типов. Усложненное и с недостатками. Также функциональные типы напоминают Func<A,B>, но все равно их реализация в Nemerle намного правильнее.
Например функцию которая принимает в качестве параметра фукнцию принимающую int и string и возвращающую int можно описать вот так
some_func(f:int*string->string):void


6. Алгебраические типы. Есть отличия от "классических" алгебраических типов, но как по мне только в лучшую сторону. Опять же по простому для знающих С++ "алгебраические типы" это "union on steroids". Обобенно мощно себя проявляют в связке с pattern matching.

дальше просто лень писать ибо долго и много, но еще есть
...матапрограммирование (и огого-го какое. Например linq из С# реализуется макросами языка)...лямбды(ну куда ж без них в наше то время)...closures...да много чего. Причем большенство - прямо от рождения. Т.е. Nemerle таким умным родился, а не эволюционировал к пятой версии.

Вообщем по фичам языка вот тут интересная табличка. Сделайте скидку на то что составлялась евангелистом (читай - фанатом) языка. Но как по мне у него есть все основания фанатствовать.

Для знакомства с языком решил поиграться с первыми задачами из ProjectEuler...

Итак задача 2.
Find the sum of all the even-valued terms in the Fibonacci sequence which do not exceed four million


Понятно что задача простая (хотя и тут можно кое-что...), суть не в ней.
Написав (точнее переписав) несколько extension methods для удобной работы с перечисляемыми типами (IEnumerable) я в первоначально пришел вот к такому решению:

        WriteLine(

            (1,1)

            .unfold((a,b)=>(b,a+b))

            .takewhile((_,b)=>b<4000000)

            .filter((a,_)=>a%2==0)

            .fold(0,(v,x)=>v[0]+x)

            );



теперь немного о простоте задачи. простая-то она простая, но и в ней можно оптимизировать решение.
рассмотрим первые числа последовательности, но следить будем только за четностью...
o(1),o(1),e(2),o(3),o(5),e(8),o,o,e,o,o,e,....

ну думаю заметно о чем идет речь...
и тогда наш код преобразуется в:

     WriteLine(

            (1,1)

            .unfold((a,b)=>(a+2*b,2*a+3*b))

            .take((a,b)=>(a+b)<4000000)

            .fold(0,(v,x)=>v[0]+v[1]+x)

            );



Попытался сделать макрос для функциональной композиции, чтобы код можно было записать так (идея честно украдена в F#):

     WriteLine(

            (1,1) |> unfold((a,b)=>(b,a+b)) |> take((_,b)=>b<4000000) |> filter((a,_)=>a%2==0) |> fold(0,(v,x)=>v[0]+x)

            );



пока не получилось...(

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

А вообще ситуация выглядит так:
- отдать бы Nemerle в хорошие руки (читать - микрософт. там к слову авторы языка уже обитают), и чтобы эти руки выделили человек 10 на разработку и еще несколько раз по столько на доки/примеры/т.д.
И чтобы эти руки добавили dynamic и какой-нибудь оператор для функциональной композиции. Ну и так...по мелочам.
И через полгода-год у нас бы был прекрасный язык, и еще через полгода все бы забыли про C#.

Выводы -
1. Nemerle это язык которым C# дай бог станет лет через пять. А то и все десять. И то - с ограничениями...
2. Если хорошие руки не найдутся - there is no future for Nemerle in this stupid and cruel world(.

А пока попробую всякие поделки клепать на Nemerle.

Комментариев нет: