Возможные фичи C# 5

Никто толком не знает что будет в следующей версии языка C#. Даже люди в C# Insiders (я в их числе) понятия не имеют, что там Microsoft придумает. Тем не менее, в сети есть очень много действительно хороших предложений, несколько из которых я решил представить ниже. Надеюсь получится хорошая дискуссия.

Замена для IEnumerable<T> — тут идея в том, что мы слишком много букв пишем, и что лучше, как это сделано в Boo, заменить IEnumerable одной буквой, чтобы можно были писать T* или T~. К сожалению, звездочка вполне может запутать тех, кто знает что такое указатель, так что придется поискать другой оператор.

Синтакcический сахар для dependency property. Идея простая – реализация DP на данный момент невменяема, т.е. выглядит как “код с известного полуострова” и мейнтейнить такие нагромождения не хочется. Уж лучше написать следующее:

public Message
{
  get; set;
  default { return "No message"; }
  assign { Console.WriteLine("Just changed message!"); }
}

И так далее. Соответственно, реализации INotifyPropertyChanged, IDataErrorInfo, IEditableObject и так далее тоже хочется получать автоматически, а не через нагромождения, как это делается сейчас.

NonNullable типы, то есть типы которые не могут быть null в принципе. Помечаем тип как T! (дуальная аналогия T?, что соответствует Nullable<T>) и всё! Некоторым правда этого мало – они хотят чтобы все типы были ! by default.

yield из анонимных функций – думаю тут все понятно. От себя добавлю, что было бы круто если бы можно было использовать var вместо полного описания прототипа. Например:

