Как стать автором
Обновить

Комментарии 169

Фух, неужели я это дочитал? =)

Статья неплохая, но, как мне кажется, слишком много отвлечённых разговоров о других языках, их проблемах и парадигмах. Информация про сам D и его плюсы теряется среди всего прочего.
Просто не хотел писать короткий список с перечислением особенностей языка, хотелось дать именно сравнение с другими языками. Если Вас интересуют именно особенности D, могу порекомендовать статью на Википедии, ссылку приводил.
Нет, я немного не про то.
Сравнение с другими языками штука хорошая, но в статье больше описание других языков, статья получилась «Почему C++ и C# хуже D».
Эх, если начать расписывать достоинства всех языков, то получилось бы страниц 20-30. Наверно, тогда бы никто до конца не дочитал. Итак пришлось статью сильно сократить — ряд особенностей D пришлось просто вынести в раздел «Заключение», хотя те же многопоточное программирование и создание шаблонов были достойны развёрнутого описания.
очень похожа на курсовую, например по летающей тарелке. Сперва воспоминания конструкторов, оказавшихся от проектирования воздушных шаров, потом обзор существующих летательных аппаратов, их недостатков и достоинств нашей тарелки. На которые поиски почемуто не хватило места. Если бы я представлял например перл, я бы привел пару связок типа map grep sort и объяснил какие задачи эти конструкции решают.
А под какие аппаратные архитектуры существуют компиляторы этого языка?
Под i386 и x86_64.
Список поддерживаемых ОС можете посмотреть сами на оф. сайте в разделе загрузки.
Так же есть сторонние компиляторы под платформы LLVM для D1 и D2 и .NET для D2 и компилятор gdc из проекта gcc. Подробнее см. здесь.
GDC в теории поддерживает все архитектуры поддерживаемые GCC, но на практике не везде портировали рантайм языка.

Люди успешно собирали под ARM и MIPS
Уффф. Слишком много воды и размышлений не по делу. Хватило бы развёрнутого (и с примерами) заключения.

Всё остальное словоблудие (увы, но иначе я это назвать не могу) можно спокойно убрать: зачем рассказывать про полноту по Тьюрингу здесь? Кто-то сомневается, что D тьюринг-полный язык? Зачем вообще упоминать SQL, Brainfuck? Они же совсем мимо кассы…

А куча утверждений весьма спорна:

1. Менеджер выбирает C++ не потому, что ему проще отмазаться в случае завала (причина достаточно глупая), а потому, что программисты и знания по языку не являются дефицитом. По языку есть тонна устоявшихся методик программирования, оценки проектов и рисков, известна и подтверждена опытным путём сфера эффективного применения и т.п.

2. Название Brainfuck не служит цели популяризации языка: язык шуточный и название объясняет саму суть языка. Не более того.

и т.д.
И «realize-версия» =)
Согласен, вводную часть статьи можно было опустить. Просто нужно было с чего-то начать, подумал, что так будет правильней.
А можете написать чуть-чуть подробней про «устоявшиеся методики программирования, оценки проектов и рисков, сферу эффективного применения»? Или хотя бы ссылку на литературу дать? Мне правда интересно.
Так, например, поступила Microsoft при разработке платформы ASP.NET – скрипты для браузера могут быть написаны на любом языке платформы .NET (например, на C#) и затем автоматически преобразованы в соответствующий код на JavaScript.


Подскажите плз где про это почитать.
возможно автор имел ввиду ASP.NET AJAX с его кодогенерацией.
Если честно, не помню, где именно про это читал. Просто сами попробуйте создать веб-форму и добавить туда валидаторы — соответствующий код на JavaScript должен быть создан автоматически (собственно, в статье я писал именно об этом функционале).
Ну а если Вы спрашивали именно о компиляции C# в JavaScript, то можете посмотреть script# для компиляции C# в javascript и jsc compiler для компиляции на IL в javascript, actionscript
Можно ли убить дракона? Можно, но не убить и не дракона


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

2)script# не есть часть ASP.NET и не написан MS.
Спасибо, учту. Если не возражаете, добавлю примечание к статье с ссылкой на Вас как на указавшего недочёт.
Есть кстати еще sharpkit.net/ но тоже не от MS. Это я не спорю, а так, вдруг вам интересно :)
ну где же D с примерами? где пример кроссплатформенной работы с потоками?
не могу промолчать про .NET и C# в частности.
C# за счет лучшего контроля ресурсов позволяет заметно усложнить проведение DoS-атаки, но делает службу более уязвимой к DDoS-атаке из-за более низкой скорости работы.

ну-ну, а если сразу на ассемблере будет написано, то DDoS может пройти мимо.

Основная проблема, которая для меня крайне важна, это компиляция в промежуточный язык Common Intermediate Language (CIL), что делает декомпиляцию тривиальной задачей. Больше того, для этого существуют специальные инструменты.

проблема заключается именно в модуле лицензирования для ПО, который обходится практически для всех коммерческих программ. вопрос про сверхсекретные алгоритмы чего-либо думаю опустим. так что MSIL не является проблемным местом.

Не много подумав, можно прийти к выводу, что использование платформы .NET так же опасно, как и C#. Поэтому лично моё мнение – не стоит писать на языках, ориентированных в первую очередь на эту платформу.

честно говоря каких-либо вменяемых доводов так и не было, кроме покупки лицензии на windows. т.е. денег на разработку есть, на оплату менеджеров и т.д., а вот $400 на хотя бы Windows Web Server нету.
и кстати, почему не вспоминаем сотни undefined behaviour в стандарте самого языка C или C++, где уже надо ориентироваться на сам компилятор. а тут еще и D — темная лошадка.
>> ну где же D с примерами? где пример кроссплатформенной работы с потоками?
Надеюсь, войдут в следующую статью.

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

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

>> денег на разработку есть, на оплату менеджеров и т.д., а вот $400 на хотя бы Windows Web Server нету
Тут уже каждый сам для себя решает, но критика принимается.

>> почему не вспоминаем сотни undefined behaviour в стандарте самого языка C или C++
Просто решил не лезть в эти дебри. Возможно, в следующий раз упомяну и их тоже.
В D нет понятия undefined bahavior — это принципиальная позиция автора языка. Но вот со спецификацией слукавили, и сильно — то, что есть для D, и рядом не лежало по полноте со стандартом плюсов. Если детализировать — то объёмы получатся схожими. D очень красивый и умно спроектированный язык, но что он много проще плюсов я бы не сказал. На поверхности — да, но если лезть в нюансы того же duck typing, во взаимодействие с миксинами и модель преопредления опреаторов — ох много там углов… Однако мощно, куда мощнее плюсов в большинстве аспектов.
Почему-то у вас все преимущества D сводятся к недостаткам С*. =)
Возможно, потому что сам программировал на C# и C++. Как известно, все познается в сравнении, вот и решил написать статью в таком ключе.
Вы то его может и выбираете, но зато все остальные — нет.
Статья именно об этом. Удачного Вам программирования на Вашем любимом языке.
Может быть, поделитесь с сообществом о своих предпочтениях?
C++ и Haskell. Первое — как неизбежное зло (я работаю с околоэмбедщиной и нестандартным железом), второе — как универсальный рабочий инструмент.

И к математике Haskell, вообще говоря, имеет не большее отношение, чем C++ или D.
Смело Вы так, сразу за всех остальных сказать.
Минусы к комментарию заставили меня прочитать статью :)

Я то не против языка D. Мне он даже нравится в качестве замены С++.

Но я имел ввиду то, что не видел, чтобы данный язык использовался где-то в промышленных масштабах. И это самое печальное.
А если от D откажутся? Шансы не меньше чем Micrisoft откажется от C#. Вот захочет человек и откажется.
Вероятность отказа от поддержки всегда существует, тут конечно, Вы правы.
Из плюсов D в этом смысле могу сказать:
1) Развивался с 1999 года, т.е. он старше C#
2) Имеются по меньшей мере 3 открытых разрабатываемых компилятора. Собственно, C++ безопаснее C# именно из-за отсутствия патентных ограничений.
Действительно статье не хвататет конкретизированной практики, например:
одна и та же задача, реализованная в C++, Java и D, где последний явно выигрывает по всем характеристикам.

P.S. Всё равно статья позитивная, рад читать, что новые языки борются за свое место под солнцем и претендуют на то, чтобы потеснить старичков.
Можете почитать статью Андрея Александреску «Место для D», там есть несколько интересных примеров. Да и в приведенных мною статьях тоже есть ряд интересных примеров. Но просьба принята, в следующий раз постараюсь сделать упор в том числе на такое сравнение.
Как программисту на C++ было интересно сравнить D и C++:

