Язык программирования D

Доброго всем времени суток!
Возникло желание (и даже возможность!) рассказать сообществу о замечательном языке программирования D. Как ни печально, в сети по нему все еще минимум информации, а на хабре и того меньше.
Все скорее всего о нем даже знают, но мало кто пытался писать на нем проекты, а все из за того, что он, видите ли, «не выстрелил», что у него нет будущего. Основная задумка, с которой я пишу эту статью — развеять некоторые заблуждения по поводу этого, несомненно, замечательного языка программирования, ну и заодно, конечно, просто отдать в широкие массы еще немного информации о нем.

О чем же пойдет речь?

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

А буду я следовать задумке авторов языка, и косвенно пропагандировать его, как замену (или аналог) C++ — как язык, в котором если возможности для всего, и как достойный конкурент других современных языков.

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

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

Первым делом я хотел бы показать, что язык D поддерживает все эти стили, при чем совершенно естественным образом (рискуя нарваться на неодобрение: гораздо более естественно, чем C++), что этот язык буквально — для всех.*

Для начала немного общих сведений:

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

Ничего кардинально нового (ну почти, но не будем вдаваться) в языке нет, главное его преимущество — удобство для всех.** Что это значит? Это значит, что язык комбинирует мощь и выразительность (а соответственно и так же уменьшает время разработки) языков типа Java и C#, но не теряет прямой связи с системой на уровне C ( и скорость скомпилированного кода!).
Это значит, что почти каждый программист, привыкший писать приложения на языке %langname% сможет легко и непринужденно приспособиться к D, даже не сменив свой стиль программирования!***
Ну, это все реклама, перейдем к конкретике.

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

Ну, тут вряд ли можно придумать что-то оригинальное, так что вот не очень осмысленная, но все же функция:

int inc(int a)
{
	return a+1;
}



Приятным добавлением по сравнению с C++ являются вложенные функции (в этом месте программисты на паскале торжествуют):

int incTwice(int a)
{
	int inc(int a)
	{
		return a+1;
	}
	return inc(inc(a));
}



Очень удобно для инкапсуляции, не так ли?
Это, наверное, все, что можно сказать о процедурном стиле, перейдем дальше — к более интересному.

Функциональный стиль: во-первых характеризуется тем, что функции — обьекты первого рода:

int main()
{
	auto inc = (int a) {return a+1;};
	writeln(inc(1));
}



Для любопытных, вот обьявления без автоматического вывода типа:

int function(int) inc = function (int a) {return a+1;};



Более того, в D можно создавать делегаты — функции, поддерживающие замыкания.

int c = 1;
int delegate(int) inc = delegate (int a) {return a+c;};



Функциями и делегатами легко манипулировать, они очень прозрачны и код не зашумлен из за вывода типов.
В принципе, по моим ощущениям D не менее функциональный, чем Python, хоть и не дотянет до haskell-а.

В добавок упомяну еще одну функциональную «фишку»: pure functions. Посмотрим:

pure int inc(int a)
{
	return a+1;
}



Это значит, что функция чистая, то есть не содержит и не изменяет состояния, как своего, так и системы в целом и для одинаковых аргументов даст одинаковые значения.

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

Отмечу, что он так же следит за корректностью. Не получится сделать вот так:

int c = 1;
pure int inc(int a)
{
	return a+c;	// ошибка, программист не прочитал определение чистой функции.
}



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

class A
{
	int v;
	int inc(int a)
	{
		return a+1;
	}
}



Даже возможность их наследовать никого не удивит!

class B : A
{
	int v;
	override int inc(int a)
	{
		return a+2;		// trollface
	}
}



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

Добавлю, что в языке нет множественного наследования классов, только множественное наследование интерфейсов.
Так же в языке есть хитрость: множественное наследование классов можно симулировать, не нарушая древовидную структуру графа родственных связей классов. Для тех, кто заинтересовался, не буду раскрывать интригу — читайте книгу Александреску «The D programming language».****

Это очень забавная и, в то же время, удобная особенность.

Что я еще обещал? Ах да, прототипное наследование.

