Нужно ли полиглотное программирование в стеке .Net?
Из комментариев к коротенькому посту на Хабре про использование Python как базового языка для Asp.Net мне понравился вот этот комментарий от centur:
Ну собственно повторный вопрос — зачем?
Дмитрий Нестерук высказал вполне здравую мысль — зачем нужна вся эта куча языков, если есть так активно развиваемый C#.
В общем возможность мульти-языкастости среды это клево, но вот потенциальная поддержка этого — один из кругов ада =)
Мне кажется что пришло самое время досконально обсудить проблему того, что конкретно нам дают все эти языки, и насколько “полиглотное программирование” вообще имеет смысл.
F#
Давайте прокинем VB и начнем с языка №2 который уже является полноправным жителем нашей .Net экосистемы. Да, интересный, функциональный язык. А теперь внимание вопрос: в чем собственно его приемущества, какой конкретно от него business value?
Вот я написал несколько проектов либо полностью на F# либо частично. У меня была возможность попробовать такие “рекламируемые” фичи как async workflows и повсеместное отсутствие мутабельности. И вот к каким выводам я пришел:
- Бизнес-программирование по большому счету мутабельное, тем самым язык который вставляет вам 100 палок в каждое колесо при попытке изменить переменную для него слабо подходит. Чего стоит например вот такое определение:
let context : Ref<IVisitable option> = ref None
- Async workflows – это всего лишь кастомная издевка над синтаксисом. Это хак. Такой же хак есть и в .Net с использованием AsyncEnumerator (PowerThreading). Ничего “гениального” в этом нет, работу это не упрощает. Вот вам прямое сравнение двух подходов – выводы делайте сами:
F#
let private DownloadPage(url:string) = async { try let r = WebRequest.Create(url) let! resp = r.GetResponseAsync() // let! позволяет дождаться результата use stream = resp.GetResponseStream() use reader = new StreamReader(stream) let html = reader.ReadToEnd() use fs = new FileStream(@"c:\temp\file.htm", FileMode.Create, FileAccess.Write, FileShare.None, 1024, true); let bytes = Encoding.UTF8.GetBytes(html); do! fs.AsyncWrite(bytes, 0, bytes.Length) // ждем пока все запишется with | :? WebException -> () } // вызов ниже делает синхронный вызов метода, но поведение внутри метода - асинхронное Async.RunSynchronously(DownloadPage("http://habrahabr.ru"))C#
public IEnumerator<int> DownloadPage(string url, AsyncEnumerator ae) { var wr = WebRequest.Create(url); wr.BeginGetResponse(ae.End(), null); yield return 1; var resp = wr.EndGetResponse(ae.DequeueAsyncResult()); var stream = resp.GetResponseStream(); var reader = new StreamReader(stream); string html = reader.ReadToEnd(); using (var fs = new FileStream(@"c:\temp\file.htm", FileMode.Create, FileAccess.Write, FileShare.None, 1024, true)) { var bytes = Encoding.UTF8.GetBytes(html); fs.BeginWrite(bytes, 0, bytes.Length, ae.End(), null); yield return 1; fs.EndWrite(ae.DequeueAsyncResult()); } } - Метапрограммирование в F# неполноценно. То, что там есть цитирование, еще ничего не значит, т.к. нам хочется не транслировать F# в какой-то там язык, мы хотим то цитирование и “сплайс” которыми мы можем помочь компилятору сгенерировать некие структуры в процессе компиляции. Настоящее статическое метапрограммирование есть пока что только в Boo, но оно будет в C#.
- Создание DSLей – да, оно проще. Если интересно – вот моя статья. Только DSLи – это пока направление которое в основном, во-первых, для internal use, а во-вторых только для продвинутых фирм вроде моей. Точно не для общего пользования. Не верите? Let me google that for you.
- Идея о том, что F# лучше чем C# для сложного алгоритмического программирования в финансовых и аналогичных индустриях не раскрыта. Да, его используют. Детальных case studies мало, и опять же, никто толком не может объяснить почему. И вообще, какая разница, во что транслировать формулы?
Есть еще нарекания в плане “общей вменяемости” – например набор всяких <@ @>, <@@ @@>, [], [| |], {}, (|x|_|), ->, <-, >>, :>, :?>, |> это же просто бред какой-то! Это “магические операторы”, иначе не назвать.
Вообщем, я действительно хочу использовать F#, но когда я реально начинаю его использовать, то каждая из фич которая изначально кажется selling point языка оказывается неповоротливой и непрактичной. Например, я надеялся что pattern matching поможет мне структурировать разбор строк вот в этом проекте. На самом же деле, код получился практически нечитабельным. Где тут maintainability? Правильно – ее нет в помине.
Boo
Я конечно понимаю что товарищ Айенде, будучи “впереди планеты всей” в плане работы с базами данных, решил поделиться своими замечаниями на тему того, как метапрограммирование на языке Boo может принести реальный business value. Проблема в том, что книжка у него отровенно не удалась, и тем самым аргумент как бы затух.
Идея Boo в том, что у вас есть якобы более лаконичный синтаксис (а-ля Python) плюс возможности расширения компилятора которые делают возможным мета-изыски которых мы затаив дыхание ждем в C#. Ну так что, давайте обсудим эти два “бенефита” на предмет их полезности.
Вообще, идея того что Питон чем-то “лаконичней” чем C# или какой-то там другой язык – это попытка продать абстрактное “нечто”, не подкрепляя это толком никакими аргументами. Возьмем например произвольный кусок кода из проекта:
class ManaIndicatorsAttribute(AbstractAstAttribute):
public override def Apply(node as Node):
c = node as ClassDefinition
for i in range(ManaSumAttribute.LandTypes.Count):
basic = ManaSumAttribute.LandTypes[i] as string
hybridLands as List = []
for j in range(HybridManaAttribute.HybridLandTypes.Count):
hybrid = HybridManaAttribute.HybridLandTypes[j] as string
if (hybrid.Contains(basic)):
hybridLands.Add(hybrid)
rbasic = ReferenceExpression(basic.ToLower())
b = Block();
b1 = [| return true if $rbasic > 0 |]
b.Statements.Add(b1)
for k in range(hybridLands.Count):
rhybrid = ReferenceExpression((hybridLands[k] as string).ToLower())
b2 = [| return true if $rhybrid > 0 |]
b.Statements.Add(b2)
r = [|
$("Is" + basic):
get:
$b;
|]
c.Members.Add(r)
Ну-с, и где тут ‘лаконичность’? На практике получается жесткий, слабочитаемый код, в котором не спасает вывод типов, в котором записи вроде return x if y добавляют только дополнительную степень неоднозначиности, а вы бы видели IL который сгенерирован – у меня при виде того как код на Boo разворачивается в код на C# с помощью Рефлектора глаза на лоб лезут – такое впечатление что этому языку просто плевать на стэк. Поэтому простое суммирование пяти переменных переведенное в C# вернется вам не как a + b + c + d + e а скорее как ((((a + b) + c) + d) + e).
Насчет вещей, аналогичных LINQ. Да, действительно, до Linq в Питоне был козырь в плане разбора списков и прочих, т.е. можно было написать list[1,-1] или например подобное:
List(y for y in (x**2 for x in range(10)) if y % 3 != 0)
Теперь это неактуально т.к. в том же C# можно сделать то же самое, причем с поддержкой IntelliSense и без необходимости запоминать всякие range() (какая разница с Enumerable.Range()? меньше букв?) и прочие названия. Приемущество Linq в том, что это унифицированный API, который выглядит одинаково вне зависимости от того, используете ли вы Linq to Objects, Linq to Events (Rx) или Linq to CepStream (StreamInsight). Тут в основном одни и те же ключевые слова, плюс IntelliSense если вы что-то забыли.
Генераторы… ах, генераторы, идея-то хорошая, но вот скажите мне, что делает следующий кусочек кода:
def TestGenerator():
i = 1
yield i
for x in range(10):
i *= 2
yield i
Утипизация? Тем кому она нужна уже имеют ее в C# с помощью таких библиотек как LinFu. Регулярные выражения через /? Ну что ж, может это и удобней, но лично мне все равно, т.к. я использую приложение, которое решает за меня все эти проблемы (хотя соглашусь, что конверсия в C#-строку выглядит коряво). Что остается?
Остается пожалуй только метапрограммирование. Это, на данный момент, единственный козырь в языке который, как мы с коллегами считаем, умрет сразу же после выхода C#5. И если вы считаете что метапрограммивание нужно сегодня и нужно срочно использовать Boo, вот вам несколько контр-аргументов:
- Язык и инструментарий не развиваются. BooLangStudio мертва. Документация на сайтах частично устарела.
- Использовать две IDE достаточно напряжно. Я имею ввиду, что вам придется компилировать Boo через SharpDevelop, а потом импортировать сборки в ваши C# проекты. Никакого configuration management рядом не стояло.
- Компилятор сырой, и у меня были мета-методы которые вообще не сходились, т.е. программа компилировалась в невалидный IL. Никаких гарантий безопасности компилятор не дает.
- Про IntelliSense или аналогичные вещи можно забыть – Boo вы будете программировать вслепую.
Вообщем, для тех кого это действительно интересует, у меня есть вводная статья про метапрограммирование на Boo. Только вот стоит ли напрягаться? Ведь C#5 не за горами, и есть большая вероятность, что с его выходом можно будет пометить Boo как [Obsolete].
IronPython
Вся критика по языку Boo может быть обращена к IronPython ибо синтаксис похожий. Единственный плюс – что IronPython как бы более “зрелый” и даже имеет поддержку в Visual Studio (IronPythonTools). Ну и да, “динамичность” этого языка несет в себе, якобы, некоторые приемущества которые всем уже известны.
Только есть одно но – тема CLR vs DLR (не знаю можно ли так писать) – явно не раскрыта. Например, почему создатели языка Go намеренно сделали его статическим? Правильно – скорость. А что делать с языком который не дает ощутимых бенефитов в плане синтаксиса, и который по скорости не тянет (чего стоит скорость декораторов, например – да легче помучаться и на C# написать, или подвязать тот же PostSharp).
IronRuby
Если питонообразные языки человек с опытом C# еще как-то может понять, то Ruby – это чистая магия, т.е. язык который нужно долго и прагматично изучать с нуля. А стоит ли это того? Alt.Net сообщество уже прожужжало нам все уши на тему того, что Ruby лучше для тестирования (см. например Cucumber), и я с этим не спорю – действительно, чем ближе мы в BDD приближаемся к обычному английскому, тем больше к нам аппелирует сама концепция BDD. Только вот есть одно но – BDD пока штука не доказанная, она как и приемочное тестирование в стиле Fitnesse является интересной абстракцией к которой индустрия присматривается, но не делает ее стандартом для разработки.
Чем еще хорош Ruby? Да, он неплохо поддерживает динамическое метапрограммирование, есть даже книжка на эту тему. Но занимаясь именно динамическим, а не статическим, метапрограммированием, следует понимать что это не совсем одно и то же – динамическое программирование это серьезное заигрывание с концепциями а-ля ExpandoObject, то есть манипуляция типов на этапе исполнения – нечто, что после безумной головной боли можно реализовать и на Mono.Cecil. В то же время, статическое метапрограммирование – это возможность расширять не тип, а компилятор. Тем самым, сравнивать эти два подхода не очень уместно, и то что Роб Конери хочет “метапрограммирование сегодня и сейчас” – это лично его представление о том, что это такое, и мне кажется он смешивает краски.
Следует заметить, что у IronRuby в отличии от IronPython нет поддержки в Visual Studio. Поэтому придется использовать или SharpDevelop или (сюрприз!!!) IntelliJ IDEA/RubyMine. При этом вы получите IntelliSense для ваших собственных конструкций, но его у вас не будет для различных .Net-библиотек.
Заключение
Прежде всего – да – существуют и другие языки в стеке .Net, например IronScheme. Но чем дальше мы отходим от “канона” тем дальше мы и от обычного бизнес-программирования, а следовательно каким бы элегантным не был тот или иной язык, можно с уверенностью говорить что без участия комьюнити, uptake такого языка будет равен нулю. Примером может служить язык Nemerle, которого, несмотря на наличие интересных (но ни в коей мере не революционных) идей, ожидает та же участь что и Boo.
Проблемы со сторонними языками можно охарактеризовать примерно так:
- Бизнес не примет их без поддержки Microsoft
- Количество людей, хорошо знающих эти языки мало́, а значит те сотрудники что у вас их знают рискуют стать незаменимыми
- Клиент вряд ли согласиться на проект на языке, особенно если саппорт он хочет получить не у вас, а где-то еще
- Инструментарий пока не очень готов – это касается даже таких языков как F#
- Реально не хватает success stories, которые четко показывают бенефиты
В заключение этой статьи я призываю всех .Net-разработчиков порадоваться, что у нас есть такой гибкий язык как C#, который удовлетворяет все 100% (да-да, именно 100%) наших потребностей. С другой стороны, никто не мешает экспериментировать – главное чтобы ваши эксперименты потом попадали в production, а то иначе это все академизм и теоретизирование. Удачи!
Update 1 Как подсказал коллега @butaji, DLR полезен тем что позволяет легко “скриптовать” ваши .Net-приложения, то есть фактически получать возможность скриптинга ваших .Net-конструктов без использования COM Automation или еще более кустарных извратов. Это конечно огромный плюс в тех ситуациях когда это действительно нужно, особенно если учесть альтернативы (создание всяких проприетарных DSL и т.п.).
Update 2 Судя по всему, с DLR-языками, в частности с IronRuby, все достаточно плохо.
Update 3
Судя по всему, огромным приемуществом DLR являются ситуации, когда нам нужно постоянно подтачивать нашу программу уже после компиляции. Коллега @butaji уже это упомянул, но мне пока это не попадалось как вопиющий юз-кейс. А теперь я даже обзавелся компонентом который делает синтактическую подсветку. Буду встраивать; посмотрим что получится.

Упущен один важный момент c DLR/Boo – то, что можно просто заскриптовать .NET (и не только?) приложения и это привносит немалый business value
butaji
2 Август 2010 в 17:02
А ты быстро прочитал пост – менее чем за минуту. Признаюсь – сам DLR никуда не встраивал, но видел решения где существующий код на том же Питоне был легко подвязан к VSX, судя по всему без портирования вообще. Супер!
Dmitri
2 Август 2010 в 17:17
Если честно, то по моему все эти пляски по поводу количества языков запускаемых под clr- это чистая политика партии. Надо догнать и перегнать jvm. Там сотня языков, так и у нас не меньше.
Для меня кроме C# есть только 1 альтернативный язык в vs2010 – это C++. F# честно говоря просто не понимаю в виду, не понимаю функционального подхода.
У меня может мозга не хватает, зачем такие языки типа Boo и Nemerlie, но думаю я не один такой, кто не понимает зачем оно. Нас таких 95% наверное.
Существование ironpython, ironruby, до хоть Phalanger(php) и janet на мой взгляд оправдано только с 1 целью- запустить без изменений код написанный на python, ruby, php, java на стандартной clr или dlr. ну и с целью перетащить товарищей на ms стек, нужна интеграция этих языков с стандартной библиотекой классов.
В общем на мой(студенческий) взгляд- это все попахивает шаманизмом. Есть инструменты для решения конкретных задач. Понятные, документированные, с массой готовых компонентов. А заниматься разработкой на каких-нибудь boo или nemerlie- пожалуйста, но в не рабочее время, не на рабочем месте.
SychevIgor
2 Август 2010 в 17:45
JVM до недавнего времени не был полиглотным. МС позиционирует полиглотность как уникальную фичу, но тут краски смешались благодаря таким языкам как Scala. И если язык вроде Scala действительно нужен ввиду общей отсталости Java, то в .Net все менее очевидно.
Насчет С++, это опять же для 1% продвинутых людей которые знают зачем это нужно и как работать с этим из C#. Лично мне недавно был интересен язык Go (от Google), т.к. хочется именно компилируемый язык который поддерживал бы всяческие новые парадигмы.
Dmitri
2 Август 2010 в 17:53
Я бы сказал, что главным стимулом для существования не-C# языков является то, что нынешний C# развивается как раз благодаря тем концепциям, которые появлялись в виде частей отдельных языков. Все, что есть в нем – до этого появлялось где-то раньше. Метапрограммирование на CLR? Пускай Boo и Nemerle и не стали мейнстримом, но они подняли тонну материала по компиляции метакода в IL, сгенерировали километры обсуждений применимости метарограммирования в мейнстриме вообще.
F# и Async Workflows точно таким же образом можно рассматривать как попытку смоделировать удобную среду для асинхронного программирования, причем, опять же – в контексте компиляции функционального кода в IL-код (компиляция функциональных языков – это вообще целый академический эпос).
Пожалуй, если вкратце, то ответом на заголовок поста будет – да :)
Ну а как итог: будущее за языками на основе некой мультипарадигмы (каждой проблеме своя парадигма), а многоязычность .NET всего лишь дает возможность достаточно быстро воплощать этот план в жизнь (в противовес идее о исключительно политической составляющей этого свойства).
Igor T.
2 Август 2010 в 19:12
Ну не километры… метапрограммирование, думается мне, понимают процентов 5 разработчиков. Это точно не мейнстрим.
Это не хитрая компиляция, это библиотечное, по сути дела, решение. Что такое workflow? Это перегрузка операторов, так что в
async { .. }например операторыlet!иdo!ведут себя по другому. Подложкой для этого всего все равно является APM, то есть парыBeginInvoke()/EndInvoke().Dmitri
2 Август 2010 в 19:27
>>> Ну не километры… метапрограммирование, думается мне, понимают процентов 5 разработчиков. Это точно не мейнстрим.
но тем не менее C# 5.0 не за горами :)
>>> Это не хитрая компиляция, это библиотечное, по сути дела, решение.
Я смотрю на все это шире – как хорошо всем жилось в синхронном мире и как всем вдруг стало весело, когда появилась *необходимость* рассихронизировать свой код, дабы прокачать производительность. На сегодня все удачные решения живут в функциональной (не массовой) парадигме. Но нужно-то что-то индус-ориентрованное! Вот исследователи мечутся между всевозможными моделями в попытке унифицировать подход ну и F# с его внутренностями – одна из испытательных площадок.
Короче, не станут сторонние языки мейнстримом, да и никому они в качестве мейнстрима не нужны. А вот прототипом новых фичей в C# – запросто.
К слову, в статье еще Spec# не упоминался :) Вот он-то очень четко иллюстрирует мою идею.
Igor T.
2 Август 2010 в 20:43
>> Это не хитрая компиляция, это библиотечное, по сути дела, решение.
Там фишка в читабельности, они убрали асинхронность и нон-блочащий стаф за ширму языка. А читабильность в асинхронных програмах это уже бизнес валью.
Mike Chaliy
2 Август 2010 в 20:51
Я не вижу особой читабельности в постоянных let! и do!
И вообще, если логика простая, можно использовать и APM. Ну или PowerThreading. А для сложных вещей лучше какую-нть DSLку заточить конкретно для этих целей. Например вот так.
Dmitri
2 Август 2010 в 21:01
А let! и do! чем не DSL?
Igor T.
2 Август 2010 в 21:53
>Да, интересный, функциональный язык. А теперь внимание вопрос: в чем собственно его приемущества, какой конкретно от него business value?
Я не много с этим языком работал, но подчеркнул бы слудующие пункты, в которых, как я вижу язык имеет преимущество:
*поддержка асинхронных цепочек на уровне компилятора
*поддержка реактивного программирования(без использования сторонних библиотек как в шарпе)
Но да, в нем много синтаксических недостатков, или просто не привык еще.
apmath
2 Август 2010 в 19:19
Асинхронные цепочки это уровень языка, компилятор делает такой же IL как и C# (см. мой комментарий выше). Что касается реактивного программирования (first class events и т.п.) – тут я вообще разницы не вижу. То что я могу сделать Event.map или Event.filter на события – да, приятно, но я могу сделать то же самое ценой всего лишь одной библиотеки.
Получается что в этом плане у F# нет приемуществ, т.к. оба примера реализуются с помощью библиотек PowerThreading и Reactive Extensions соответственно.
Dmitri
2 Август 2010 в 19:31
Главное чтобы ваши эксперименты потом попадали в production. –> не считаю это такой уж неприложной истиной и это мое главное возражение.
Alexander Tankeev
2 Август 2010 в 21:08
Я фанат денег. Мне нужен хороший язык чтобы заработать побольше, быть конкуррентней, делать более качественный продукт. Что в этом плохого? А академязыков итак гора, разного вкуса и цвета. Но тратить на них время, если это не инвестиция в будущее, я не могу.
Dmitri
2 Август 2010 в 21:28
Все верное, массы идут за C#. А C# идет за python/ruby/f# и прочей кодлой. Если бы их не было, была бы вторая жава.
Хотя те тоже встрепенулись.
Весь этот “зоопарк” действительно можно заменить C# ну пару раз наступив себе на горло. Но можно. Вот с JavaScript все сложнее. Чего мне не хватает, так это аналога GWT (google web toolkit).
(только не надо про silverlight плз)
Shrike
3 Август 2010 в 1:32
Я думал вы скажете “только не надо про Script#”, ведь именно он пытается быть аналогом GWT, не так ли? Вообще идея GWT очень сильно импонирует, т.к. сокращает, а не преумножает, количество языков, которые нужно знать для разработки веб-приложений.
Dmitri
3 Август 2010 в 9:21
Script# как-то странно пытается, застряв на C# 1.1.
Есть более интересная на вид вещь – jsc (jsc-solutions.net). Но как-то отзывов на нее нет.
“не надо про silverlight” – т.к. это компилируемый язык в приложении для браузера. GWT – тоже компилируемый язык в приложении для браузеров, но совсем по-другому.
Вобщем MS опять проморгали тренд имхо со своим silverlight’ом.
Shrike
3 Август 2010 в 17:53
Да не, не проморгали. Это RIA, это нужно чтобы динамический график показать и т.п. Для этого всегда будет рынок, и будут даже те, кто будет строить полноценные решения с SL-фронтендом. Но вернувшись к GWT, да, это совсем другая тема – тема которая имеет огромное количество плюсов по сравнению с той кашей, которая получается даже в самом простом проекте Asp.Net MVC.
Dmitri
3 Август 2010 в 20:40
WebSharper не пробывали? http://www.intellifactory.com/products/wsp/Tutorial.aspx
Я сам отношусь весьма скептически к этим инструментам (особенно глядя как хороши всевозможные dynamic data/updatepanel на простых примерах и как они начинают откровенно мешать на сложных задачах).
Андрей
3 Август 2010 в 21:39
Не пробовал. Для меня странновато использовать функциональный язык в этом контексте. Непонятно где тут пресловутый business value.
Dmitri
4 Август 2010 в 17:35
А, еще на тему “нафига нам python и пр” рекомендую глянуть на фреймворки Grails и Django (если не видели).
Все-таки забавно там, код и он же одновременно dsl для доменной модели и он же одновременно dsl для конфигурации.
Shrike
3 Август 2010 в 1:36
Отличная статья, подтвердила для меня то, что я тоже подозревал подсознательно, но не мог чётко высказать. Очень нравятся “так между прочим” ссылки на вещи типа FitNesse – эрудированных специалистов сейчас очень мало к сожалению.
Так держать!
Kirill Osenkov
3 Август 2010 в 7:11
C#, конечно, всем хорош, но! Лично меня уже давно утомляет его синтаксис. Хочется чего-то более простого и, в какой-то мере, изощрённого. Какой-нибудь Лисп или подобие Haskell с Erlang.
Короче, я против того, чтобы добавлять новые классные конструкции в язык за счёт костылей синтаксиса. Sequence comprehension через LINQ сложно назвать верхом изящества, хотя, несомненно, задачу оно решает.
Maxim Moiseev
3 Август 2010 в 9:27
Так мне кажется либо оно простое либо изощренное, и тому и тому не бывать. А вот интересно, чем тебя синтаксис утомляет? Тем что приелся? В таком случае мне тоже. Но изучать другой язык только потому что скучно… можно конечно, но денег в копилку оно вряд ли принесет.
Dmitri
3 Август 2010 в 12:51
Отличное слово – приелся. Многословен и приелся.
Изучать языки – фан, деньги – суета сует.
Maxim Moiseev
3 Август 2010 в 14:44
Попробуйте Nemerle. :)
hc
3 Август 2010 в 19:16
В защиту F#
yield return 1; по крайней мере не читабельнее чем let!
Писать с обработкой ошибок в стиле APM на С# очень неудобно. Да и workflows не ограничиваются только async. Не упомянут pattern matching, active pattern помогают при написании кода. Конечно отсутствие инструментов типа resharper (да и встроенная поддержка студией далека от С#) не способствует развитию использования F#
Андрей
3 Август 2010 в 9:39
Ну это спорно, что читабельнее – кастомные операторы или хаки из уже существующих. По мне так одно другого стоит!
Dmitri
3 Август 2010 в 13:05
Почему же не был рассмотрен Nemerle?
Синтаксис практически полностью копирует C#, есть интеграция в VisualStudio 2008. В отличие от Boo он имеет гораздо больше возможностей относительно “цитирования и сплайсинга” – квазицитирование, при том генерирование невалидного IL из макросов практически нереально. Постепенно обрастает фичами – PEG-парсер на макросе (это в тему разбора текста), компьютеэйшн экспрешонз из F#, умеет LINQ запросы.
hc
3 Август 2010 в 16:58
а кто его за пределами rsdn.ru знает?
Cлушал подкаст altspb, кто-то из ведущих сказал: не посещает этот сайт из-за того, что там дизайн так себе :), другие согласились.
Андрей
3 Август 2010 в 17:14
Уж давно хочу исправить эту ситуацию, но все нехватает силы воли.
hc
3 Август 2010 в 19:17
Нет, во-первых это подкаст spbalt.net, а во-вторых, мы в основном игнорируем РСДН из-за откровенно непрофессионального поведения его участников. Статьи там интересные, но атмосфера там на грани добра и зла, и участвовать в этом нет ну никакого желания.
А насчет Nemerle, нужно больше людей которые готовы его рекламировать. Нужна полная поддержка в VS2010, а не поддержка в 2008 которая лично у меня, например, вообще не захотела работать (было давно, правда).
Более того, претензий к Nemerle слишком много – очень много криптических операторов вроде $.. которые известны только авторам. “С нуля” Nemerle вообще невозможно читать. Ну и попытка вплести функциональщину мне не очень нравится, плюс опять же часть связанная с метапрограммированием по сравнением с Boo запутана (вроде как там 4 конструкта по сравнению с 2мя в Boo).
Dmitri
3 Август 2010 в 20:37
Насчет людей – так их всегда не хватает. Опенсурс проект все же, да, я время от времени занимаюсь доработкой компилятора и библиотек. В настоящее время проверяю на прочность генератор парсеров (тот самый PEG).
Претензии не совсем ясны. Операции и конструкции аналогичные C# выглядят совершенно также. Конкретно по $ – это тот самый сплайс оператор, для подстановки параметров в строку или квазицитату.
Не спорю, метапрограммирование несколько отличается от Boo, но все также есть два конструкта – макросы уровня выражений и макросы уровня объявлений. Nemerle обладает навороченной системой вывода типов и все сложности с метапрограммированием в основном начинаются когда макросу нужно получать богатую информацию о типах (но до этого уровня стоит дорасти, не часто он нужен).
Функциональщина совершенно уместна. Язык является гибридным: на уровне объявлений используется труЪ ООП подход аналогичный C# (то с чем совсем плохо у F#), на уровне тел методов находится “функциональщина” – все достаточно чисто и продумано (то с чем откровенно хреново у императивного C#). В отличии от Boo в языке есть квазицитаты, без них генерирование более-менее сложного кода в макросах было бы серьезно осложнено: вы пробовали работать с CodeDom? так вот в Boo происходит работа с чем-то похожим, это я вам скажу мрак полнейший.
Я не слишком верю что в C# 5.0 появится что-то подобное, тем более когда бишь он выйдет? ;)
Так что если хочется статического метапрограммирования в .NET без погружения в адские конструкты CIL, то Nemerle это то что нужно.
hc
4 Август 2010 в 0:00
очень интересная статья, большое спасибо!
а где можно почитать про метапрограммирование в C# 5.0?
cdriper
3 Август 2010 в 17:13
Сейчас – нигде. Есть небольшая презентация Хельсберга где он демонстрирует REPL в C#, но пока больше инфы не было. Как только появится – ей будет пестрить весь интернет.
Dmitri
3 Август 2010 в 20:33
наверное поэтому гугл мне так ничего и не нарыл по теме :)
просто ты так уверенно про это пишешь, как про состоявшийся факт…
кстати, если ты активно пользовал метапрограммирование в F# или Boo, было бы очень интересно почитать по теме, желательно с более менее реалистичными примерами.
cdriper
4 Август 2010 в 9:52
Для начала пойдет вот эта статья. Также есть слайды с доклада на spbalt.net. Ну а если хочется совсем конкретных примеров то есть еще одна статья.
Dmitri
4 Август 2010 в 10:23
да…
и какая связь между REPL и метапрограммированием?
cdriper
4 Август 2010 в 9:59
[...] Только DSLи – это пока направление которое в основном, во-первых, для internal use, а во-вторых только для продвинутых фирм вроде моей. Точно не для общего пользования. [...]
По-моему, это звучит слишком пафосно и вульгарно.
В действительности, не надо вводить в заблуждение народ и хвастаться крутостью своей фирмы.
На самом деле, DSL – это просто.
Когда напишешь LL(1) парсер с восстанавлением после сбоя , или хотя-бы простой нисходящий парсер методом рекурсивного спуска, тогда меня поймёшь.
Как внешний, так и внутренний DSL – это всего лишь способ задания последовательности действий в котексте задачи, сформулированный на языке предметной области (для экспертов).
Например – lua-скрипты для многих игр – это DLS описания игры (плагинов, заставок, модов, сцен, карт и т.д.)
hack2root
11 Август 2010 в 17:35
Я имел ввиду не техническую сложность реализации DSL а скорее идеологическое непрятие подобного подхода. Я мог бы привести примеры из моей “прошлой жизни”, но не хочу никому создавать антипиара.
Dmitri
11 Август 2010 в 17:43
Уговорил :)
hack2root
11 Август 2010 в 17:46
Вначале хотел написать комментарий, но он получился относительно большим, посему вынес в отдельный пост:
http://status-alexus.blogspot.com/2010/08/net-ironpython.html
Alexey Diyan
12 Август 2010 в 2:32
[...] наткнулся на статью Дмитрия Нестерука “Нужно ли полиглотное программирование в стеке .Net?&#…, где была высказана жалоба что нет успешных историй [...]
Roinet.Net » Blog Archive » Нужен ли Python в .Net стеке?
12 Август 2010 в 14:05
В защиту скриптовых языков в .Net и Python вообще, написал небольшую заметку об успешном проекте с использованием .Net и IronPython:
http://roinet.net/2010/08/12/nuzhen-li-python-v-net-steke/
Pavel
12 Август 2010 в 14:10
Почитал – спасибо, интересно.
Dmitri
12 Август 2010 в 23:29
А как же все-таки на счет VB.NET? Интересно ваше мнение. Работал в нескольких фирмах и как не странно, для заказчиков, на которых работали фирмы, было предпочтительнее, чтобы писали на VB.NET. Это можно отнести к пережиткам прошлого?
Роман
12 Август 2010 в 23:03
К сожалению, я не квалифицирован чтобы судить на счет VB. Мне кажется что новые .Net-проекты сейчас создаются исключительно на C#, а вот легаси – тут может быть и VB и C++/CLI и что угодно еще.
Кто-то просто всегда занимался VB и им легче продолжать писать на нем. Ничего против не имею.
Dmitri
12 Август 2010 в 23:28
вообще, как правило, то что есть в C# есть и в VB.NET. если в C#5 появится метопрограммирование, то в VB.NET 11, я думаю тоже. Но учитывая то, что для C# намного лучше поддержка ReSharper’а, то C# конечно предпочтительнее
Роман
13 Август 2010 в 0:00
Для .Net еще есть и Clojure (пока в бета-версии)
Alex Ott
25 Август 2010 в 18:24
Интересно, часто слышу про этот язык.
Dmitri
25 Август 2010 в 22:21
И всё-таки как же язык Scala (для .NET), красивее и продуманнее синтаксиса я ещё вообще не видел. Хотя, конечно, за последнее время C# во многом догнал и уже даже перегнал, но сама идиома Scala – просто замечательная (самая лучшая гибридизация функционального и импиративного языков + метапрограммирование и прямая работа с XML; намного лучше, чем в Nemerle).
Darklight
14 Сентябрь 2010 в 16:21
Мне кажется что Scala гораздо уместнее сравнивать с F#, и тут он (имхо) весьма серьезно проигрывает по ряду параметров, в частности по синтаксису. Впрочем, Scala – это наверное лучшее что на данные момент существует на JVM, а его поддержка для .Net, насколько я знаю, в зачаточном состоянии.
Dmitri
10 Январь 2011 в 16:29
Часто одним из плюсов F# называют более удобную работу с многопоточностью из-за immutable (не изменных) типов.
В книге “Real-World Functional Programming WITH EXAMPLES IN F# AND C#” приводится пример immutable типа на C#
class GameCharacter {
readonly int health;
readonly Point location;
public GameCharacter(int health, Point location) {
this.health = health;
this.location = location;
}
public GameCharacter HitByShooting(Point target) {
int newHealth = CalculateHealth(target);
return new GameCharacter(newHealth, this.location);
}
}
т.е. любое изменение состояния объекта влечет создание нового экземпляра.
Вопрос – стоит ли применять F# и immutable типы для каких-то сложных и долгих вычислений, покрывает ли удобство распараллеливания затраты на постоянное создание новых экземпляров?
Alex_BBB
9 Июль 2011 в 7:36
Зависит от кол-ва аллокаций. Если вы наплодили миллион объектов и они попали в Gen 2 а у части из них еще и финалайзеры есть, вы будете писать свой garbage collector. Кстати, вон ребята из Jane Street ясно говорят почему не используют F# – запредельное кол-во аллокаций. Ведь следует помнить, что каждая мало мальски функциональная фишка, например передача оператора в качестве аргумента – это лишний выделенный struct.
С другой стороны, это структура а не класс, что как бы намекает, что ежели использовать System.ValueType’s, stackalloc и т.п. то может все не так плохо.
Dmitri
14 Июль 2011 в 15:47