1. Мне кажется, что про сборку мусора пример не очень удачный.
>> Number* c = a + b;
как вы и предлагаете, можно создавать реальный тип объекта с помощью new. Возможна техника, когда полученный таким образом объект скрывается внутри класса, который управляет его временем жизни (как пример умный указатель). Какие ограничения вы имеете ввиду, говоря о проблеме с умным указателем внутри, скрывающим детали реализации?

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

2. Мне показалось не совсем корректным сравнение размеров стандарта: в стандарте языка C++11 специфицирована STL (standard template library), описание которой начинается с примерно 500-й страницы. То есть по объёму уделённому только языку, получается примерно столько же, сколько C#4. Понятно, что без библиотек сложно программировать, и программисту C#/D точно так же нужно знать библиотеки стандартные для языка. Просто они описаны в стандарте C++, но в отдельной документации для C#.
>> Какие ограничения вы имеете ввиду, говоря о проблеме с умным указателем внутри, скрывающим детали реализации?
Если в двух словах, две.
1) При передаче указателя в функцию, которая ничего не знает об умных указателях (например, из внешней библиотеки). Тогда придется блокировать умный указатель, чтобы он не освободил объект до того, как функция вернет управление (актуально в первую очередь для многопоточных программ). Соответственно, возникают проблемы связанные с вызовом функции разблокировки. Например, ее просто могут забыть вызвать или ее вызов будет пропущен в результате генерации исключения.
2) При создании циклических структур данных, например — кольцевых связанных списков, когда класс A ссылается на класс B, а B — на A. Тут, конечно, можно применять другой вид умных указателей (тот же weak_ptr), чтобы разорвать кольцо, но это еще больше усложняет проектировку и эксплуатацию таких классов.

>> Мне показалось не совсем корректным сравнение размеров стандарта
Критика принимается. С другой стороны, думаю, Вы не станете возражать, что синтаксис C++ сложен. Взять хотя бы пример со структурой классов, унаследованных от одного базового Object, который обеспечивает какую-то базовую функциональность (например, toString). Тогда в случае применения тех же умных указателей в программе будет возможен примерно такой код:

smartPrt p;
//Разные функции
p->toString();
p.toString()
Всё равно пример неудачный.
Теперь представьте, что где-то в вашей программе появляется примерно такая строчка:

Number* c = a + b;

где a и b – указатели на Number, т.е. фактический тип переменных не известен.

В программе на C++ не может встретиться такая строчка, ибо не разрешено переопределять операторы для указателей. Хотя бы один должен быть классом. Так что данный пример вообще невозможен.
Оба должны быть умными указателями, т.е. классами. Извините, что не рассмотрел этот вопрос подробно — все же не основная тема статьи.
Вот. Тогда и ответ будет умным указателем. :)
Или это реализовать таким образом:
class Number;
class Integer : public Number;
class BigInt : public Number;
...
class AnyNumber
{
public:
...
private:
    Number* value;
    ...
};

AnyNumber operator+ (const AnyNumber& a, const AnyNumber& b);

При необходимости в AnyNumber зашивается логика copy-on-write, позволяющая избежать лишних копирований таких типов как BigInt. А напрямую доступ к Number и его потомкам не давать. По сути тоже как бы умный указатель.
Да, Вы правы. Спасибо за пример кода. Можете еще книгу Джеффа Элджера полистать, думаю, Вам может быть интересно. Там вообще очень много написано про умные указатели (их там добрый десяток) и сборку мусора в C++.
Например, C# всегда делает проверки выхода за пределы массива, что делает подобные ошибки гораздо менее вероятными, но теряя при этом в производительности (переполнение буфера всё ещё потенциально возможно из-за возможных ошибок в реализации компилятора или стандартных библиотек).
не всегда, а только при необходимости.
var sum = 0;
for (var i=0; i<arr.Length; i++)
{
sum += arr[i];
}

никаких проверок на выход за пределы массива.
Приятно читать такие комментарии, сразу видно — в вопросе Вы разбираетесь.
В данном примере лучше использовать цикл foreach, но, думаю, Вы знаете это не хуже меня.
Действительно, компилятор C# «умный», и проверяет границы массивов только при необходимости.
Вот пример кода, где проверка границ массивов будет проведена только один раз (предполагается, что длинна массива больше 5):
var sum = 0;
int maxi = 5;
for (var i=0; i<maxi; i++)
{
sum += arr[i];
}
Тут проверка границ будет проводиться непосредственно перед входом в цикл по формуле
if(maxi<arr.Length)

Все это не вошло в статью с целью хоть как-то сократить ее объем, так как на общую мысль проверки границ массивов не влияет.
Это я к тому, что проверка на выход за границы не так сильно замедляет программу, как кажется на первый взгляд. В большинстве случаев они будут там, где она все равно нужна и была бы в хорошо написанной программе на C
Знаете, Вы правы, но не во всех случаях. В первую очередь это касается произвольного доступа в массивах C#. Например, взять тот же алгоритм быстрой сортировки: в нормальной реализации на C будет проверка только для входных данных, в C# — при каждом обращении к массиву.
Я не специалист по C#, но отказаться от проверки выхода за границы массива можно даже в Haskell.
В C# можно делать вставки unsafe кода, для которых проверки выхода за границы массива будут отключены. Впрочем, это одновременно отключает практически все другие проверки компилятора, сборку мусора, и т.п., так что код становится похожим на C++. Собственно, поэтому небезопасный код писать на C# не рекомендовано, и подобная информация не вошла в статью.
Ну, не рекомендовано не означает нельзя. Оба языка, в общем-то, уже отошли от принципа «не платить за то, что не используется» — так какая разница, кто отошёл дальше?

Надо выполнить оптимизацию — выполним.
Тут, конечно, Вы правы, я не спорю. Просто C# по умолчанию делает проверки, а C++ — нет. Собственно, именно об этом я в статье и писал.
На C# нормальная реализация алгоритма быстрой сортировки — стандартная библиотека. Там никакой проверки внутри при каждом обращении нет
Хорошо, а что Вы будете делать, когда потребуется реализовать алгоритм, отсутствующий в стандартной библиотеке, но требующий произвольного доступа к элементам массива?
Например, при реализации:
1) алгоритма сортировки слиянием (допустим, потому что этот тип сортировки устойчивый, а реализация быстрой сортировки в C# — неустойчивая)
2) алгоритма поразрядной сортировки (потому что в ряде случаев она работает быстрее быстрой сортировки)
3) алгоритма внешней сортировки, например по алгоритму четно-нечетной сортировки слиянием Бэтчера (потому что все данные просто не помещаются в оперативную память)
4) алгоритма вычисления произведения матриц
5) алгоритма расчета обратной матрицы
и т.д.
Ваши действия?
Я выкину свои сертификаты в корзину, покаюсь и перейду на D.

Действия такие же, как и всегда:
1. Проверить наличие хорошо реализованного в системной/внешней библиотеке алгоритма. (например стабильного Enumerable.OrderBy)
2. Реализация алгоритма наиболее простым-прямым способом.
3. При необходимости — профилирование, отладка, оптимизация.

Если узким местом окажутся проверки границ массива — то в ход пойдет тяжелая артиллерия, unsafe вставки и прочая фигня.

Только практика показывает, что это все нужно в 1% случаев.
Сортировка слиянием в C# работает быстрее сортировки Array.Sort. Правда, для этого ее надо написать в unsafe mode на указателях.
Введение есть, и довольно большое, перечисление особенностей вместо заключения есть, а самой статьи нет :)
Контрактное программирование, способное сильно упростить отладку программ и помочь компилятору лучше оптимизировать код. То, что таких возможностей нет в стандартах C++ и C#, меня огорчает.

CodeContracts msdn.microsoft.com/en-us/devlabs/dd491992
Речь шла о стандартной поставке компиляторов C# и C++.
Справедливости ради нужно добавить, что для C++ тоже есть библиотеки, добавляющие поддержку контрактного программирования.
В 4й фреймворк они уже включены и стороннего ничего ставить не надо. Делается это не через компилятор, а уже после компиляции «дохачивается» IL-код. Правда, из-за этого оно работает не быстро, но все таки это вполне стандартная поставка
«Знаменитый Червь Морриса, парализовавший интернет в 1988 году»