Все, кто пишет на языках типа C++, не привыкли видеть такие вещи и писать в своем коде. Казалось бы, это противоестественно для компилируемых языков из за статической типизации.

Однако, тут такое тоже возможно (простите уж за много строк, но сами знаете, что ООП-код получается немного жирным):

class A
{
	string s;
	this() { s = ""; }		// да, так называются конструкторы, по-моему удобней, чем по названию класса.
	this(string s)
	{
		this.s = s;
	}
	override string toString()	// перегрузим метод корневого класса Object
	{
		return s;
	}

}

A createA(string s)
{
	class B : A		// точно, вложенные в функцию классы!
	{
		this() { s = ""; }	
		this(string s)	// конструкторы не наследуются.
		{
			this.s = s;
		}
		override string toString() { return "trollface"; }
	}
	return new B(s);
}

void main()
{
	A a = new A("hi!");
	A b = createA("hi!");
	writeln(a, " : ", b);		// ну да, выведет "hi! : trollface"
	readln();
}



Более того, для ленивых и любителей прекрасного есть анонимные классы, перепишем кусок кода:

A createA(string s)
{
	return new class A		// это значит, что наследуется от A
	{
		this() { s = ""; }
		this(string s) {this.s = s;}
		override string toString() { return "trollface"; }
	};
}



Итак, все анонсированные концепции программирования поддерживаются языком D, и при том вполне лаконично.
Конечно, этого не достаточно, чтобы язык стал хорошим. Чтобы он стал по-настоящему мощным и удобным, необходимо красивое и элегантное взаимодействие всех этих концепций.

Было бы неплохо, например, чтобы программист на javascript и программист на C++ могли писать один проект на D вдвоем, писать так, как привыкли в своей области, или, хотя бы, приближаться к этому, и при этом так, чтобы не терялась ни читабельность ни эффективность, и что еще важнее, чтобы оба стиля могли органично и без костылей взаимодействовать друг с другом.

Но это уже тема для другой статьи.

Я сам только изучаю этот замечательный язык, так что:

Во-первых, если тут найдутся гуру, которые найдут ошибки — с радостью выслушаю указания.

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

В-третьих, если возникнут вопросы, то с радостью готов ответить, обсудить и подискутировать, только без фанатизма.

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

* для многих.
** да-да, поймали — опять для многих.
*** И код при этом не станет откровенным говнокодом — каким он становится при переходе, например, от C++ к haskell (это я о себе :), а вполне вписывается в общий стиль языка.
**** А вы действительно думали, что название статьи я сам придумал?