var z = (int [] x => { foreach (var y in x.Where(x % 2 == 0)) yield return y; }

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

public IEnumerable<Person> OldPeople(this Person person)
{
  if (person.Age > 80) yield return person;
  // instead of this
  foreach (var result in OldPeople(person.Children))
    foreach (var p in result)
      return p;
  // we write this
  foreach yield OldPeople(person.Children);
}

Sequence-инициализация, чтобы например 1..10 производило то же самое, что Enumerable.Range(1, 10).

Правильная инициализация кортежей. Сейчас метод может вернуть два значения в Tuple<T,U>, но получать их нужно через .Item1 и .Item2. Это нечитабельно, и лучше делать вот так:

(sex,death) = GetMeaningOf(life);

Хотя лучше всего наверное использовать struct-тип для возврата, т.к. иначе подсказки о том что возвращается можно получить только из документации.

Как альтернатива – возможность возвращать анонимные именованые типы, примерно вот так:

public static new { T X, T Y } Vector2<T>(this T k)
{
    return new { X = k, Y = k };
}

Оператор цепочной проверки на null. Например, если один из элементов person.Address.PostCode является null, мы получим исключение, а проверять их все—лень. Поэтому хочется получить оператор а-ля ?. чтобы написал вот так person?.Address?.PostCode мы получили null если любой из элементов null.

Extension properties — у нас уже есть методы, а если еще будут свойства (как в F#), то легче будет делать примеси. Это некий аналог multiple inheritance который, насколько я понимаю, есть например в Scala.

Скрытая ленивость — иначе говоря, обертка вокруг Lazy<T> которая позволить переменной быть ленивой без всяких .Value и так далее. Например:

class C
{
  yield int Z;
  public C()
  {
    Z = SomeLazyComputation(); // only done when asked
  }
}

Приватные поля для свойств — еще одна идея как инкапсулировать поля когда объект не является POCO:

class C
{
  public int N
  {
    int n = 0;
    get { return n; }
    set { if (value != n) {
      n = value;
      NotifyPropertyChanged("n");
    } }
  }
}

Если у вас есть еще какие-то идеи насчет новой версии языка – пишите!

150 responses to “Возможные фичи C# 5”

  1. Хорошая статься Дмитрий.

    Пару фич из приведенного списка я бы использовал. Особенно идея насчет INotifyPropertyChanged. Возможно заменить атрибутом который можно применять к свойству или ко всему классу целиком.

    Sequence-инициализация тоже была бы полезной штукой.

    Насчет Lazy слышу первый раз. Спасибо, что просветили :). Насколько я понимаю эта возможность появилась в 4 версии, а в нашей организации до сих пор на 3.5. Да и причины по которым откладывают переход лично мне не понятны.

    1. Так часто бывают. А некоторые сейчас только переходят с 2.0 :)

      1. Я вам больше скажу: а некоторые и не переходят. Или ставят МВС 2010, но все равно продолжают писать под 2.0. А почему? А потому что нормальный функционал можно прекрасно реализовать и на старых версиях фреймворка. А все новые плюшки хороши в основном для аутсортинга, ибо под лозунгом новейших технологий легче конкурировать и, стало быть, продаваться.

      2. Лично мне плевать на конкуренцию с аутсорсерами т.к. их рейты мне подавно не нужны. А с тем что все можно сделать на 2.0 не соглашусь – например DLR хорошо развязал нам руки.

    2. Я не знаю какой в Вашем городе центр хороший, но вот Я был тут http://kinezislife.ru/ – Идеальный Медицинский центр “Кинезис-Лайф”

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

  2. Множество фич есть в F#, ну, кроме относящихся к DP
    ксати, я тут занялся изучением F#, и вот как мне посоветовали апгрейдить ваш пример с DSL http://cs.hubfs.net/forums/thread/16535.aspx

    1. Класс, спасибо за наводку! Только мне не очень нравятся все эти |> в описании проекта – смахивает на <*> в WebSharper :)

      1. ну, так там в комментах ниже пишут, как от них можно избавиться

      2. у меня пока левел не дошел до уровня понимания computation expressions :)

  3. Убрать “not nested” ограничение с классов в которых могут быть реалзованы extension methods. Если конечно это возможно, то убрать и обязательность делать это в static типе. Таким образом мы получим возможность писать расширения видимые в контексте только одного типа.
    Сценарий использования – скажем нужно написать приватный метод GetSomeItemsFrom(list), гораздо читабельнее было бы list.GetSomeItems(). Что скажете?

  4. По поводу приватных полей для свойств.
    Обращение к свойству намного медленнее, чем непосредственно к полю (т.к это фактически вызов метода), поэтому внутри класса я все-таки предпочитаю обращаться к полям напрямую, а не к их свойствам. Поэтому вопрос спорный, но идея хорошая.

    1. Я подозреваю для get { return x; } большую вероятность JIT-inlining, поэтому даже забывая про необоснованность предварительной оптимизации, скорее всего для сборки в Release нет разницы между полем и невиртуальным свойством.

  5. Александр Avatar
    Александр

    Могу предложить
    1. Сделать типизированный класс WeakReference.
    2. Добавить к классу Lazy функциональность WeakReference, если объекты могут быть легко пересозданы при необходимости.

  6. Так, в порядке ворчания

    – dependency property все же не C# фича :) Но все же дефолтную реализацию нотификации прикрутить стоит.

    – не надо операторов типа “T!” уж лучше NonNullable. Читабельность кода с такими фишками падает. T* туда же. Не надо делать из С# какой-то RegExp :)

    – ну про yeild уже говорили :)

    – насчет цепной проверки на null, мне опять же больше нравиться форма записи в виде функции. Например в PHP есть метод isset() возвращающий true или false в зависимости от существования переменной. Вот как-то так и для null.

    1. А мне нравится Т*, вроде очень удобно. Чисто теоретически. Конечно оператор * наверняка не подойдет.

      1. Дело не в самом знаке – он может быть любой.

        Есть такой факт – что мы не читаем по буквам, а воспринимаем информацию блоками (есть даже текст с переставленными буквами внутри слова читающийся без проблем). Именно по этому и сейчас легко не заметить “int?”

        Так что я не против фичи, но за читабельность.

      2. Ну, уж не знаю, лично мне тоже нравится. T? / T! было бы весьма удобно.
        >Не надо делать из С# какой-то RegExp :)
        эх) посмотрите на F# – вот там рассадник таких вещей))
        http://msdn.microsoft.com/en-us/library/dd233228.aspx

      3. В Comega так и было сделано. И + для непустой/неnull последовательности.

  7. Из того, что хочется и не указано выше.

    Аналог #light синтаксиса из F#

    – Возможность убрать {} – и заменить отступами (indentation)

    – Убрать ; если одна инструкция в строке

    – Для статических классов возможность вызывать функции без указания класса
    using System.Console

    в коде после такого можно писать WriteLine(“some”);

    1. > – Возможность убрать {} – и заменить отступами
      > (indentation)
      > – Убрать ; если одна инструкция в строке

      Кладезь для багов :) :) :)

      1. Так это же Python. Или Boo.

      2. С ними не работал. Видимо к счастью.
        Но не все, что есть в других языках – хорошие фичи.

        Вы еще PHP в пример поставьте. На мой взгляд его возможность просто объявлять переменную фактом использования просто кошмарна. Или считать опечатки ключевых слов за неопознанные константы.

      3. Демагогия – я же ничего не говорил о PHP, а вы его взяли и разгромили.
        Посмотрите на F# – там еще до релиза сделали #light опцией по умолчанию.

      4. Ну зачем так сразу – я просто привел пример известной мне фичи другого языка, которую я бы не хотел видеть в С#.

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

    2. А вот штука с using System.Console – это вроде в Nemerle есть. Не назвал бы это огромным плюсом.

  8. И как я мог забыть о pattern matching’е, вместе с discriminated union’ами, которые сейчас приходится эмулировать многословным наследованием.

    1. Pattern matching – полезно, конечно. Что касается discriminated unions, так по мне это зло, источник неоднозначности, непонятности и наверняка нарушают что-то из SOLID :)

      1. В чем неоднозначность и непонятность? Это же обычная закрытая иерархия класов.

      2. В Scala и Nemerle может быть и открытая ;)

      3. Это хорошо что есть. Надо и мне Scalу поглядеть.

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

        Это позволяет проверять полноту паттер-матчинга во время компиляции.

      5. Мне кажется вы просто не “врубились” в ФП.
        Алгебраические типы данных, которые вы называете “размеченными объединениями”, вкупе с сопоставлением с образцом просто являют собой другой подход к полиморфизму и совершенно незаменимы при работе с “древесными” структурами данных.

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

        Утверждение ваще просто смехотворна, так как паттерн-матчинг (ПМ) был разработан совместно с алгебраическими типами и является стройной математической концепцией.

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

        По существу, алгебраические типы – это не более чем семейство типов (в ООП выражается как набор типов с единым предком) которые можно выразить через их конструкторы. Так что бояться тут не чего.

      7. Да я не боюсь. Просто мои попытки выпилить value из паттерн-матчинга кончились ничем. Например, то что для последовательности букв я должен писать | '&' :: 'g' :: 't' :: '&' :: tail вместо | "&gt;" :: tail – это уже огромный минус. Я конечно придираюсь, знаю что парадигма другая и что тот же разбор строк лучше делать парсерами или “по привычке”, просто констатирую тот факт, что даже от паттерн-матчинга я мало чего получаю.
        Что касается алгебраических типов и всяких приколов вроде Option<'t> – бенефиты всего этого весьма сомнительны. Я понимаю что это и как работает, но не знаю – то ли мозг уже проштампован тем что де “легче наследование сделать”, то ли не знаю что еще. По крайней мере, по этой фиче я в C# не скучаю.

      8. > Просто мои попытки выпилить value из паттерн-матчинга кончились ничем.

        Значит не с того конца подходили.
        Большая часть того что вы описали в своей “хотелке” уже давно реализовано в Nemerle в виде макросов. Макросы же Nemerle просто не мыслимы без алгебраических типов (которые в нем называются вариантными типами).

        Попробуйте написать какой-нибудь не примитивные проект на этом языке. В процессе работы вы освоите основные фичи языка включая варианты и ПМ. Уверяю, Вас что через месяц Вы измените свое мнение об алгебраических типах.

        >Например, то что для последовательности букв я должен писать | ‘&’ :: ‘g’ :: ‘t’ :: ‘&’ :: tail вместо | “>” :: tail – это уже огромный минус.

        Начнем с того, что писать как Вы продемонстрировали можно только если вы работаете со списком. А для списка запись “…” смысла не имеет. Потому она и не применима. Для сравнения попробуйте написать что-нибудь подобное с List. У Вас вообще ничего не получится.

        ПМ не надо воспринимать как решение всех проблем. Это инструмент который надо уметь применять по назначению.

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

        А вот для разработки тех самых парсеров или для представления результата работы парсера отлично подходя алгебраические типы.

        Например, вот парсер C# 4.0
        http://code.google.com/p/nemerle/source/browse/nemerle/trunk/snippets/peg-parser/CSharp/CSharpParser/ созданный с помощью макроса PegGrammar.

        В этом http://code.google.com/p/nemerle/source/browse/nemerle/trunk/snippets/peg-parser/CSharp/CSharpParser/Parser.n файле описывается грамматика, а в файлах http://code.google.com/p/nemerle/source/browse/nemerle/trunk/snippets/peg-parser/CSharp/CSharpParser/Parser_*.n находятся обработчики которые генерируют AST (например, следующий файл содержит обработчики для выражений http://code.google.com/p/nemerle/source/browse/nemerle/trunk/snippets/peg-parser/CSharp/CSharpParser/Parser_Expressions.n). AST описывается вариантными типами. Например, вот так описывается выражение: http://code.google.com/p/nemerle/source/browse/nemerle/trunk/snippets/peg-parser/CSharp/CSharpParser/Expr.n

        А вот код из конвертера преобразующего AST выражений C#-а в AST выражений немерла:
        http://code.google.com/p/nemerle/source/browse/nemerle/trunk/snippets/peg-parser/CSharp/CSharpToNemerle/AstConverter_Expr.n

        Представьте насколько бы разросся код если бы вы описывали AST выражений классами, а анализировали бы его с помощью if-ов. Если не можете представить, то просто поверьте, что объем кода увеличился бы где-то в 5-10 раз. А его понятность уменьшилась бы аналогичным образом.

        Собственно сам макрос PegParser сам использует варианты для внутреннего представления грамматик. Вот как выглядит описание AST грамматики в формате PEG:
        http://code.google.com/p/nemerle/source/browse/nemerle/trunk/snippets/peg-parser/LRPEGCC/Rule.n#199

        Такое представление позволяет резко облегчить анализ и оптимизацию грамматики. Вот как выглядит оптимизация грамматики:
        http://code.google.com/p/nemerle/source/browse/nemerle/trunk/snippets/peg-parser/LRPEGCC/Optimizer.OptimizeRule.n
        Не трудно заметить, что оптимизация почти вся состоит из паттер-матчинга. И возможно это благодаря тому, что грамматика представлена в виде вариантов (т.е. алгебраических типов).

        В общем, вариантные типы – это отличное средсво описания некоторых моделей данных. Их легко описывать, легко трансформировать, и легко анализировать. Как и классы варианты предоставляют динамический полиморфизм. Но в отличии от классов он реализован не через виртуальные методы, а через анализ типов выполняемый с помощью паттер-матчинга.

        Если хотите понять алгебраические типы и научиться с ними работать, то советую скачать и установить http://code.google.com/p/nemerle/ и прочесть “Язык Nemerle”:
        http://rsdn.ru/article/Nemerle/TheNemerleLanguage.xml
        http://rsdn.ru/article/Nemerle/TheNemerleLanuage-prt-2.xml
        http://rsdn.ru/article/Nemerle/TheNemerleLanuage-prt-3.xml

        И не просто прочесть, а каждый пример скомпилировать и разобрать вдоль и поперек (можно под отладчиком).
        Это позволит ощутить мощь вариантов и ПМ на реальном практическом примере.

      9. Как раз option очень удобен – код с его использованием выглядит нагляднее, нежели банальная проверка на null’ы или значения по умолчанию.

        Утрируя – это встроенный в язык Null object pattern.

  9. Дмитрий, а что такое “примесь”? А что такое mixin в Scala? А как мне extension-свойства помогут сделать “некий аналог multiple inheritance”?

    1. Дык… Класс А, от него наследует класс Б. То есть в Б уже ничего не добавить. А так, объявил специальный БЕкстеншнс и давай в нём нужных методов добавлять. И в зависимости от области видимости у Б магическим образом появляются всякие нужные методы. Вроде как декоратор, только проще.
      Екстеншн свойства позволят расширять интерфейс класса, собственно, свойствами, а не только методами, как сейчас. Вот и всё, вроде бы.

      1. Полей нема. А какой mixin без состояния? Понятно что состояние можно емулировать. Но всетаки.

      2. Очень советую глянуть на Scala mixin. Они могут и состояние добавлять, и реализацию интерфейсов, mixin’ы можно унаследовать от классов и других mixin’ов, mixin’ы могуть override’ить методы.

        Что из этого повзолят extension properties? Как статические методы вне класса, коими они будут являются, позволят сделать «некий аналог multiple inheritance»)?

    2. Примесь (mixin) – конструкт который путем множественного наследования (С++), добавляет некий функционал в класс. В языке Scala есть возможность подмешивать функционал к существующим классам. А вот в C# у нас проблемы – мы можем добавлять только поведение, т.к. начинка Extension-классов статична (как и они сами). А вот если бы этого не было, можно было бы классам добавлять поведение и свойства пост-фактум. Кстати: в принципе это можно делать через статический Dictionary<string,WeakReference>, но это очень хрупкое решение.

  10. Я предлагал некоторые из этих тем на SO ещё для 4.0 (http://stackoverflow.com/questions/138367/most-wanted-feature-for-c-4-0/426002#426002)

    В принципе я сомневаюсь в:
    1. поддержке dependency property на таком уровне, т.к. too specific
    2. NonNullable (х.з., вроде бы требует хитрого анализа в конструкторе и виртуальных методах, вызванных из конструктора базового класса). Плюс частично покрывается контрактами, хотя и довольно страшно.
    3. sequences (мне кажется это слишком редко нужно, чтобы делать special syntax)

    Пара дополнений:
    1. Правильная инициализация “кортежей” — Miguel de Icaza сделал в mcs –future http://tirania.org/blog/archive/2009/Dec-23.html
    2. Extension properties Eric Lippert вроде обсуждал, говорил что они пытались добавить в 4.0, но не влезло по времени
    3. Есть сильное подозрение, что для C# 4.0 рассматривают immutable types, вроде из блога того же Липперта

    Я лично хотел бы JavaGI, yield foreach, better string.Format, и какой-нибудь AOP. И immutable types. И “.?”.

    Что касается скрытой ленивости, хочется обобщения Lazy и Future с возможностью иметь арифметические операции и вызовы методов без потери отложенного вычисления (или будущего вычисления). Особенно хотелось бы магии вроде Lazy(disposable) implicitly implements IDisposable.

    Из невероятного, было бы ещё очень клёво получить quantum superpositions или junctions (http://en.wikipedia.org/wiki/Perl_6#Junctions), но в это я не верю. А, ещё я бы не отказался от 5 <= x <= 10 в качестве встроенной возможности.

    1. А можешь в кратце написать про то, что такое Java GI?

      1. http://homepages.cwi.nl/~ralf/JavaGI/paper.pdf
        Суть примерно следующая: This (ссылка на текущий тип в generic), определение имплементации интерфейса классом отдельно от класса интерфейса (ретроактивная имплементация интерфейса) и таким образом определение мультиметодов/dynamic dispatch:

        interface Count { int count(); }
        implementation Count [BTree] { int count() { return 0; } } // works also for Leaf
        implementation Count [Node] { int count() { return this.left.count() + this.right.count() + 1; }
        } 
        

        статические интерфейсы фабрик (применимы когда есть generic зависимость на фабрику), связанные интерфейсы.

      2. Так это ж классы типов, а не JavaGI =)

        Правда при текущей версии VM это можно будет реализовать только через делегирование и неявные преобразования. А именно этим меня пугает scala.

      3. Ну частично, как я понимаю, да, это type classes, но адаптированные к Java/C# (но это не только type classes). Я не обсуждаю реализцаю, т.к. версию CLR теперь менять не проблема, за счёт side-by-side CLR.

  11. Я за упрощение синтаксиса для частых операций.

    Добавили LINQ в своё время — давайте теперь сделаем comprehensions какие-нибудь.
    Механизму вывода типов есть ещё куда расти.
    Аналог import static из жавы было бы, наверное, классно, но возможны последствия.

    А ещё надо как-то параллельность и прочую конкурентность на уровень языка внести… Но это будет уже другой язык.

    1. Я в свой время перешёл с VB.NET в т.ч. из-за отсутствия import static в C# (ну это не главная причина, понятно).

      1. Времена были другие. Я когда начал на C# писать, то прямо так радовался, что нет больше “висячих” функций. Всё чётко. А теперь вот опять… История развивается по спирали, говорят.

      2. Да, ну просто extension methods вроде как покрывают большую часть случаев, а с остальными хелперами чёрт разберёт потом откуда взялись все эти методы (и на самом деле статических хелперов у меня довольно мало оказывается, большинство через IoC).

      3. Да я вот и думаю, что от import static вреда больше чем пользы. Только вот одно не даёт покоя.
        Press(Key.Enter).Then.Wait(20) просто прикольнее выглядит, чем Helper.Press(…) ну и так далее.
        F# зараза… Развращает.

      4. Так на С# тоже можно так делать, не?

      5. Ну для этого скорее нужен with, как показывает опыт JavaScript (Event.Behavior, например). Но в любом случае это возможно, через extension methods или обычный fluent interface.

      6. А в чем вред, если не секрет?

      7. Интеллисенс всегда поможет, точно также как и с var

      8. Если честно, то, когда я писал о своем варианте, то, за кадром, подразумевал вариант Nemerle, и не знал, что в java уже есть import static.

        Насколько я понял из первой ссылки в гугле – в java import static работает per namespace. В то время как в Nemerle пример с using System.Console работает в конкретном файле (как и обычный) – и не засоряет другие файлы/пространства имен.

        На самом деле код упрощается, особенно для всяких хелперных классов. Отчасти помогают extension методы, но все равно – попробуйте написать длинную формулу с использованием методов из Math.

        В том же F# это будет выглядеть, в начале, примерно как

        let sin = Math.Sin

        Да и в примерах проще писать WriteLine :)

  12. О! Я придумал. Надо добавить в язык атомы Ерланговские а.к.а. символы из Руби и ЛИСПов. Ну вы поняли. Чтобы вместо магических строк ими пользоваться. Тут и рефлекшн вам, и NotifyPropertyChanged, и прочие биндинги…

    1. Они не менее магические, на само деле. Я пользовался, не вижу отличий от строк (писать чуть короче). Причина Ruby к C# не применима (immutability/interning).

      1. Говорят их сравнивать быстрее.

      2. Конечно, interning.

      3. Хм.. Это оказывается interning и есть. А почему не применима?

      4. Потому что C# уже решает этот вопрос для любых строк, вводить новый тип строк не обязательно. С другой стороны в C# нет gsub! и прочих “!” на строках.

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

    Правильная деинициализация кортежей необходима, если язык поддерживает кортежи, от C# я ожидаю:
    var (sex,death) = GetMeaningOf(life);

    yield из анонимных функций это безусловно правильно и скрытых опасностей в нем, кажется, не больше, чем в замыканиях. Правда я бы добавил возможность объявления функций внутри методов, например, запись
    def add(x, y) { return x + y; }
    где тип x, y выводиться по использованию ниже,
    мне кажется явно лучше
    var add = (int x, int y) => { return x+y; }

    Extension properties не очень желанная мной фича, но, наверное, полезная.

    Думаю, что контракты с run-time/compile-time проверкой более элегантно решают проблему, чем ввод нового типа NonNullable – меньше будет засоряться интерфейс, сохранится совместимость c предыдущей версией фреймворка.

    Анонимные именованые типы вводить не стоит – они решают задачу, которую решать не стоит: использовать кортежи в публичных интерфейсах – дурной тон.

    Скрытое * не подходит, так как сложно читать код, когда используется что-то скрытое, а свойство исходника быть читаемым важнее быстрых хаков при его создании.

    Все остальное вредно реализовывать на уровне языка, если C# будет поддерживать метапрограммирование, то эти предложения (сахар для dependency property, sequence-инициализация, цепочная проверка на null, приватные поля для свойств и yield foreach) можно включить в стандартную макро библиотеку.

    Повторю свой коммент на хабре, для меня критично

    1. Насчет метапрограммирования – согласен. Бесполезно расширять язык если сам пользователь может его расширить.

  14. По всей видимости Микрософт однажды “изобретет” Nemerle и назовет этот C#-X.0 – новым революционным языком.

    1. Вполне возможно :)

    2. Боюсь, что этого так и не случится. Я уже потерял надежду.

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

      ФП полноценно в C# придет только когда из него уйдет Хейльсберг.

      1. Так это и не нужно толком. Есть F# для всех кто фетишизирует ФП, а для LoB подходит то, что есть в F#. Да, понятное дело что есть очень много сложных страшных фич вроде Pulse & Wait которые не особо мэпятся на аутсорсинг, но мне, собственно, все равно – если кто-то недотягивает, что поделать. А конкретный юзкейс для ФП лично для себя очень сложно вычерпать. Я пытался – честно!

  15. Исправьте, пожалуйста, «инкаспулировать» в конце.

  16. Ну всё чуваки, с меня хватит. Я поглядывал в сторону дот нета, но теперь окончательно определился что буду пилить консервативную яву.
    Ну вас нахер братцы с вашими синтаксическими сахарами.

    1. Да мы и не заставляем. Только не пытайтесь убедить нас что у вас там в Java лучше – а то мы вам примомним properties, дженерики и еще вагон и маленькую тележку “непиленного консерватизма”.

      To each his own…

    2. Полностью поддерживаю.

      Нафиг этот сахарок не нужен. Я жду того момента, когда C# просто разорвёт от фич. И они ещё говорят, что С++ сложен!

      Ява минимальна, и всем хорошо – и кодерам, и майнтейнерам, и ревьюерам. Ну а программисты пусть балуются плюшками из C# :)

    3. “Нафиг синтаксический сахар” для меня звучит как “я хочу писать больше кода чтобы решить ту же самую задачу”. В чём суть и польза этой идеи?

      1. Польза в том, что несмотря на обилие кода в нём проще разобраться. Когда то министерство обороны США объявило конкурс на создание языка для своих нужд. Победила Ада – прекрасный паскалеподобный язык. Но в нём тоже много сущностей, и это явно опасно.
        Другая крайность – слишком бедный язык, например тупо байт код.

        Тут аналогия с языком и алфавитом – в китайском алфавите ну просто совсем дохренища иероглифов, когда другие пошли по принципу базовый набор букв, и слова формировать из букв.

        Нужно подбирать так чтобы базовых сущностей было столько чтобы можно было их быстро (точнее сразу) выяснить, были удобные средства абстрактизации (ООП) и всю сложность перенести из языка на библиотеки. При этом строить по одной определённой философии. Если есть какие то рутиные часто повторяющиеся операции (например создавать гетеры и сетеры) то это нужно перенести на инструмент разработки. В Яве именно так. Хотя конечно лично мне, как делфисту, не хватает свойств классов.

        То как тут бойко обсуждаются какие то невнятные и ненужные вещи (я без них прекрасно обхожусь, да) мне показало основную тенденцию C# — впитывать всё нужное и ненужное.

      2. По-моему, если синтаксический сахар прозрачен и интуитивен, то он нужен, если же он усложняет процесс понимания кода новичком (старики и так поймут), то он не продуман и возможно излишен.
        Взять хотя бы инициализацию полей класса инлайн (хоть это немного более чем сахар). Вполне интуитивно и даже более читабельно, чем инициализация в конструкторе.
        Или те же свойства. Намного более прозрачно, чем явное использование функций.
        По мне так лучше убрать дублируемый синтаксис типа инлайн делегат и ламбда. Зачем их двое. Насколько я понимаю они полностью дублируют друг друга. Или такие вещи как встроенные типы: . Вполне можно обойтись системным обозначением и меньше зарезервированных слов необходимо знать.
        Я бы ещё подчистил бы систему и язык от старого мусора. А то так можно до бесконечности возить за собой этот вагон и маленькую тележку. Конечно конвертор старого в новое необходим.

      3. Aleksey Berezan Avatar
        Aleksey Berezan

        Правильно!
        Зачем ведь обратная совместимость :)

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

      5. Aleksey Berezan Avatar
        Aleksey Berezan

        Конвертацию для систем, которые уже в продакшине, большинство делать не будут. Потому-что:
        1) после конвертации систему нужно будет перетестировать. А это требует дополнительных человеческих ресурсов(уж далеко не в усех есть авто-тесты);
        2) Понятно, что найденные баги после конвертации нужно будет исправлять, а потом тестировать фиксы.
        * Да, да, я понимаю, современные парсеры очень крутые и переконвертят все так, чтобы новых багов не появится. Да, это так. В идеальном мире. Или парсер должен обладать исскуственным интеллектом чтобы смочь предвитеть все подводные камни, что могут появится после переконвертации кода. Наверное, звучит неубедительно. Привожу пример, буквально на днях столкнулся. Сопровождал систему, которая уже давно в продакшине.
        В класе имеем поле и соотв. свойство:

        private string _name;
        public string Name
        {
        get{return _name;}
        set{_name=value;}
        }

        Поле используется только в свойстве. Хм… Ну так сделаем авто-проперти. Мелочь, но приятно.
        public string Name
        {
        get; set;
        }
        Сказано, сделано, скомпилено :) Для кейса, над которым я занимался, все работало отлично(а с чего бы ему не работать? :) ). Через несколько дней баг вылез совсем в другом месте системы. В том месте, где использовалась бинарная (де)сериализация инстансов этого класса(балы попытка десериализации ранне(до правки) сериализированих обьектов). Вот, а казалось бы, плёвое изменение…
        Ничего не имею против современных парсеров, но по-моему, парсер, который может учитывать подобные тонкости – это уже что-то из Азимова :)

        Так что, фичи фичами, а самый лучший способ делать что-то новое не ломая при этом старое – это не трогать старое.
        Вот и Compatability.

  17. Лично меня очень сильно раздражает реализация перечислимых типов. Явное объявление поля _value в перечислимом типе это нечто, не говоря уже о том, что для базовых операций над экземпляром перечисления тяжело используется рефлексия. Разработчики .NET могли бы перевести реализацию перечислимых типов на обобщения уже в .NET 2.0, сделав базовый класс Enum. Но собственно реализация то реализацией, но каковы её последствия для разработчика:
    1. Невозможно использовать enum в качестве ограничения на тип специализации шаблонного класса или метода. Где это может пригодится, думаю очевидно.
    2. По причине 1 для Enum нельзя писать методы расширения. Правда можно для производных от Enum классов, т.е. для собственно конечных перечислимых типов. Но расширить функциональность сразу всех перечислений не выйдет.
    3. Вместо вызовов IsFlagSet, SetFlag, ResetFlag, ReadFlag, WriteFlag и т.д. (таких методов в классе Enum не существует, но, думаю, понятно что они должны делать) приходится повсеместно использовать громоздкие конструкции из операторов “==”, “|”, “~”, “&”. И по причине 1 и 2 нельзя реализовать методы расширения.

    Вот пример. В моём приложении тяжело используются DependencyProperty перечислимых типов. Было большое желание реализовать универсальный упаковщик перечислимых типов, в котором держались бы упакованные копии элементов перечислений, чтобы избежать созданий сотен тысяч промежуточных объектов, при работе с Binding’ами и значениями Dependency свойств. Т.е. реализация свойства должна была выглядеть как:

    MyEnum MyProperty
    {
    get { return (MyEnum)GetValue(MyPropertyPropery); }
    set { SetValue(MyPropertyProperty, value.Box()); }
    }

    Ну само собой по вышеназванным причинам не вышло :(

  18. Синтактических сахар для dependency property, yield из анонимных функций, Правильная инициализация кортежей и Extension properties было бы неплохо. Всё остальное имхо не нужно.

    Ну и поделюсь своими идеями:
    1. Оператор `A`, который возвращает имя объекта A в виде строки (` – апостроф, а не одинарная кавычка). Пригодится, например, при реализации INotifyProperty + смена имени типа или метода при рефакторинге будет успешно обработана. Примеры:

    int IVar = 0;
    class ACls { public int F {get;set;} }

    `int` == “Int32”, `ACls` == “ACls”, `IVar` == “IVar”, `ACls.F` == “F”

    2. Контракты данных. Описывает доступные операции над объектом.
    Пример:
    class A {
    public void M() {}
    public static A operator+ (A a, A b) { … }
    }

    class B {
    public void M() {}
    public void M2() {}
    public static B operator+ (B a, B b) { … }
    }

    теперь объявляем контракт:
    datacontract Ctr {
    void M();
    static Ctr operator+ (Ctr a, Ctr b);
    }

    После чего получаем следующие возможности:
    а) Некий аналог var
    A a1 = new A();
    A a2 = new A();
    Ctr ctr1 = new B();
    Ctr ctr2 = a1;
    Далее из ctr2 будет доступен метод M() и возможность сложить его с другим объектом: ctr2 + a2
    При этом во время компиляции произойдёт подстановка реальных типов, т.е. Ctr ctr2 = a1; будет заменено на A ctr2 = a1; со всеми вытекающими последствиями. Соответственно во время компиляции ctr1 + ctr2 приведёт к ошибке.

    б) Автоматическое обобщение методов:
    void Method(Ctr a) {…}
    Во время компиляции произойдёт дублирование методов под каждый из типов, т.е. если есть вызовы Method(new A()) и Method(new B()), то будет автоматически выведено 2 метода с именем Method, но разными типами.

    в) Использование в качестве ограничений на тип в шаблонах:
    class GenCls where T: Ctr {}
    Соответственно теперь при реализации GenCls будет доступен интерфейс Ctr на внутренние типы. Работать будет аналогично за счёт генерации нескольких классов с разными типами для T.

    Варианты б) и в) лучше реализовывать не на основе кодогенерации (как я описал), а за счёт добавления этой возможности во фреймворк.

    1. Фича 1 мне очень нравится, при условии что это значение статически компилируется как константа, а не является shorthand’ом для вызова злотсного reflection- или Expression-ориентированного куска кода.

  19. Очень хотелось бы получить не как можно больше новых фич C#, а полноценную поддержку старых.
    Например, анонимные методы, lambda-expressions, linq – очень удобная вещь, но вот во время дебага проверить работу какого-либо выражения, вставив его в Watch, нельзя, и также нельзя во время дебага изменить код внутри анонимного метода да и метода, который его содержит. А ведь таким способом исправляется значительная часть мелких ошибок(типа +1/-1 в цыклах, методы для генерации строк и пр.), и перезапускать после каждой маленькой правки проект, который запускается 2-3 минуты(а потом часто еще и парольчик нужно ввести, перейти на нужную форму и т.д.), это еще то удовольствие :)
    Не поймите неправильно, я не против новых фич, более того, я даже за. Просто по причинам, указаным выше, многие фичи часто попросту не используются, вследствии чего и забываются. Вот часто так и получается, что серьезные приложения пишем на “pure” C#2.0(еммм, анонимные методы, ок, “almost pure”) а на C#4.0 – хелло вордлы всякие.

    1. Ну в этом я не соглашусь на 100% – даже если отладка где-то страдает, это не значит что на этом нельзя писать. Я не шучу! Посмотрите например на разработку в С++ без Intel Parallel Studio. А как насчет отсутсвия вменяемой 64-битной отладки в VS2008 и более ранних версиях? Да, это нехорошо, но мы все равно все это пишем, поставляем на этом решения.

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

        > Посмотрите например на разработку в С++ без Intel Parallel Studio.
        > А как насчет отсутсвия вменяемой 64-битной отладки в VS2008 и более ранних версиях?
        Спору нет, пишем, поставляем решения. Но ведь намного приятней когда разработка в С++ ведется С Intel Parallel Studio, VS2008 есть 64-я отладка, правильно?

      2. * упс, извините, опечатался, хотел написать
        а в VS2008 есть 64-битная отладка,

      3. Ну, mixed-mode отладка для 64-битных приложений не работает в VS2008

    2. ” перезапускать после каждой маленькой правки проект, который запускается 2-3 минуты(а потом часто еще и парольчик нужно ввести, перейти на нужную форму и т.д.), это еще то удовольствие :)”

      Эээээ а юнит-тесты?

      1. А не всегда в проекте есть юнит-тесты. А в большых проектах с legacy кодом юнит тесты написать еще и очень проблематично, если реально вообще.

      2. Ну как бы тесты это первый шаг перед изменениями в любых проектах (не знаю, есть ли это в книжке про legacy code, но должно быть). Хотя интеграционные вместо юнит тоже ок.

        Кстати, на legacy code написать юнит тесты абсолютно реально с помощью Moles или TypeMock.

        Но интеграционные тесты тоже решают вопрос с необходимостью залогинится и т.д., если они не слишком медленные (не 2-3 минуты).

      3. Ну, все равно бы еще чуток поспорил, да чуствую и так уже в оффтоп зашли :) Так что пожалуй на этом и остановимся.

        Тем более что без тестов, что с ними, все равно хотелось бы иметь полноценную отладку.

  20. Чего бы я хотел видеть в следующей версии C#
    1)managed компилятор, compiler as service, объектную модель компилятора и желательно полегче, чем CCI
    2)Полное квази-цитирование, чтобы по любому коду C# строилось expression tree. Желательно еще добавить механизмы для сплайсинга.
    3)Поддержку языком кортежей
    4)Паттерн-матчинг (маловероятно, но все же)
    5)Глобальный вывод типов

    Из того что описано в самом посте – поддержку ленивости с запоминанием. Правда в условиях побочных эффектов будет приводить к множественными разрывам мозга. Чтобы избежать эффекта стоит также встроить в язык поддержку иммутабельности и функциональной чистоты.

    1. Все будет так (пожалуй, кроме глобального вывода типов), и даже больше, но в Nemerle 2.0. :)

      1. Вспомнилась сцена из фильма “Спиздили”, когда Ави прилетает из США в Лондон.
        Действующие лица Ави (А) и Даг (Д).
        А – Я очень не люблю выбираться из своей страны, особенно когда выбираюсь не на песчаные пляжи, где все ходят в бикини и подтаскивают мне коктейли
        Д – Но у нас есть песчаные пляжи…
        А – И кому нах** они нужны?

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

        Кроме того, несмотря на продолжительное существование, не было написано ни одного killerapp на этом языке.

      2. Это, конечно, флейм уже, наверное, но можно несколько примеров несогласованности на вскидку? Чего не хватает до того, чтобы являться функциональном языком, по сравнению с F#? Понятие юзабельности размытое, разве конструкция из C# “var foo = new Dictionary()” более юзабельна, чем “def foo = Dictionary()” из немерле; но это мелочи, по сравнению с (в C#) запуска внешней тулы для генерации парсера по грамматике, когда в немерле грамматику можно описать в атрибуте и дело сделано.

        Проекты на Nemerle есть, но в основном внутренние. Из крупных – сам компилятор. Могу привести в пример еще http://uniquation.com это еще не killer app, но уникальная разработка.

      3. Как минимум не хватает карраинга, first-class operators, монадного синтаксиса (хотя вроде ко второй версии что-то прикрутили), глобального вывода типов, лакончиности записи.

        Это все можно сказать просто глядя на исходники на Nemerle, даже не писать ни строчки. Если начинать писать, то можно еще много чего найти.

      4. > Это все можно сказать просто глядя на исходники на Nemerle, даже не писать ни строчки.

        Если на нем поработать пару дней, то станет ясно, что это все преувеличение.

        Сurrying:
        def f(a,b) { a + b }
        def g = f(2,_);
        WriteLine(g(1));

        Operator as a first class object:
        def z = [1,2,3].Fold(0, _+_);
        WriteLine(z);

        Вывод типов работает внутри методов, уровнем выше он не нужен, так как декларация типа в интерфейсе является контрактом.

      5. Этого и следовало ожидать. Очередной бред сивой кобыли вместо аргументов.

        Все кроме отсутствие глобального вывода типов абсолютнейшая чушь. Аргументы тут уже привели, так что не буду повторяться. Скажу только про мнимую “лаконичность”. Начнем с того, что к указанным выше “недостаткам” (в кавычках, так как они высосаны из пальца) вообще никаким образом никакого отношения не имеют. Ну, а закончим тем, что вот уже 6 лет вот здесь:
        http://code.google.com/p/nemerle/source/browse/nemerle/trunk/snippets/raytracer/
        лежит примеры реализации raytracer-а на ML, C# и Nemerle демонстрирующие ту самую лаконичность.
        Не трудно заметить, что минимальный пример на Nemerle практически идентичен по длине минимальному примеру на C#:
        http://code.google.com/p/nemerle/source/browse/nemerle/trunk/snippets/raytracer/ray2.ml
        http://code.google.com/p/nemerle/source/browse/nemerle/trunk/snippets/raytracer/ray.n
        http://code.google.com/p/nemerle/source/browse/nemerle/trunk/snippets/raytracer/ray-cs.cs

        Так что продолжайте дискредитировать себя и дальше делая заявления не соответствующие действительности.

      6. > Nemerle практически идентичен по длине минимальному примеру на C#

        Опечатался. Имелось в виду “идентичен по длине минимальному примеру на ML”. Пример C#, конечно же намного длиннее.

        Кроме того, не надо забывать, что Вы Стас говорили о включении фич в C#:
        “Чего бы я хотел видеть в следующей версии C#
        1)managed компилятор, compiler as service, объектную модель компилятора и желательно полегче, чем CCI
        2)Полное квази-цитирование, чтобы по любому коду C# строилось expression tree. Желательно еще добавить механизмы для сплайсинга.
        3)Поддержку языком кортежей
        4)Паттерн-матчинг (маловероятно, но все же)
        5)Глобальный вывод типов”

        Уж что, что, а Nemerle в любом виде лаконичнее C#-а. Так что кроме как попыткой сменить тему обсуждения ваши кивки на лаконичность назвать нельзя.

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

      7. Стас. Без обид, но единственное адекватная мысль в твоем сообщении – это замечание о том, что девелоперов у Nemerle мало.

        В остальном это полный гон. Ты или говоришь о том, что в глаза не видел, или почему-то озлоблен и намеренно кидаешь дерьмо на вентилятор.

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

        Скажем Nemerle on rails (аналог Ruby on rails), но в статически типизированном языке и с поддержкой LINQ-а потянет на эту роль?

        Или скажем генератор парсеров “шаговой доступности” – PegGrammar, который использовать так же просто как регекспы (так как он реализован в виде макроса), но при этом работающий со скоростью близкой к рукописным парсерам и позволяющим разбирать грамматики самых сложных для разбора компьютерных языко?

        А что за killerapp созданы на F#-е?

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

        Если я ошибаюсь, то с радостью послушаю конструктивный рассказ о “несогласованностях”, о том почему “Nemerle никак не является функциональным языком”, о том почему “не может тягаться с даже F#” и в особенности о том почему именно “даже” (что F# такой плохой язык?). Ну, и конечно же очень интересен рассказ о том в чем заключается “никак по юзабельности не дотягивает до C#”. А то те кто этот язык пробовали почему-то потом постоянно плюются пытаясь писать на C# по той же самой причине но с точностью до наоборот.

      8. Точно, я еще забыл упоминуть отношение разработчиков к какой-либо критике. Сразу объявляется “полным гоном” или “вот тебе макросы, сделай сам”

        Для F# killerapp давно существует и называется F# Web Tools.

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

      9. Хотя бы одна статья – http://habrahabr.ru/blogs/nemerle/104968/ Код оттуда живой и работает в http://uniquation.com

      10. > Точно, я еще забыл упоминуть отношение разработчиков к какой-либо критике.

        Стас, помилуйте! Не надо этой демагогии. Критике мы только рады. Но критика должна содержать достоверные факты, а не основываться на лжи и выдумках, как ваши суждения. Тогда от нее есть толк.

        Что до “вот тебе макросы, сделай сам”, так этому радоваться надо. Язык и его библиотеки и так сдержат больше чем любой другой язык под дотнетом. А то чего нет, но очень хочется прикладному программисту он действительно может сделать сам. И примеров этому не мало.

        Например, как-то на форум зашел некий dsorokin и заявил, что дескать, на его взгляд F# лучше чем Nemerle, так как в первом есть ComputationExpressions. Ему резонно заметили, что встраивать такую штуку в язык при наличии макросов не имеет никакого смысла, и что ComputationExpressions можно реализовать самостоятельно в виде макроса.

        В отличии от Вас dsorokin не обиделся на эти слова, а взял и опробовал реализовать такой макрос. В результате у него получилась реализация которая сейчас доступна в snippets/ComputationExpressions репозитория немерла.

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

        > Для F# killerapp давно существует и называется F# Web Tools.

        Помилуйте! Это же неуловимый Джо. Неуловимый потому что его на фиг не нужно никому ловить. К тому же проект явно не развивается уже несколько месяцев и это при том, что релиза так и не было.

        Для Немерла тоже есть похожая разработка называется Nemerle on rails. Очень приятный фрэймворк созданный в рекордные строка. Код доступен на гугкоде. Легко гуглится.

        > PegParser может и существует, но увидеть бы хоть одну статью с примером его использования.

        Примеров использования хватает. Тот же парсер C# 4.0 доступен здесь:
        http://code.google.com/p/nemerle/source/browse/nemerle/trunk/snippets/peg-parser/CSharp/
        Более простые примеры:
        Простой строчный калькулятор:
        http://code.google.com/p/nemerle/source/browse/nemerle/trunk/snippets/peg-parser/Calculator/
        JSParser http://code.google.com/p/nemerle/source/browse/nemerle/trunk/snippets/peg-parser/JSParser/

      11. >Например, как-то на форум зашел некий dsorokin и заявил, что дескать, на его взгляд F# лучше чем Nemerle, так как в первом есть ComputationExpressions. Ему резонно заметили, что встраивать такую штуку в язык при наличии макросов не имеет никакого смысла, и что ComputationExpressions можно реализовать самостоятельно в виде макроса.

        Только в итоге оно было реализовано через дополнительные ключевые слова, что не есть гуд.

      12. Покажите мне другой язык где это вообще возможно?!
        В том же F# пришлось править код компилятора.

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

        Так что серьезно сравнивать Немерл можно толко с Лиспом.

        Что касается ключевых слов, то сам автор данного макроса как-то высказался, что это даже хорош, так как четко показывает что происходить.

        Во второй версии немерла, работа над которой начнется в ближайшее время (а точнее уже потихонечку уже ведется, так как PegGrammar – это по сути прототип новой макро-системы), можно будет вводить практически любые синтаксические расширения. Единственное ограничение они должны хоть как-то отличаться от синтаксиса, что уже использован для других возможностей.

      13. Кстати, в F# точно так же было введены дополнительные ключевые слова let! и return.

      14. Ну, и конечно же очень интересен рассказ о том в чем заключается «никак по юзабельности не дотягивает до C#». А то те кто этот язык пробовали почему-то потом постоянно плюются пытаясь писать на C# по той же самой причине но с точностью до наоборот.

        Вот у меня почему-то “не срослось”, хотя честно пробовал. Мне кажется что даже тот же Boo, который я (и не только я) реально использовал (даже Айенде книжку накатал) как-то лучше “продан”, что ли, чем Nemerle. Ну и синтаксис – дело конечно наживное, но я беру Boo и там практически все понятно, синтаксис знакомый. А вот Nemerle, как и F# например, нужно целенаправленно изучать.

      15. Забавно, если поменять местами Nemerle и Boo, то высказывание станет верно для меня)

        Синтаксис F# действительно немного пугает, а Boo мне показался реинкарнацией Python для .Net, из них троих, c синтаксической точки зрения Nemerle – почти C#, только типы нужно не перед переменной/методом писать, а после.

      16. Осмелюсь предположить, что до этого Вы хорошо знали Питон. Потому у Вас все так хорошо прошло с Бу.

        Что до Немерла, то как я понимаю, вы не осилили варианты (которых попросту нет в Бу). Иначе, при наличии опыта программирования на C# освоение немерла не составило бы труда.

        Как я уже говорил, имеет смысл сделать вторую попытку прочитав “Язык Nemerle” ссылки на который я приводил выше.

        Кстати, макросистема Бу позаимствована у Немерла.

      17. Почему в 2.0 то?

        Все кроме глобального вывода типов уже есть и отлично работает.

Leave a reply to hc Cancel reply