Прямо как в Терминаторе — Моррис заслал свой червь в прошлое, за 2 года до появления интернета, чтобы заранее парализовать его работу?
Интернету в прошлом году исполнилось сорок лет. Отправить в 1-й класс учится заново отнимать в столбик.
Интересно было почитать, спасибо автору.
Зацепил вопрос про сборщик мусора. Шутка, конечно удобная, но то, что из-за него теряется производительность ИМХО — факт. GC — работает — значит занимает ресурсы. Тесты, которые вы предлагаете провести — как их проводить? В языке D можно включить/выключить сборщик? А если сравнить по скорости C++ без сборщика и D со сборщиком — получится глупо.

Вот, пример из жизни про GC:
Как-то давно писал я мелкие игрушки на C++, Delphi. При грамотно написанном коде — никаких лагов и задержек. все «мегагладко».
Во всеми ивестном Flash Actionscript 3.0 есть GC. Но даже, если вы напишите на нем что-то ооочень простое, типа несколько шариков летают и умирают — вы заметите небольшие рывки раз в секунду. При большом количестве объектов они не заметны ибо и так все мельтешит, поэтому в играх их не видно.
Та же история касается и JS с его GC, вот пример
jsfiddle.net/paul/XQpzU/
если присмотреться — шарик дергается раз в секунду или две, хотя код — проще некуда.

так что GC — не есть добро по умолчанию.
забыл добавить, что когда копался из-за чего эти рывки в JS и AS — знающие люди рассказали мне, что это GC :-)
К сожалению, я настолько привык к лагающим программам, что эти мини-рывки до сегодняшнего дня не замечал.
Конечно, они еле заметны, но тем не менее из-за GC сделать гладкую анимацию, как в C++ в JS и AS — невозможно. Интересно, как обстоят дела в D?
Может, автор статьи напишет что-то простенькое в стиле jsfiddle.net/paul/XQpzU/ для проверки?
Они не еле заметны, они ужасно заметны, но уже успели прочно войти в нашу жизнь.
Надеюсь, вы не отвернетесь от флэша или хтмл5 :-) Когда я показал эти лаги знакомому флэшеру, тот сказал: «ну что делать?.. забей! они не таки уж и сильные :-)»
Я боюсь, придется отвернуться от компьютера.
Мне уже снятся сны, лагающие на красивых эффектах.
Если они будут еще и подергиваться…
Есть такая штука — пул объектов. Поможет в борьбе рпотив GC.
не знаю, как в D, но в C# сборщик мусора в пользовательских приложениях конкуретный, т.е. ему не нужно усыплять все остальные потоки.
Включить/выключить — да, можно. Можно писать вообще без использования сборщика мусора — но тогда потребуется своя стандартная библиотека. По скорости — как раз за счёт сборки мусора (и иммутабельности) в D получилась очень эффективная работа со строками — к примеру, подстрока отдается как ссылка, без копирования и подсчета ссылок.
Это к GC отношения не имеет. Такие строки на C#, на Java, и можно написать такой класс для C++, где нет GC.
проблема всех VM для JS в том, что на данный момент их GC являются stop the world сборщиками. в таких платформах как .NET GC — Generational.
в этом плане у C# проблем нет. более того с .NET 4 дела обстоят еще лучше.
У меня никаких претензий к минусующим, и даже ответные минусы ставить не буду, если они откроются :-). Мне действительно интересно, в чем же ляп, или ошибка, или почему не стоило писать этот комментарий/вопрос?
Это отлично, что в D сборщик сделан по другому принципу, нежели, чем в JS или AS. Я, например, этого не знал, возможно кто-то другой — тоже не знает. А возможно, для кого-то эти лаги окажутся открытием.
Ошибка как минимум в выводах, основанных на незнании. Примитивный mark and sweep GC — это одно, современный GC с регионами и поколениями — совсем другое. Есть и RT Java в конце концов.
Вроде выводов особо не сделал. Я же не утверждаю, что GC — доктор зло. Просто сказал, что наличие сборщика мусора в языке само по себе ни о чем не говорит. В подтверждение привел пример, когда GC реально «тормозит процесс». И, как выяснилось, я был прав, а вот наличие «современного GC с регионами и поколениями» — уже может о чем-то сказать. И это дописали в комментариях, за это спасибо вам и остальным понимающим людям :-)
В D можно сборщик мусора отключить.
В немалой степени лаговость GUI андроида обьясняют именно наличием сборщика.
Я склонен этому верить.
Так что тут палка о двух концах.
Вы знаете, C++ и Delphi — языки компилируемые, а Flash Actionscript 3.0 — интерпретируемый. Так что, с моей точки зрения, сравнивать производительность C++ и Actionscript просто некорректно.
Согласен с вами, однако, именно GC в AS и JS, как выяснилось приводит к тому, что гладкой анимации не добиться. К счастью в D он устроен иначе и не тормозит процесс. Жаль, что в подтверждение не приводят не «лагающих» примеров =)
Про отсутствие деструкторов в C# вы зря так категорично написали
В большинстве ситуаций интерфейс IDisposable и конструкция using — неплохая альтернатива

По крайней мере, у нас за два года работы не было ни одной ошибки, связанной с забытым using
Кстати есть еще и деструкторы. Но не рекомендуется полагаться на них, т.к. они вызываются недетерминированно. Но как «последний рубеж» освобождения unmanaged ресурса в случае краха (или забытого using) самое то.
Это не деструкторы (в C++ смысле). В C# именно деструкторов нет. То, что Вы показали — именно завершители, вы же сами пишете, что они вызываются недетерминированно. Просто синтаксис объявления завершителей в C#и деструкторов в C++ фактически одинаковый (~ИмяКласса), отсюда и путаница.
Как уже было сказано, это не деструкторы.
Аналогом плюсового деструктора является именно метод Dispose интерфейса IDisposable.

Конструкция using является аналогом создания объекта на стеке.
Согласен, между методом Dispose и деструктором C++ можно провести параллель. Тем не менее, согласитесь, в C# нужно или явно вызывать метод Dispose, или явно использовать конструкцию using, а C++ вызывает деструкторы автоматически.
Хотя я не спорю — при вызове метода Dispose в нужных местах проблем с освобождением ресурсов не будет.
Статья, ради которой приятно зайти на хабр. Плюсов вряд ли наберет много, тк тема порно и копирастов не раскрыта, но мое «спасибо» автор честно заслужил.
> Судите сами: стандарт только на C занимает около 500 станиц, C++ – около 800, C++11 – около 1300. Если сравнить объем технической документации – этот язык по сложности явно превосходит миксер, швейную машинку и автомобиль, приближаясь скорее к самолётам. Для сравнения, стандарт C# 4.0 занимает всего 505 страниц.

Давайте сделаем честное сравнение. Приложите к спецификации на C# спецификацию на его библиотеки.

И получите следующую картинку (Going Native 2012, keynote day 2): www.habrastorage.com/images/zzz.png
Ну знаете, библиотеки — несомненно важная вещь, но они не язык. Разговори идет о сложности языка, а не библиотек. Хотя я тоже против того, чтобы числом страниц мерить сложность. Я читал книгу Страуструпа про С++, ту, которая основная, без продвинутых штук, и читал книгу Алуксандреску про D. Так вот, во-первых мое личное впечатление таково, что первая существенно сложнее, несмотря даже на то, что вторая на английском.
Более того, от книги страуструпа у меня остался такой осадок, что примерно 40-50% информации — описание и способы избежания возможных ошибок.
В кнге про D это примерно 4% — навскидку припоминается только: «Не используйте сишные указатели, это небезопасно». Так что касательно сложности языка автор абсолютно прав. Способов выстрелить себе в ногу при использовании SafeD почти что и нет, а если использовать низкоуровневые штуки — так они просто копируют функциональность си.
> Ну знаете, библиотеки — несомненно важная вещь, но они не язык.

Я говорил о другом. Из упомянутых 1300 страниц C++11 больше половины — STL. Сравнивать со спецификацией на C# по объёму нужно ту часть стандарта, которая описывает язык — а их там остаётся как раз около 500.

> Более того, от книги страуструпа у меня остался такой осадок, что примерно 40-50% информации — описание и способы избежания возможных ошибок.