P.S.
Как мне намекнули в комментариях, в Python все-таки есть замыкания. Видимо, давно я его пробовал, либо что-то изменилось, либо я просто забывчив. Приношу свои извинения.
Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

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

    +5
    Не помню, сколько лет назад впервые заинтересовался этим языком, но одно могу сказать точно, что за все эти годы он не «повзрослел» — не стал стабильным и не обзавёлся инструментарием.

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

    Скорее мертв, чем жив. К сожалению…
      +1
      Все верно, но моя позиция как раз и состоит в том, что это примерно потому же, почему не выстрелил Go и не выстрелит Darth — из за инертности аудитории и из за страха того, что положение не изменится в лучшую сторону.
      По поводу инструментария можно делать отдельную статью, однако скажу сразу, что уже сейчас можно писать в студии (не говоря уже о QtCreator-е и эклипсе), а стандартная библиотека существенно богаче оной в C++.
        +3
        Дело не в инертности. Если бы D был детищем Google, я бы с удовольствием писал бы на нем :) Потому что это был бы «продукт», а пока это больше похоже на хобби Брайта.
          +3
          По моему личному мнению — это как раз только достоинство. LISP, C, lua, Mathematica — тоже изначально писались «для себя», без размышлений о будущей поддержке. Самый лучший продукт тот, который вырос из хобби.
            +2
            Перефразирую — лучший продукт, это тот, которым хоть косвенно пользуется автор продукта.
              0
              Тоже верно, но я намекал не на это. Вы, я так понимаю, апеллируете к тому, что для себя плохо не сделаешь — ну так это бесспорно, только я говорил совсем о другом.
              О том, что проект, который хобби, делается не из под палки, не для денег, не для того, чтобы клиенты схавали, не для того, чтобы даже дойти до финиша. А для души. Тщательно продумывается каждая деталь. Как минимум потому, что если это хобби, то автору элементарно нравится продумывать. Потому, если продукт доходит до логического завершения, то несомненно в лучшем виде.
                +1
                Что-то вы сильно идеализируете проекты, которые делаются «для себя». Нет потребителей — нет качества.
                  0
                  Ну такой вот я мечтатель :)
          +4
          Не надо вот бросаться словами, Go живее всех живых.
      +6
      На мой взгляд вы не увидили настоящей проблемы D. Вы написали, что он «не выстрелил», но потом почему-то сразу перешли к его удобству и возможностям. Язык может быть сколь угодно красивым и удобным, но это никак не поможет тому факту, что он «не выстрелил». У D нет вменяемого инструментария, он не стандартизирован уже просто с невероятной быстротой успел обзавестись несколькими несовместимыми фремворками. D подерживается неизвестно кем, к нему нет интереса со стороны ведущих компаний, вести разработку коммерческих проектов на D просто рискованно. Плюс отсутствуют специалисты по D в достаточном объеме, что тоже чревато проблемами для бизнеса. А так да, язык красивый. Но это ничего не меняет.
        0
        К вышесказанному добавлю пример C# — язык тоже в своё время был новым, но люди-таки на него подсели. Видимо, Майкрософт правильнее продвигал своё детище, чем Digital Mars. Хотя если таки люди, как Александреску начинают писать о нём книги, то может что-то начинает меняться.
          +3
          Microsoft — международная компания-миллиардер. У них огромная доля рынка ОС и огромная куча денег на рекламу. Потому, успех C# совершенно не удивителен. Я не утверждаю, что C# не хорош сам по себе, очень даже хорош, сам люблю на нем писать, но его распространенность не только этим обусловлена.
        +2
        Более того, в D возможно то, чего мы все так хотим в Python (извиняюсь, если это на самом деле можно, но я точно знаю, что в lambda — нельзя, сам пробовал):
        Кто не понял — речь о замыканиях :)

        Либо я вас неправильно понял, либо вы гоните…
          0
          Спасибо за замечание, сейчас попробовал, и правда где-то я ошибся :)
        • НЛО прилетело и опубликовало эту надпись здесь
            +2
            Это я смешал две фразы, конечно, время разработки.
            0
            Обязательно познакомлюсь поплотнее, когда D2 включат в GCC. Язык действительно хорош сам по себе, но вникать глубже хелловорлдов пока смысла не вижу.
              0
              Пожалуй это должно будет сильно ускорить его развитие. Тогда на нем можно будет всякие серверные и системные либы в линуксах начать смело писать.
              +1
              Я чего-то не понял, или в последнем примере пропущена передача в конструктор параметра s?
                0
                О, наконец-то заметили :)
                Да, пропущена, при том намеренно. Но в данном конкретном примере смысла передавать в конструктор что-либо все равно нету, значение не используется.
                +7
                Не используйте сноски. В книгах можно немедленно их прочесть, а тут надо три экрана крутить ради пары слов.
                  0
                  Логично. Спасибо, учту на будущее.
                  0
                  А в каком смысле конструкторы не наследуются? Т.е. если самому не вызвать конструктор базового класса или не проинициализировать базовые члены вручную, то они останутся неинициализированными?
                    0
                    В смысле нельзя не писать их и надеяться на то, что компилятор скомпилирует
                    B b = new B;
                    где class B: A {...}, а у A определен конструктор по умолчанию.
                    Конструктор базового класса можно вызвать как super(args);

                      –1
                      Неудобно и бессмысленно… По крайней мере, я никогда не сталкивался в C++ с ситуацией, где вызов базового конструктора, сгенерированный компилятором, приводил к проблемам.
                        0
                        Сдается мне, вы меня не поняли, а может я вас.
                        Уверен, так будет понятней:
                        import std.stdio;
                        
                        class A
                        {
                          this() {writeln("A");}
                          ~this() {writeln("~A");}
                        }
                        
                        class B : A
                        {
                          this() {writeln("B");}
                          ~this() {writeln("~B");}
                        }
                        
                        
                        void main()
                        {
                          B b = new B;
                          clear(b);
                        }
                        


                        Выводит:
                        A
                        B
                        ~B
                        ~A

                        Как и аналогичная программа на C++.

                        Однако, программа:
                        import std.stdio;
                        
                        class A
                        {
                            string s;
                            this() { s = ""; }
                            this(string s) { this.s = s;  }
                        }
                        
                        class B : A
                        {
                            override string toString() { return "trollface"; }
                        }
                        
                        
                        void main()
                        {
                            B a = new B("hi!");
                        }
                        



                        Не компилируется потому, что вместо B. this(string s) не подставляется A.this(string).
                          0
                          А, понятно — т.е. как и в C++, конструктор по умолчанию генерируется (вызывая базовый конструктор), а с параметрами — нет? И термин «наследование конструкторов» происходит из-за того, что они все называются «this»?
                            0
                            Да, верно.
                            И нет, не верно, это не термин, это я попытался описать явление необходимости заново писать конструктор с параметроми в классе-потомке. Может, неудачно, но уж как получилось.
                              0
                              Конечно, параметрами.
                    +4
                    С одной стороны язык D выглядит как язык мечты, невзирая на то, что язык еще окончательно не сформировался.
                    С другой стороны, у него не очень хорошо с платформами, отличными от x86, поэтому я бы не стал его пока использовать в реальных проектах.
                      0
                      Я не изучал эту сторону вопроса, но вот последний (первый в списке, последний по времени) пункт changelog:
                      Better use of XMM registers in 64 bit targets.
                      Так что поддержка, несомненно, есть.
                      Может и правда не идеальная, но есть. И развивается.
                        0
                        XMM — похоже на название регистров x86-64
                      0
                      Давно присматриваюсь к D, но скорее ради интереса, чем для работы.

                      Всё. конечно, упирается в инструментарий. Вон Scala насколько удобна, но плагины сырые, поэтому даже JetBrains, несмотря на официальную поддержку плагина для Scala (правда — всего двумя разработчиками), решили сделать свой язык на JVM, который изначально будет хорошо интегрирован в среду разработки.
                        +1
                        Все пишут про нехватку инструментов для программирования.
                        Согласен, их меньше, чем для некоторых других языков, однако не все так ужасно.
                        Вообще-то я хотел в следующей статье обсудить другие темы, но если коммьюнити желает — могу подробно описать все, что знаю (и еще нагуглю) по этому поводу. Заранее скажу, я программирую на D только пару недель, однако нехватки инструментария не ощущаю.
                          0
                          Давай, там много интересного — property, unittest.

                          Инструментарий нужен для промышленного программирования, а не учебного.
                          0
                          Мне кажется, что выход стандарта C++11 был сильным шагом. Приведённый ниже код уже поддерживается распространёнными компиляторами (проверено Visual Studio 2010, должен работать с gcc, где поддержка нового стандарта более полная). Код похож на примеры приведённые в статье. Думаю, что если стоит выбор куда инвестировать свои усилия, в изучение C++11, или в изучение D, у C++11 есть определённые преимущества. Мы уже сейчас активно используем реализованное в Visual Studio 2010 подмножество C++11 в production, и впечатления очень хорошие.

                          int incTwice(int a)
                          {
                            auto inc = []( int i ) { return i+1; };
                            return inc(inc(a));
                          }
                          


                          #include <functional>
                          
                          void testLambdas(int c)
                          {
                            auto f = []( int a ) { return a+1; };
                            std::function<int(int)> f2 = []( int a ) { return a+1; };
                            auto inc = [c] (int a) { return a+c; };
                          }
                          
                            0
                            Верно, лямбды создаются уже и в C++.
                            Однако, во-первых они не так хороши. Ваше [] на самом деле почти всегда (если это делегат) совсем даже не [], а сложным выражением, выбирающим какие переменные и как туда послать. А если их много?
                            Во-вторых может это мой личный вкус, но std::function<int(int)> — это, конечно, хорошо, а что, если она вектор строк возвращает? Макароны получаются. Или много typedef. Замечу, что да, auto спасает, но работает оно не везде и не для всех типов.
                            Попробуйте, например, написать такой код:
                            int[string] function(int[string]) getFun()
                            {
                              return (int[string] a) {return a ~= ["hi" : 1];};
                            }
                            


                            Но это все, конечно, житейские мелочи, глобально я полностью согласен, что новый стандарт неплохо улучшил язык.
                            Однако лямбды — далеко не все, что я описал в статье и тем более, далеко не все, чем отличается C++ от D.
                              0
                              Ой, ошибочка, там И потом тип функции getFun тоже можно заменить на auto. Что тоже очень удобно.
                                0
                                Что-то пошло не там. Должно быть написано «Ой, ошибочка, там ~».
                                +1
                                Эквивалентная реализация на C++ будет раза в 2 длиннее из-за необходимости прописывать библиотечные типы std::function, std::map, std::string там, где D использует встроенные типы. Гораздо важнее то, что нужно больше внимания уделять логике передачи параметров и возврата результата по значению или ссылке: на С++ я бы предпочёл возвращать функцию с типом «void (map&)».

                                Чтобы в C++11 компилятор делал черновую работу, и сам решал что и как собирать в функцию можно использовать синтаксис [=], [&]. Первый вариант будет сохранять копию используемых переменных в функциональном объекте, второй — сохраняет ссылки. Лично я [=], [&] предпочитаю не пользоваться, и явно специфицирую, что и как должно сохраняться («Explicit is better than implicit», Zen of Python)

                                А вообще было бы интересно почитать об особенностях, для которых нет аналогов в языке или библиотеке C++11; о новых стилях программирования используя D.
                                  0
                                  1) [=], [&] и то и другое, несомненно, отвратительно: большие обьекты при [=] будут тормозить + вдруг надо именно по ссылке, а встроенные типы при [&] могет нежелательно себя вести. Вы совершенно правы, что управляете процессом вручную. Вот только в D в данном случае Explicit equal to implicit. Об этом я еще расскажу, несомненно.
                                  2) Да, я надеялся, что аудитории понравится и я смогу продолжить цикл и описать целую кучу особенностей, которые сами по себе вроде как довольно милые, но сильно не впечатляют, но учитывая, что их очень много, экономия кода и времени его написания получается внушительная. Про время я пока сужу субьективно, так как больших проектов не писал, но оно как минимум пропорционально количеству кода.
                                    0
                                    Когда мы смотрели на язык D для использования в новом проекте как вариант альтернативы C++, то D как раз провалился на эффективности библиотечных/встроенных типов. Всё было настолько плохо что например map отличался по производительности от 2 до 5 раз от std:map. Это было слишком много. Хотелось бы увидеть сравнения эффективности библиотечных/встроенных типов в D vs STL/C++. Если сейчас D в этом не проигрывает то как замена C++ он может быть достойной, если всё так же плохо как и было, то трудно говорить о полноценной замене C++ в той области где C++ как раз и выбирается - выжать максимум скорости имея ООП/generic programming etc.
                                      0
                                      Если пришлёте код, использовавшийся для бенчмарка С++ версий, могу поколдовать с текущим dmd и рассказать, как оно.
                                      0
                                      Насчёт (2) — не возражаете против небольшой конкуренции? :) Я вижу по количеству плюсов, что определённый интерес к языку есть, хочу написать небольшой обзор метапрограммирования/CTFE в D. Как раз то самое, что С++11 и не снилось :)
                                        +1
                                        Ну как раз следующая статья у меня планировалась по метапрограммированию и compile-time computation :)
                                          0
                                          Mkay, благое начинание, дерзайте.
                                          Cтоило бы рассмотреть то, что упрощает функциональный стиль — ranges, immutable, pure/weak pure, std.algorithm. Но в этой области не уверен, что моей компетенции хватит :(
                                            0
                                            Вот как раз я начал размышлять, что лучше в третей статье написать: тонкости функционального или обьектно-ориентированного подхода. Потому, что и там и там много интересных возможностей, и выбрать как-то сложно.
                                –2
                                — A, B, C, D, E, F, G,
                                John is hiding far from me.
                                Looking here, looking there,
                                I can’t see him anywhere.

                                Вспомнилось с уроков английского.
                                Надо же, как нас муштровали этой считалкой, что даже спустя 1,5 десятка лет ее помню.

                                С нетерпением жду продолжения статей об «алфавитных» языках. :)
                                  +1
                                  >в этом месте программисты на паскале торжествуют

                                  Они еще остались?
                                    0
                                    Сам удивляюсь этому факту, но да. Сам лично двух знаю.
                                      +2
                                      Где-то в интернетах водятся даже дикие оберонщики и форте на программисты.
                                      +2
                                      Как легко можно понять по моему профилю, я — преданный поклонник D2 и считаю его лучшим образчиком _дизайна языка_ из представленных широкой публике вариантов. Но D2 своенравен и регулярно испытывает моё терпение, даже несмотря на то, что я не использую его ни для чего, кроме любительских экспериментов.

                                      На мой взгляд, язык отчаянно нуждается в сильном open-source сообществе и главная проблема сейчас — то, что Walter всё ещё хочет сохранить за собой старые наработки Digitalmars. Люди, участвующие в разработке компилятора и стандартной бибилиотеки, вне всякого сомнения, гениальны — из регулярного чтения обсуждений тех или иных исправлений в newsgroup я узнал больше о дизайне языков, чем из любой книги. Но их довольно мало и они физически не могут выдать достаточный темп разработки для такого сложного по техническому обеспечению языка. Да, есть gdc и ldc — но в их разработке как раз «мастодонты» участия не принимают, более фанатские проекты, обречённые на постоянную синхронизацию с новыми релизами dmd.

                                      Характерно, что самый заметный прирост скорости разработки совпал с банальным переездом проекта на github.
                                        +2
                                        Собственно, моя мечта — Google вместо всяких Go и Darth'ов просто покупает Digitalmars с потрохами и даёт допилить эту няшку :) Несбыточная, конечно же.
                                          0
                                          Подписываюсь под каждым словом. Кроме несбыточнотсти. Гугл вообще проявил тенденции к внедрению инноваций и покупке кучи компаний. Так что кто знает. Да и не гуглом единым. Так что будем надеяться.
                                            0
                                            Покупают перспективные технологии, которых не оказалось в собственном арсенали, покупают потенциальное усиление для конкурентов. Не вижу «Места для D» тут.
                                          0
                                          Несколько минут уже разглядываю Ваш профиль и не могу увидеть того, из-за чего сразу должно стать понятным, что Вы — преданный поклонник D2 :) Выручайте, а то меня уже любопытство съест скоро :]
                                            0
                                            А что, мне бэйджик носить чтоли? :)
                                            Да если я буду в профиль писать все, что мне нравится, он же ух как раздуется!
                                              0
                                              Хм, тут древовидная структура комментариев не просто так же :) Я писал Volfram'у :)
                                                0
                                                Упс, мне почему-то показалось, что это к статье.
                                              0
                                              Я попал на хабр только для того, чтобы поделиться переводом статьи Александреску про D2: )
                                            0
                                            Кстати, у сего замечательного языка программирования наконец таки появился официальный русский сайт dlang.ru/
                                              0
                                              Кстати, этот сайт давно и надежно не работает. Как вариант, вэлком — http://dlanguage.ru. Официальный или не официальный — не суть. Но кого нашел на смежных форумах, пригласил всех. Заходите на огонек! :-)
                                                0

                                                Привет из 2016! Там «Медвестник», новости медицины и здоровья.

                                                0
                                                Увы ((( Хотел сменить регистратора, и не успел буквально три дня. Кто-то умудрился выкупить доменное имя раньше, видать дальше продали. Я не совсем в курсе этого вида «бизнеса», но результат нехороший((

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

                                                Самое читаемое