А у D есть спецификация, при составлении которой дотошно рассмотрена каждая возможная комбинация фич языка? Продуманы undefined behaviors? Есть наработки по статическому анализу? Если нет — то мы просто не знаем, какие паттерны в D являются склонными к ошибкам, поэтому и в книгах об этом не пишут.
по D еще мало статистики касательно склонности к ошибкам, но в обшем выстрелить себе в ногу в нем обычно можно, но для этого надо что-нибудь явно сделать. К примеру, хотите экземпляр класса положить на стек — можно, но нужно будет использовать специальный хелпер из библиотеки, который легко ищется/рефакторится.
А как коррелируют характеристики языка и объем документации? Если чем меньше документация тем лучше язык то давайте кодить на brainfuck или машине тьюринга. Там документация на страницу влезет размашистым почерком.

Сложность языка не определяется объемом документации по-моему. Ну хотя как, если документации вообще нет, то язык не простой получился. А если она есть и исчерпывающая, то чем её больше, чем больше там примеров и best pracrice тем лучше, разве нет?
Критика по поводу объема документации принимается.
Тем не менее, писал в первую очередь о том, что C++ сам по себе сложен.
в нём есть встроенная поддержка проверки границ массивов для отладочной версии программы, которая отключается при компилировании оптимизированной версии

Что толку от проверки, которая включена только в отладочном режиме? Ошибки в безопасности, как правило, при нормальной работе не проявляются, нужно скормить программе специально подобранные данные. Злобные хакеры-то будут смотреть на конечный продукт, в котором компилятор заботливо отключил проверки.
он полностью совместим с кодом C/C++ на уровне объектных файлов, что позволяет получить прямой доступ к функциям и классам, написанным на C/C++ и наоборот

Даже сам C++ несовместим с кодом C++ на уровне объектных файлов. Нестандартизированного манглинга имён уже достаточно, чтобы объектные файлы от разных компиляторов были несовместимы, а уж когда появляются исключения — а они всегда появляются, мало кто использует new(nothrow) — то на переносимости можно смело ставить крест.
Автор очень много оставил за скобками. Разумеется, совместимость не полная — она достаточна для того, чтобы без особой мороки связать код на плюсах и D. Ну а если совсем припрёт — придётся имена с явным манглингом писать как extern «C» — так тоже можно. Впрочем, в никсах царит GCC и вроде как совместимый с ним LLVM.
Автор статьи некорректно выразился: проверку границ можно отключить при помощи ключа -noboundscheck, а так она есть и в оптимизированной версии.

Что до совместимости с C++, это только с компилятором от Digital Mars, увы. Впрочем, хоть так можно — и то хорошо: C++ в плане интеграции с другими языками особняком стоит.
Если точнее, компилятор Digital Mars D нужно использовать вместе с Digital Mars C для Windows и с GCC для остальных платформ.
Всем хорош язык D, особенно возможностью линковаться с сишным кодом в обе стороны (по крайней мере, при использовании компилятора от Digital Mars). Особенно, если закрыть глаза на то, что у языка есть две разных стандартных библиотеки.

Жалко, что нет крупных компаний, которые делают ставку на этот инструмент. Вот у языка Go этой проблемы нет.
У Вас немного устаревшие данные. Две стандартных библиотеки (Phobos и Tango) были в D1. В D2 осталась только одна (Phobos), Tango все еще не портирована под D2.
Самое главное — в D нет .h файлов :)
Да, Вы правы, нет.
Всю информацию компилятор получает сам из исходного кода. Если необходимо выпустить библиотеку без исходных кодов, то компилятор сам может создать D Interface Files, которые фактически будут играть роль .h файлов.
Статья интересная, спасибо. Только маленькая поправочка — SQL с рекурсивными подзапросами полный по тъюрингу (SQL1999).
Спасибо за уточнение.
D — очень хороший, продуманный и синтаксически сладкий язык. Меня например, привлекает то, что он компилируемый (несмотря на рост процессоров и железа, интерпретаторы по-прежнему адски медленные, особенно когда построишь большое дерево классов и объектов), но при этом на нем удобно писать.

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

И совместимость с Си-библиотеками — тоже отличная особенность.

Язык очень хорош. Увы, почему-то он не популярен. Видимо, потому, что за ним не стоит ни маркетинга от крупных корпораций, ни компаний вроже 37 signals, ни армии «чайников», ни элитного флера зазнаек-хаскеллистов, ни производителя телефонов, ни линуксоидов.
Вот пока язык не найдет себе кого-то кто будет за ним стоять, никто на нем писать не будет. Автор столько распинался на то что в 2016 году майкрософт выкинет виндоус и тысячи c# программистов на мороз, поэтому на нем опасно писать, но совершенно не ясно что будет если автору D — профессиональному разработчику компиляторов надоест его разрабатывать. Ну или начнет делать E.
интерпретаторы по-прежнему адски медленные, особенно когда построишь большое дерево классов и объектов
Большинство серьезных конкурентов D — языки с JIT.
Вы можете мне объяснить, почему Tango D так зверски работает с XML'ем?

dotnot.org/blog/archives/2008/03/10/xml-benchmarks-parsequerymutateserialize/
dotnot.org/blog/archives/2008/03/12/why-is-dtango-so-fast-at-parsing-xml/

Что-то объяснения про оптимизированную работу строк не сильно впечатляют.
Tango — библиотека для D1. Выше упомянутая работа со строками относится к D2 — именно там строки сделаны неизменяемыми.
По оси X на указанном Вами графике — среднее число циклов в секунду.
>> After the run, I take the average cycle time, and turn that into the followin graph showing cycles per second.

Другими словами, Tango примерно в 78 раз быстрее Java6 DOM.

>> Вы можете мне объяснить, почему Tango D так зверски работает с XML'ем?
Может быть Вы подумали, что по оси X — время?
Как обстоят дела с GUI библиотеками?
Есть:
GtkD — порт GTK+
DWT — порт SWT
QtD — порт Qt
Полный список смотрите здесь.
Странно, я где-то читал, что
а. У D проблемы с цеплянием C++ библиотек. Или это относится только к либам, а с объектниками всё нормально?

б. Сборщик мусора в последних версиях чуть ли не обязателен, а delete считается deprecated. Не так?
В D1 правда нельзя подключать C++ библиотеки, только C. В D2 также добавили поддержку подключения C++ библиотек.

Выше в комментариях уже писали, что в D можно отключить сборщик мусора.
a.
«проблем», как таковых, нет, просто, в отличии от поддержки C ABI, поддержка C++ ABI не полная. Поэтому, насколько мне известно, в release-версиях стараются использовать extern «C» прослойку, просто для надёжности. Подробнее здесь: www.d-programming-language.org/cpp_interface.html

б.
delete как ключевое слово языка, действительно, deprecated. Причины можно найти на офф. форуме, сейчас, увы, нет времени искать — довольно давно было. Помню жаркую дискуссию. Что, впрочем, ничуть не мешает иметь функциональность delete, если есть такая необходимость ( а она есть редко ).

Сборщик мусора никогда не был и не будет обязательным. Просто нужно отдавать себе отчёт, в том, что при его полном отключении изрядная часть стандартной библиотеки будет недоступна ( вся память будет утекать ), как и некоторые особо «сладкие» нативные фишки. Язык в таком состоянии больше напоминает better C, нежели better C++.

Обсуждения насчёт того, что было бы неплохо иметь стандартную библиотеку в режиме reference counting, если сборщик мусора отключен, ведутся постоянно и, в целом, особо никто не возражает. Но соотношение практической ценности этой фичи относительно трудозатрат делают её далеко не приоритетным направлением.
***Сборщик мусора никогда не был и не будет обязательным. Просто нужно отдавать себе отчёт, в том, что при его полном отключении изрядная часть стандартной библиотеки будет недоступна ( вся память будет утекать ), как и некоторые особо «сладкие» нативные фишки. Язык в таком состоянии больше напоминает better C, нежели better C++.***

Жалко, «продолжаем писать на С++». Есть много мест где возможность самостоятельного управления памятью критична по соображениям производительности.
Возможно, я недостаточно точно выразился.
Ручное управление памятью и gc — не противоречащие друг-другу понятия. Даже при включенном gc всегда доступны malloc, free и аллокация на стеке + можно пометить любые блоки памяти как недоступные gc для обхода. Или приостановить gc на какой-то момент для выполнения real-time блока. Это ничем не грозит.

Речь же в предыдущем комментарии шла о ситуации, когда gc отсутствует в принципе, не включен druntime на этапе компиляции. Это важно, в основном, только если вы хотите уместить программу на D на какую-нибудь очень embedded платформу, куда garbage collector просто не влезает.
> В результате это привело к трагедии для тысяч программистов, работающих на Basic’ке. К тому же, по сообщениям в прессе, в 2015-2016 году Microsoft планирует отказаться от бренда «Windows», создав новую ОС для планшетов, смартфонов, компьютеров, консолей, телевизоров и других устройств, а, значит, языки для разработки под эту ОС тоже могут кануть в небытие.

Про mono я полностью согласен, но вот про windows… Я не пойму, вы вот представляете это как? Что вот придет 2016 год, выйдет глава майкрософт, скажет: «все, нет больше виндовс, и мы выкидываем ее, еще заодно и c#, вместо них теперь Doors и Ab (а бемоль)»

Мы все: «А-а-а-а-а-а, как дальше жить?», а вы так гордо «хаха, а я вот сижу на D, и мне ничего не страшно».

Вам не кажется, что в условиях такого резкого перехода D тоже не выживет? Скорее уж выживет CLR, которую просто портируют на новую Doors. Не будет работать то что завязано на WinAPI, а все что работает в рамках CLR прекрасно заведется и на новой Microsoft Doors с портированной на нее CLR.

Мне лично такой вариант развития событий представляется более вероятным.

Еще:
>Последнее означает, что прекрасный компонент ASP.NET, служащий для построения сайтов различных масштабов, не имеет ровным счетом никаких преимуществ перед тем же PHP.
Как же это то что .NET завязан на windows, позвольте спросить, означает что он не имеет никаких преимуществ перед php? При всем моем уважении к php .NET даст ему гору очков вперед почти по всем критериям оценки. Начиная с того что c# типизированный, компилируемый и имеет в составе гору встроенных примитивов, в отличии от скудной объектной модели php и заканчивая тем что средства разработки и тестирования под .NET стоят на три лестничных пролета выше чем под php.

> Ну а если вдруг вам все же захочется использовать его в своих проектах, будьте морально готовы к покупке лицензий на серверную версию Windows.
Я не понимаю, ну и что? Первая ссылка из гугла показывает что Windows Web Server 2008 стоит 10 765 рублей. Это зарплата одного программиста максимум за неделю. А еще её можно «взять в аренду» в месте с хостингом: арендуя VPS на Windows вы автоматически «арендуете» совершенно лицензионную копию windows. Это стоит от 700р в месяц. Вот то что вижуал студия стоит 25к за рабочее место еще можно было бы рассмотреть, но есть скидки и спец предложения для малого бизнеса. Да и не так это много в масштабах организации. Снять в Москве офис на 2-3 месяца будет стоить столько же сколько купить лицензионного софта на всю команду.
я мог бы еще кое с чем поспорить, но тогда будет слишком уж длинно
Если есть критика по существу — всегда готов выслушать. Именно в результате подобных дискуссий рождается взаимное понимание.
топику тем не менее поставил плюс. написано хорошо, хоть я и не согласен со многим
>> Скорее уж выживет CLR, которую просто портируют на новую Doors.
Вы знаете, .NET почти полностью написана с использованием WinAPI. Просто в документации все методы, реализованные именно с помощью .NET, отмечены специальным значком, и таких методов сравнительно мало. Так что фактически придется переписывать большую часть кода платформы .NET, чтобы ее портировать под другую ОС.

>> Как же это то что .NET завязан на windows, позвольте спросить, означает что он не имеет никаких преимуществ перед php?
Я имел ввиду, что на Unix-платформах нельзя использовать ASP.NET, а раз его нельзя использовать, то он не даёт никаких преимуществ. Если сравнивать именно языки, то я с Вашей позицией согласен — платформа ASP.NET действительно лучше PHP. Извините, что не выразил свою мысль достаточно внятно.

>> Первая ссылка из гугла показывает что Windows Web Server 2008 стоит 10 765 рублей.
Собственно, я и имел в виду, что при использовании ASP.NET скорее всего придется покупать лицензионную Windows. А нужно ли это делать — каждый решает для себя сам. У разных ОС свои плюсы и свои минусы, с вашего разрешения, давайте отложим эту дискуссию на другой раз — всё же это не является непосредственной темой статьи.
> Вы знаете, .NET почти полностью написана с использованием WinAPI. Просто в документации все методы, реализованные именно с помощью .NET, отмечены специальным значком, и таких методов сравнительно мало. Так что фактически придется переписывать большую часть кода платформы .NET, чтобы ее портировать под другую ОС.
Ну так оно и предполагалось в общем-то. CLR своего рода прослойка между .NET приложением и конкретной ОС. Отсюда и необходимость JIT компиляции из MSIL. Вполне логично что в windows CLR использует WinApi. А в Unix Mono использует наверное какие-нибудь вызовы ядра. И что в этом плохого? .NET приложению не надо об этом думать. CLR сама как-нибудь разберется, ну не сама, а конечно благодаря труду программистов портировавших её на целевую платформу, но программисту .NET приложения это безразлично. С его точки зрения все «само».

Про заначек. Ни разу не видел, как он выглядит? Скиньте ссылку на MSDN где он есть. Не в порядке спора или требования пруфлинка, просто заинтересовали меня, я с удовольствием почитаю про этот значок и отличие методов помеченных им и не помеченных.
Тоже заинтересовал этот значок, где его можно посмотреть в MSDN?
Знаете, видел этот значок в документации к Microsoft Visual Studio 2005 (не Express версия, а обычная). Пользовался именно встроенной в среду справкой, а не ее онлайн версией, для .NET 2.0.
Мне кажется, что в то время онлайн версии документации вообще не было, но за последнее утверждение не ручаюсь. Собственно, именно в MS VS 2005 я этот значок и видел. Встречался он почти в каждом классе, примерно у одной-двух функций. Выглядел примерно как оранжевая иконка .NET, всплывающая подсказка гласила примерно следующее: «This method provided by .NET» (за точность фразы ручаться не могу, пишу по памяти), что наводило на простую мысль — остальные методы предоставляются кем-то еще. В литературе встречались утверждения, что .NET почти полностью реализован на основе WinAPI, поэтому в отношении «не помеченных» функций сделал соответствующий вывод.
Дальнейшая судьба значка мне неизвестна, возможно, Microsoft отказалась от распространения подобной информации.
Вы знаете, .NET почти полностью написана с использованием WinAPI
А стандартная библиотека С/С++/D/whatever для Windows что, с использованием святого духа написана? Все равно, если мы на платформе Windows открываем файл, мы всегда вызываем CreateFile, а он всегда вызывает NtCreateFile.
Если Microsoft откажется от WinAPI, то стандартную библиотеку для С/С++/D/whatever все равно переписать придется.
«Константность и неизменяемость переменных» — это весело!
Веселее (и безопаснее) может быть только язык вообще без переменных.

Если не лень — нельзяли вот об этой особенности поподробнее?
Какие мега-удобства это привносит (ну, кроме очевидных проблем с многопоточностью)
Вы знаете, как правило в библиотеке D для всех ленивых функций реализован их обычный вариант. Так что Вы сами выбираете, что именно Вам нужно — получить результат сейчас, или отложить вычисления «до востребования».
Что касается преимуществ ленивых вычислений, то, если навскидку, возможность оперировать с бесконечно длинными последовательностями.
По поводу многопоточных вычислений — Вы неправы (по крайней мере в отношении D). В языке память по умолчанию локальна для потока, чтобы передать данные в другой поток переменную нужно явно объявить разделяемой, что позволяет компилятору проводить ряд проверок.
По поводу «константности и неизменяемости переменных» — речь шла о такой возможности (которая, к слову, облегчает написание многопоточных программ). Будете Вы ее применять или нет — зависит от Вас.
Почти весь ряд особенностей есть и в Haskell, и многое другое. Почему же нет раздела «немного о недостатках Haskell»?
Возможно, потому что не было достаточно много опыта программирования на Haskell’е.
Тогда рекомендовал бы приобрести
Если выбор и не поменяете, то время проведёте весело :)
Если некий С-подобный язык и Haskell обладают сравнимым набором особенностей в заданном контексте, какой же окажется естественным выбором для программиста с опытом С/С++?
Я не говорил «сравнимым». Ряд особенностей Haskell куда больше, поэтому не изучить и игнорировать его было бы глупо. А уж выберет ли его потом программист с опытом на C/C++, дело программиста. Я лично выбрал, и далеко не только я (почти все Haskell'исты с C/C++ background'ом).
«в заданном контексте»
Ряд особенностей D2 тоже куда больше. Я бегло пробовал и D2, и Haskell, увидел, что D2 покрывает все возможности, что мне интересны в Haskell и не нашел причин изучать его дальше. Более того, Haskell ведь, как я понимаю, всё ещё придерживается строго функционального подхода? Если да, это большой аргумент против.
В заданном лично вам контексте — может быть. Но речь не только о вас.
А строгая функциональность — это большой аргумент «за». Но понять это можно только попрограммировав на Haskell.
Заданном автором в статье.
Строгая функциональность — отрада для математика и бессмысленное ограничение для программиста. Особенно для С/С++ программиста. По крайней мере, пока не появятся компьютеры строго функциональные на уровне машинного кода ;) Я вполне понимаю преимущества, которые дают гарантии функционального подхода, особенно для многопоточности. В D2 это есть.
В общем же случае предпочитаю не создавать дополнительных абстракций там, где они не требуются.
Строгая функциональность — отрада для математика и бессмысленное ограничение для программиста.

Вы много писали на Haskell?

Особенно для С/С++ программиста.

Странно говорить это C++ программисту, вы не находите?
А как насчёт аргументации по существу?
Назовите преимущества строгой функциональности, из-за которой я мотивирован себя ограничивать в способе выражения мыслей.
Ну например строгая статическая типизация, по-вашему, это лишняя сущность и бессмысленное ограничение для программиста?

По типу функции Haskell можно видеть не только типы аргументов и результата, но и некоторые важные аспекты функции, наличие состояния, использование ввода-вывода и т.п. Языки с зависимыми типами идут и того дальше, позволяя зафиксировать в типе функции например факт того, что она именно сортирует список, а не делает что-либо ещё.
Причём на существующую систему типов ложатся и исключения, и ввод-вывод, и множественные результаты, и то многое другое, ради чего в других языках городятся специальные конструкции.
Но при этом лишние сущности почему-то именно в Haskell.
1) Строгая типизация не ограничивает возможностей, она лишь заставляет описывать преобразования типов явно. Размен небольшого синтаксического сахара на предсказуемость поведения.
2) Статическая типизация ограничивает, предлагая взамен большую производительность и, в сочетании со строгой, возможность задавать некие контракты.

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

Всё ещё не вижу связи между обязательной строгой функциональностью и списком фич. В D2 тоже по типу функции можно определить некоторые аспекты, такие как pure, nothrow или safe. Обошлись как-то без ограничений.

Хочу заметить, что я нигде не упоминал «лишние сущности», только «бессмысленные ограничения». Это не имеет отношения к теме.
никак неявных преобразований целых чисел

Ну если это для вас действительно лишняя сущность, то значит у нас слишком разные взгляды. От неявных преобразований тоже немало ошибок возникает, а ничего плохого в явном касте (очевидном, в первую очередь, для читающего код) я не вижу. А вот в неявном — вижу. Где там floor произойдет? Для этого при чтении в уме надо типы держать, а не просто читать явное floor b + c.

В D2 тоже по типу функции можно определить некоторые аспекты, такие как pure, nothrow или safe. Обошлись как-то без ограничений.

А асинхронный код как синхронный (плоско) там можно писать?
А ФВП позволяет указать, что принимаемая ей функция pure и nothrow (и соот-но проверит ли это компилятор)?

Нет никаких ограничений, вы вполне вольны написать
foo :: MVar Int -> MVar Int -> IO (MVar Int)
Тут и мутабельность, и ввод-вывод.
Если пугает синтаксис, ну так можно ж упросить, это непринципиально.

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

Ограничения на практике оказываются полезными.
То, что мутабельный стейт-фул код писать немного напряжнее — это ж хорошо! Задаёт верные приоритеты. Никто не мешает его писать, но:
1. Это явно отражено в типе функции и читатель сразу видит контракты
2. Провоцирует писать более чистый код с декомпозицией (что упрощает, например, тестирование, так как набор чистых функций тестировать — сказка)
3. «Грязный» код пишется лишь тогда, когда действительно нужен, а не везде, где ни попадя.
Отвечая на ваше сообщение, наткнулся на любопытное поведение компилятора dmd, которое явно стоит внимания. Пардон, нужно некоторое время, чтобы ответить точно.
А ФВП позволяет указать, что принимаемая ей функция pure и nothrow (и соот-но проверит ли это компилятор)?
Да.
void hof( int function() nothrow pure f ) { }


А асинхронный код как синхронный (плоско) там можно писать?
Этот вопрос не понял, мне незнаком термин «плоское написание асинхронного кода».

Касательно неявных преобразований, как минимум, привычной идиомы if(ptr) мне бы не хватало. Есть некоторое количество преобразований, которые на практике достаточно безопасны и удобны в неявном виде. Я это к тому, что цель языка программирования — быть удобным и практичным, а не предоставить строгую красивую модель.

Как насчёт вставки в ваш мутабельный пример inline assembler'a? Если уж он действительно такой императивно-мутабельный, а не просто имитирует стиль, взгромождая ещё одну абстракцию?

Вы исходите из предпосылки, что императивный код «грязнее» и хуже только потому, что он императивный. Кстати, императивный стиль не обязательно подразумевает мутабельность, что вполне показано в D2. До тех пор, пока эта предпосылка существует, нам очень трудно будет найти общий язык.
Этот вопрос не понял, мне незнаком термин «плоское написание асинхронного кода».

Например как тут.
Т.е. вместо явной передачи callback мы пишем, к примеру
x <- download "foo";
lift $ print "foo is downloading"
y <- download "bar";
lift $ print "bar is downloading"
x' <- await x
y' <- await y
return (x' + y')

Это как пример, нафантазировать можно то, что удобнее.

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

Основной момент в «мне бы не хватало». Поверьте, мне очень многого не хватало из C++ поначалу, но потом оказалось, что это от лукавого :)
Строгая красивая модель делает язык удобным для чтения, ибо мало частных случаев и каких-то ситуаций, где только знание каких-то нюансов стандарта помогает понять, что происходит. Всё декларируется достаточно явно.

Как насчёт вставки в ваш мутабельный пример inline assembler'a?

Ну ассемблер напрямую не вставить, ибо Haskell куда выше уровнем, да и компилироваться может через LLVM. Но звать сишные функции никто не запрещает.

Кстати, никто не мешает и в чистой функции пользоваться state'ом через ST монаду, она позволяет использовать переменные только внутри, поэтому результат гарантированно чистый (причём опять же, никаких хаков). Это похоже на ограничения pure в D.

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

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

import std.stdio;
import std.file;
import std.parallelism;

// Синтаксический сахар, которого не нашёл в стандартной либе.
// Возможно стоить сделать pull request для phobos :)
auto launch(T)( T new_task )
{
        struct Launched
        {   
        private:
                T task;
        public:
                this(T new_task)
                {   
                        task = new_task;
                        task.executeInNewThread();
                }   

                auto result()
                {   
                        return task.yieldForce();
                }   
        }   

        return Launched(new_task);
}

void main()
{
        auto task1 = launch( task!readText("test1.txt") );
        auto task2 = launch( task!readText("test2.txt") );
        write( task1.result ~ task2.result );
}


Это сравнимый аналог вашего примера? Callback, конечно, неявно где-то все равно передается, но, подозреваю, в недрах имплементации Haskell тоже без них не обошлось.

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

… мало частных случаев и каких-то ситуаций, где только знание каких-то нюансов стандарта помогает понять, что происходит

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

И хороший практичный язык, ИМХО, должен иметь множество частных случаев и нюансов стандарта. И сам стандарт на тысячи страниц. С тем лишь отличием от С++, что незнание этих нюансов не должно бить новичка по лицу, пока он с ними не знаком.

Ну ассемблер напрямую не вставить, ибо Haskell куда выше уровнем, да и компилироваться может через LLVM. Но звать сишные функции никто не запрещает
Я это к тому, что у Haskell и у D несколько разные дизайн-цели. И в D необходимым требованием является то, что встроенный ассемблер должен выглядеть так же естественно, как и функциональный стиль. Равноправное использование всех парадигм.
Что такое task!readText?

Я привёл несколько неудачный пример. Вот пример поудачнее:

do
  send int 1
  x <- receive int
  send string ("hello" ++ show x)
  y <- receive string
  return (show x ++ y)


send — отправляет сообщение клиенту
receive — получает сообщение

Однако receive не блокирует, так как на деле он не ждёт сообщения, а регистрирует callback. Т.е. всё, что ниже receive — автоматом callback.

Другой пример:
do
  line <- lines contentOfFile
  word <- words line
  ch <- word
  if ch == 'x' return True else return False


Аналогичен:
foreach (line in lines(contentOfFile))
  foreach (word in words(line))
    foreach (ch in word)
      if (ch == 'x') { yield return true; } else { yield return false; }


Однако тут нет вложенных foreach, это делает монада.

Контракт может быть полезным, может не быть.

Однако если у нас нет возможности его наложить, сложно обсуждать его полезность.
В Agda можно статически гарантировать, что функция, принимающая число, вернёт список с длиной, равной этому числу.
В Haskell и C++ этого гарантировать нельзя, и в этом смысле Agda более мощный язык.
Тот факт, что в язык вводят nothrow и pure, говорит о полезности таких контрактов.
А как в D дела с STM (Software Transactional Memory)? В Haskell это органично вписалось без каких-либо проблем на существующую систему типов. Как это сделать в D так же органично?

У Haskell выбраны другие умолчания: чистый язык и навешиваемые расширения (STM, IO, State, Cont, list-monad...). На мой взгляд этот путь себя оправдывает.

А то чувство, когда горы кода после первой же удачной компиляции сразу работают как надо, незабываемо, и про него говорит почти каждый новоявленный Haskell'ист :)
Haskell, конечно, далёк от идеала. Например, там есть две функции:
map :: (a -> b) -> [a] -> [b]
mapM :: Monad m => (a -> m b) -> [a] -> m [b]

Хотя вообще говоря достаточно лишь одной реализации (первой), а во вторую она превращается автоматически переносом на стрелки Клейсли.
Т.е. map для списка может быть генерализован до:
map :: (Arrow a, ArrowChoice a) => a b c -> a [b] [c]

с одной единственной имплементацией, подходящей как для функций с эффектами, так и для чистых.

Т.е. любая лямбда-функция типа \f x -> f x + 2 * f x может иметь сразу обобщённый тип. Но в Haskell этого нет, и пока вроде нигде.
По поводу ограничений, в Haskell даже Data.Dynamic есть, какие ограничения? Хоть динамику используйте.
Правда практика показывает, что нужно это ну очень редко. Но если очень нужно — то есть.
Просто переходя с языков, где всё цветёт мутабельностью, по первости непривычно, да, но это не потому, что Haskell плохой, а потому, что инструмент надо сначала изучить, а не кидаться им сразу гвозди забивать, а потом удивляться, что в руке-то не молоток.
Number* c = a + b;

Не смог такое представить, такое скомпилится правильно в одном случае, если a указатель, а b число, иначе как минимум будет варнинг. А представить что оба указатели и надо сложить значения по их адресам я вообще не могу, да и вменяемый сяшник не сможет. Да и оперировать указателями в таком виде, чтобы реализовать свой оператор сложения именно для указателя, да это бред какой-то. Лечиться от этого надо.
Вы уж извините, решил не приводить код на пол-страницы. a и b должны быть умными указателями, для которых перегрузка операторов разрешена.
NickLion в комментариях написал возможную реализацию, можете посмотреть здесь.
Вот меня давно волнует следующий вопрос: если язык так хорош, почему он до сих пор не попал в мейнстрим, в особенности учитывая то, что он вроде как для мэйнстрима и планировался? Как бы с одной стороны понятно, что не помешала бы поддержка кого-нибудь крупного, но, с другой стороны — а почему ее до сих пор нет? И еще вот интересно: может кто из хабрасообщества участвовал в разработке реального проекта на D? Если так — реквестирую хотя бы краткую выжимку такого опыта!

P.S. Вот сейчас специально глянул и не нашел ни одной вакансии «разработчик D» в Москве — поправьте меня, если это не так
А как связан мэйнстрим и качество языка?
В общем случае никак, разумеется =) Я вот о чем: имеем язык N, язык этот не эзотерический и не предназначенный для решения узкого круга специфических задач. Авторами языка позиционируется как альтернатива плюсам. Многие, в.т.ч. автор статьи, утверждают, что он удобнее плюсов, и приводят ряд аргументов, часть из которых для меня звучит разумно. Отсюда у меня и возникает резонный вопрос: почему язык не популярен? Вопрос, кстати, ни разу не риторический, мне на самом деле это интересно =)
Язык умеренно популярен для личных проектов — на уровне всех остальных не-эзотерических-но-и-не-устоявшихся языков. Что касается индустрии, то там качество языка играет чуть ли не последнюю роль. Важна доступность кадров, надёжность toolchain, полнота библиотек, успешный практический опыт. При этом одна из целевых ниш языка — «замена С++» подразумевает большие, сложные, долгоиграющие проекты, а не что-то формата стартапов, где риск уместен.

И, лично моё мнение, сейчас сложилась патовая ситуация для языка, из-за того, что текущая команда разработчиков не может выдать количественно нужный темп улучшений, не говоря уж о поддержке для корпоративного пользователя. При этом автор языка, Walter Bright всё ещё не хочет отдавать reference toolchain в полный open-source ( полностью открыт только front-end, исходники back-end доступны но проприетарны ), что, несомненно, отпугивает некоторых больших игроков, которые могли бы поддержать проект. Остальным мешает синдром NIH.

Так же нет никакого централизованного пиара, распространение информации о языке, по большей части — community effort. Если бы не сочный язык статей Александреску и его репутация в сообществе С++, возможно, про D слышали бы ещё меньше :)

При этом те, кто может позволить себе выбирать язык для нового проекта и готов к некотором количеству работы с напильником — используют вполне успешно. Например, мне известно, что некий Adam D. Ruppe использует D2 для вполне коммерческой веб-разработки ( во всяком случае так он утверждал сам :) ), и в очень интересном стиле ( github.com/adamdruppe/misc-stuff-including-D-programming-language-web-stuff ). Если следить за сообщениям на офф. форуме, то такие маленькие «истории успеха» вполне проскакивает.

Но в мэйнстриме играют по другим правилам и я не знаю, в каком направлении надо двигаться D, чтобы преодолеть этот барьер.
Доступность кадров, надёжность toolchain, полнота библиотек, успешный практический опыт — это проблемы, которые возникают перед любым новым языком программирования. Причем, редко когда язык занимает абсолютно новую нишу, но удалось же в свое время PHP потеснить Perl, а потом ASP.NET и Ruby / RoR, в свою очередь, потеснить PHP.

Вот объяснение, предложенное вами во втором абзаце, на мой взгляд выглядит достаточно разумно и многое объясняет =)

В любом случае, спасибо за развернутый ответ =)
Кстати, глянул ваш профиль, увидел статьи про D. Почитал. Т.к. судя по-всему с языком вы знакомы достаточно плотно, я конкретизирую свой вопрос: можете рассказать о проектах, написанных на D?
Какого рода проекты вас больше интересуют?
Хм, конечно, наиболее интересен был бы любой опыт коммерческой разработки на D, ежели таковой имеется =) Если вы про тип приложения — мне лично интересно, как язык проявляет себя в разработке GUI-приложений практически любого рода.
Тогда, увы, не могу помочь. Я слежу, в основном, за развитием библиотек и всего, что касается серверных/сетевых технологий, в силу своего рода занятий. Касательно коммерческого — Adam'а я уже упоминал; несколько человек упоминали, что долгое время используют D для научных вычислений.

Сам я несколько раз использовал D для написания плагинов, которые в нормальных условиях предполагалось писать на С/С++, во вполне коммерческих проектах. Кодом поделиться не могу, ибо NDA. Могу победить лень и на основе оного написать статью, это максимум.

Что касается GUI — так оно в большей степени определяется GUI-библиотекой, нежели языком. Тот же GTK он и в D GTK.
От статьи веет пафосом, что еще больше раздражает при наличии фактических ошибок.

Так, например, поступила Microsoft при разработке платформы ASP.NET – скрипты для браузера могут быть написаны на любом языке платформы .NET (например, на C#) и затем автоматически преобразованы в соответствующий код на JavaScript

Ms так не поступала так, как такой функциональности в asp.net нет.

Первое, о чем следует помнить – разработчики Mono будут всегда на шаг позади Microsoft, так как они начинают реализовывать уже выпущенные библиотеки и стандарты.

Не стоит проводить равенство между mono и .net, они пересекающиеся технологии, но не равные. где-то mono задерживается от ms, где-то заметно впереди (managed компилятор от ms выпущен только в прошлом году, а от mono точно был в 2009), а где то вобще не имеет аналогов — monotouch и monodroid. Кстати, на D можно писать приложения под android и iphone, существуют биндинги к gui?

В настоящее время все патенты на C#/CLI принадлежат Microsoft..

Вообще то на c# стандарт есть (Ecma (ECMA-334) и ISO (ISO/IEC 23270:2006)) в отличии от, например, Java. А D стандартизован?

P.S. Я не понимаю, как можно доверять технической статье, которая содержит фактические ошибки, про которые автор пишет «Если честно, не помню, где именно про это читал» это не гуматитарщина, не знаешь — не пиши.
Насчёт android — как раз недавно появился к этому интерес, вот статья по тому, как можно собрать программу для Andoid, используя NDK + gdc. Но без полного портирования druntime и phobos это совсем не так круто, как хотелось бы, увы.
>К тому же, по сообщениям в прессе, в 2015-2016 году Microsoft планирует отказаться от бренда «Windows», создав новую ОС для планшетов, смартфонов, компьютеров, консолей, телевизоров и других устройств, а, значит, языки для разработки под эту ОС тоже могут кануть в небытие.
Мелкософт тратит очень много усилий именно для поддержки обратной совместимости. Нет никаких причин для того, чтобы так резко менять курс. Даже если такое изменение и произойдёт, о нём должны заблаговременно проинформировать, ибо слишком много сейчас у них на .Net завязано.
Вы знаете, очень хочу верить, что именно так и будет. В смысле, что будет обратная совместимость.
Однако хочу заметить, что Microsoft уже отказывалась от обратной совместимости, например:
Есть старое программное обеспечение, которое несовместимо с Windows Vista, а также драйверы и устройства.
Это всё таки единичные случаи. Если программа написана грамотно, никакие хаки и недокументированная информация в ней не использует, то она будет работать и на следующей версии винды. А так чтобы отказываться от поддержки целой технологии, причём своей же, о таком я не читал.
Ну а по указанной вами ссылке: кто же виноват, что производители устройств не следовали USB спецификациям:)
Интересно услышать от автора подобное сравнение с Vala: live.gnome.org/Vala
— переносимость (в рамках gcc)
— компиляция в native (посредством gcc)
— полная интеграция с существующими библиотеками на C (для этого собственно и разработан)
— С# подобный синтаксис и основные концепции
— вместо сборщика мусора и деструкторов выбран усредненный вариант — счетчик ссылок
— компилируется в JavaScript (пока экспериментально)
Если оценивать по приведенному списку, то D разве что в JavaScript не компилируется. Почему бы не предоставить линк на обзор Vala? Тогда можно и сравнить, а ставить рядом язык, на котором написано N строк кода и язык, который только что вычитан в интернетах — не практично.
Основная проблема, которая для меня крайне важна, это компиляция в промежуточный язык Common Intermediate Language (CIL), что делает декомпиляцию тривиальной задачей.

И в чем проблема? Сверхсекретные алгоритмы можно вынести на С и вызвать через PInvoke, а ваш код вью-модели очередного диалога никому не интересен. Это не говоря о том, что используя ту же IDA, провести реверс-инженеринг программы, написанной на С/С++ тоже не представляется чем-то особо трудным. Собственно по-этому и появились запаковщики и прочее.

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

Во-первых вы путает Free Soft и Open Source. Во-вторых если у вас есть действительно задача защитить программу от реверс-инженеринга, то ее придется целенаправленно решать не зависимо от того, на какой платформе вы пишете.

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


Самая простая защита от какого-нибудь рефлектора/dotPeek'a это когда делается небольшая программа на С, ей в ресурсы кладутся все ассембли, программа инициализирует CLR и запускает стартовую на выполнение. После чего сам ваш код работает так же, как и без запаковки. Так что вопрос вполне решаемый, хотя на мой взгляд в 90% такая проблема вообще не стоит.

Не знаю, прав ли автор, но из C# очень легко вызвать функции WinAPI, объекты COM и другие компоненты, которые сделают программу непереносимой.


А из С++ или скажем Python вызвать WinAPI разве трудно? Так называемый «system coupling», который трудно развязать, это ошибка архитектуры приложения, никак не связная с языком.

Да, конечно же, Mono – это широко известный продукт, но при его использовании проблемы всё же могут появиться. Первое, о чем следует помнить – разработчики Mono будут всегда на шаг позади Microsoft, так как они начинают реализовывать уже выпущенные библиотеки и стандарты. Второе: а им случайно не надоест? Да, я прекрасно понимаю, что это – проект со свободной лицензией, который развивает сообщество, но риск прекращения поддержки все равно существует.


А вдруг сообществу в целом и Торвальдсу в частности надоест поддерживать linux-kernel? А вдруг гугл завтра обанкротится? Такие предположения в отношении проекта, которому почти 10 лет, звучат как-то странно. Безусловно, в этом мире ни в чем нельзя быть уверен, но надо же как-то жить.

следует вспомнить – отсутствие стандартов на компоненты WinForms, ADO.NET и ASP.NET со стороны Microsoft. Их использование может повлечь за собой юридические претензии со стороны Microsoft, поэтому не рекомендуется использовать их совместно с Mono."


Ну там все тоже не так плохо на самом деле. Ребята с Моно говорят, что если что, просто постараются обойти патенты «Should patent issues ever arise, the Mono project's stated strategy for dealing with them is as follows:
Work around the patent by using a different implementation technique that retains the API, but changes the mechanism; if that is not possible, they would
Remove the pieces of code that were covered by those patents, and also
Find prior art that would render the patent useless.» Ходя судя по тому, как развивается ситуация, MS довольно либеральны в отношении Mono.

а будет ли Microsoft дальше развивать этот язык? В настоящее время все патенты на C#/CLI принадлежат Microsoft, и отказ от поддержки с её стороны будет означать смерть этому языку. Лично я считаю, что C# будет продолжать развиваться – Microsoft слишком много вложила в этот язык. Но гарантий никто дать не может


Во-первых на C# есть стандарт. Делайте свой компилятор и вперед. Развитие C# не привязано к MS, хотя безусловно именно MS двигает его. Что касается гарантий — где гарантии дальнейшего развития любого другого языка?

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


Во-первых об этом было заявлено заранее. Во-вторых никакой трагедии не было, народ просто мигрировал на .net.

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


Во-первых первый раз слышу, чтобы язык был под ОС. .net приложения на С# вполне себе пишутся под ту же WP7(это к слову о переносимости .net). И думаю в новой ос поддержка .net точно так же никуда не денется.

Лично для меня этих доводов достаточно, чтобы отказаться от использования C#


Вы знаете, я согласен, что есть примеры задач, когда C#.net не уместен — это микроконтроллеры, задачи реального времени, работы в ограниченных размерах памяти, необходимость максимальной оптимизации кода под процессор или, например, необходимость быстрого изменения кода без перезапуска приложения. Но доводы, которые привели вы более чем спорны. Что же касается самой статьи, то она скорее должна была называться «Критика С# и С++». Если говорить о D, то интересно было например посмотреть сравнение при решении одних и тех же задач. Ну пример взять простую задачу составление частотного словаря по нескольким файлам. Решить ее с учетом параллельного вычисления и/или распределительного. Сравнить решения на C#\C++\D.

Программисты на D, как часто встречаетесь с ситуацией, что нужной либы нет и её необходимо писать самостоятельно?
Примерно столь же часто, как и программисты на С. Чуть реже.
Вы недооцениваете значение совместимости ABI.
Хм, хорошая новость.

А кто щупал QtD, насколько он полноценен (или, может, есть какие-то его аналоги)?
Если верить вики, то не вполне.
Сам ни разу ещё не пробовал писать на D что-либо с GUI, не могу сказать.
Из аналогов QtD (в смысле, порт библиотеки Qt на D) ничего нет.
Вот здесь можете посмотреть, какие части Qt уже портированы, какие — еще нет. На данный момент не портированны QtSql, QtScript, QtTest и QtUiTools. Хочу заметить, что в целом поддержка библиотеки улучшается — раньше было больше не портированных компонентов (в частности, не было поддержки QtWebKit).
Возможно, текущей функциональности Вам будет достаточно, или нужные Вам классы появятся в ближайшем будущем.
Есть так же порты других GUI библиотек, в том числе:
GtkD — порт GTK+
DWT — порт SWT
wxD — порт wxWidgets
Возможно, Вам подойдёт что-то из этих библиотек.
Кстати открылся официальный русский сайт языка программирования D dlang.ru
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории