Alexander Zhirov 5b83f89224 | ||
---|---|---|
.. | ||
README.md |
README.md
Введение
Обретая силу в простоте, язык программирования порождает красоту.
Поиск компромисса при противоречивых требованиях – сложная зада ча, для решения которой создателю языка требуется не только знание теоретических принципов и практической стороны дела, но и хороший вкус. Проектирование языка программирования – это последняя ступень мастерства в разработке программ.
D – это язык, который последовательно старается правильно действовать в пределах выбранных им ограничений, таких как доступ систем ного уровня к вычислительным ресурсам, высокая производительность и синтаксическая простота, к которой стремятся все произошедшие от C языки. Стараясь правильно действовать, D порой поступает традиционно – как другие языки, а порой ломает традиции с помощью свежего, инновационного решения. Иногда это приводило к пересмотру принципов, которым, казалось, D никогда не изменит. Например, большие фрагменты программного кода, а то и целые программы, могут быть написаны с помощью хорошо определенного, не допускающего ошибок памяти «безопасного подмножества» D. Ценой небольшого ограничения доступа на системном уровне приобретается огромное преимущество при отладке программ. D заинтересует вас, если для вас важны следующие аспекты:
- Производительность. D – это язык для системного программирования. Его модель памяти, несмотря на сильную типизацию, совмес тима с моделью памяти C. Функции на D могут вызывать функции на C, а функции на C могут использовать функции D без каких-либо промежуточных преобразований.
- Выразительность. D нельзя назвать небольшим, минималистичным языком, но его удельная мощность достаточно велика. Он по зволяет определять наглядные, не требующие объяснений инструкции, точно моделирующие сложные реалии.
- «Крутящий момент». Любой лихач-«самоделкин» скажет вам, что мощность еще не все – было бы где ее применить. На одних языках лучше всего пишутся маленькие программы. Синтаксические излишества других оправдываются только начиная с определенного объема программ. D одинаково эффективно помогает справляться и с короткими сценариями, и с большими программами, и для него отнюдь не редкость целый проект, органично вырастающий из простенького скрипта в единственном файле.
- Параллельные вычисления. Подход к параллельным вычислениям – несомненное отличие D от похожих языков, отражающее разрыв ме жду современными аппаратными решениями и архитектурой компьютеров прошлого. D покончил с проклятьем неявного разделения памяти (хотя и допускает статически проверенное, явно заданное разделение) и поощряет независимые потоки, которые «общаются» друг с другом посредством сообщений.
- Обобщенное программирование. Идея обобщенного кода, манипули рующего другим кодом, была впервые реализована в мощных макро сах Лиспа, затем в шаблонах C++, обобщенных классах Java и схожих конструкциях других языков. D также предлагает невероятно мощные механизмы обобщенного и порождающего программирования.
- Эклектизм. D подразумевает, что каждая парадигма программирования ориентирована на свою задачу разработки. Поэтому он предполагает высокоинтегрированный объединенный стиль программирования, а не Единственно Верный Подход.
- «Это мои принципы. А если они вам не нравятся, то у меня есть и другие»1. D старается всегда следовать своим принципам устройства языка. Иногда они идут вразрез с соображениями сложности реализации и трудностей использования и, главное, с человеческой природой, которая не всегда находит скрытую логику здравой и интуитивно понятной. В таких случаях все языки полагаются на собственное бесконечно субъективное понимание баланса, гибкости и – особенно – хорошего вкуса. На мой взгляд, D как минимум неплохо смотрится на фоне других языков, разработчикам которых приходилось принимать решения того же плана.
Кому адресована эта книга
Предполагается, что вы программист. То есть знаете, как решить типичную задачу программирования с помощью языка, на котором вы пишете. Неважно, какой конкретно это язык. Если вы знаете один из языков, произошедших от Алгола (C, C++, Java или C#), то будете иметь некоторое преимущество перед другими читателями – синтаксис сразу покажется знакомым, а риск встретить «мнимых друзей» (одинаковый синтаксис с разной семантикой) будет минимальным. (Особенно это касается случаев, когда вы вставляете кусок кода на C в D-файл. Он либо скомпилируется и будет делать то же самое, либо не скомпилируется вообще.)
Книга, знакомящая с языком, была бы скучной и неполной, если бы не объясняла, зачем в язык включены те или иные средства, и не показывала наиболее рациональные пути использования этих средств для решения конкретных задач. Эта книга логично обосновывает добавление в язык всех неочевидных средств и старается показать, почему не были выбраны лучшие, на первый взгляд, проектные решения. Некоторые альтернативы требуют необоснованно высоких затрат на реализацию, плохо взаимодействуют с другими средствами языка, имеющими больше прав на существование, обладают скрытыми недостатками, которые не видны в коротких и простых примерах, или просто недостаточно мощны для того, чтобы что-то значить. Важнее всего то, что разработчики языка могут совершать ошибки так же, как и все остальные люди, поэтому, пожалуй, лучшие проектные решения – те, которых никто никогда не видел.
Структура книги
Глава 1 – это бодрящая прогулка с целью знакомства с основами языка. На этом этапе не все детали полностью видны, но вы сможете почувствовать язык и научиться писать на нем простейшие программы. Главы 2 и 3 – необходимое перечисление выражений и инструкций языка соответственно. Я попытался скрасить неизбежную монотонность подробного описания, подчеркнув детали, отличающие D от других традиционных языков. Надеюсь, вам будет легко читать эти главы подряд, а также возвращаться к ним за справкой. Таблицы в конце этих глав – это «шпаргалки», интуитивно понятные краткие справочники.
В главе 4 описаны встроенные типы: массивы, ассоциативные массивы и строки. Массив можно представить себе как указатель с аварийным выключателем. Массивы в D – это средство, обеспечивающее безопасность памяти и позволяющее вам наслаждаться языком. Строки – это массивы знаков Юникода в кодировке UTF. Повсеместная поддержка Юникода в языке и стандартной библиотеке позволяет корректно и эффективно обрабатывать строки.
Прочитав первые четыре главы, вы сможете на основе предоставляемых языком абстракций писать простые программы вроде сценариев. Последующие главы знакомят с абстракциями-блоками. Глава 5 объединяет описание различных видов функций: параметризированных функций режима компиляции (шаблоны функций) и функций, вычисляемых во время компиляции. Обычно такие вопросы рассматриваются в более «продвинутых» главах, но в D работать с этими средствами достаточно просто, так что раннее знакомство с ними оправданно.
В главе 6 обсуждается объектно-ориентированное программирование на основе классов. Как и раньше, здесь органично и комплексно подается информация о параметризированных классах. Глава 7 знакомит с дополнительными типами, в частности с типом struct
, позволяющим, обычно совместно с классами, эффективно создавать абстракции.
Следующие четыре главы описывают довольно специализированные, обособленные средства. Глава 8 посвящена квалификаторам типов. Квалификаторы надежно гарантируют от ошибок, что одинаково ценно как для однопоточных, так и для многопоточных приложений. В главе 9 рассмотрены модели обработки исключительных ситуаций. В главе 10 представлен мощный инструментарий D, реализующий парадигму контрактного программирования. Этот материал намеренно вынесен в отдельную главу (а не включен в главу 9) в попытке развеять миф о том, что обработка ошибок и контрактное программирование – практически одно и то же. В главе 10 как раз и объясняется, почему это не так.
В главе 11 вы найдете информацию и рекомендации по построению больших программ из компонентов, а также небольшой обзор стандартной библиотеки D. В главе 12 рассмотрены вопросы перегрузки операторов, без которой серьезно пострадали бы многие абстракции, например комплексные числа. Наконец, в главе 13 освещен оригинальный подход D к многопоточному программированию.
Краткая история
Как бы сентиментально это ни звучало, D – дитя любви. Когда-то в 1990-х Уолтер Брайт, автор компиляторов для C и C++, решил, что больше не хочет работать над ними, и задался целью определить язык, каким, по его мнению, «он должен быть». Многие из нас в тот или иной момент начинают мечтать об определении Правильного Языка; к счастью, Уолтер уже обладал значительной частью инфраструктуры: генератором кода (back-end), компоновщиком, а главное – широчайшим опытом построения языковых процессоров. Благодаря этому опыту перед Уолтером открылась интересная перспектива. По какому-то таинственному закону природы плохо спроектированная функциональность языка проявляется в логически запутанной реализации компилятора, как отвратительный характер Дориана Грея проявлялся на его портрете. Проектируя свой новый язык, Уолтер планомерно старался избежать таких патологий.
Едва зарождающийся тогда язык был схож по духу с C++, поэтому программисты называли его просто D, несмотря на первоначальную попытку Уолтера даровать ему титул «Марса». По причинам, которые вскоре станут очевидными, назовем этот язык D1. Страсть и упорство, с которыми Уолтер работал над D1 несколько лет, привлекали все больше единомышленников. К 2006 году D1 достиг уровня сильного языка, технически способного на равных соперничать с такими уже признанными языками, как Java и C++. Но к тому времени уже было ясно, что D1 никогда не станет популярным, поскольку, в отличие от других языков, он не обладал функциональной индивидуальностью, оправдывавшей его существование. И тогда Уолтер совершил дерзкий маневр: решив представить D1 в качестве этакой первой сырой версии, он перевел его в режим поддержки и приступил к разработке нового проекта – второй итерации языка, не обязанной поддерживать обратную совместимость. Пользователи текущей версии D1 по-прежнему выигрывали от исправления ошибок, но никаких новых возможностей D1 не предоставлял. Реализовать определение наилучшего языка было суждено языку D2, который я и называю просто D.
Маневр удался. Первая итерация показала, что достойно внимания, а чего следует избегать. Кроме того, можно было не спешить с рекламой нового языка – новые члены сообщества могли спокойно работать со стабильной, активно используемой версией D1. Поскольку процесс разработки не был ограничен ни обратной совместимостью, ни сроками, можно было спокойно оценить альтернативы развития проекта и выработать правильное направление. Чтобы еще больше облегчить разработку, Уолтер призвал на помощь коллег, в том числе Бартоша Милевски и меня. Важные решения, касающиеся взглядов D на неизменяемость, обобщенное и функциональное программирование, параллельные вычисления, безопасность и многое другое, мы принимали в долгих оживленных дискуссиях на троих в одной из кофеен Киркленда (штат Вашингтон).
Тем временем D явно перерос свое прозвище «улучшенный C++», превратившись в мощный многофункциональный язык, вполне способный оставить без работы как языки для системного и прикладного (промышленного) программирования, так и языки сценариев. Оставалась одна проблема: весь этот рост и все усовершенствование прошли никем не замеченными; подходы D к программированию были документированы очень слабо.
Книга, которая сейчас перед вами, – попытка восполнить это упущение. Надеюсь, читать ее вам будет так же приятно, как мне – писать.
Благодарности
У языка D было столько разработчиков, что я и не пытаюсь перечислить их всех. Особо выделяются участники новостной группы digitalmars.D
из сети Usenet. Эта группа была для нас одновременно и рупором, и полигоном для испытаний, куда мы выносили на суд свои проектные решения. Кроме того, ребята из digitalmars.D
сгенерировали множество идей по улучшению языка.
В разработке эталонной реализации компилятора dmd
2 Уолтеру помогало сообщество, особенно Шон Келли (Sean Kelly) и Дон Клагстон (Don Clugston). Шон переписал и усовершенствовал стандартную библиотеку, подключаемую во время исполнения (включая «сборщик мусора»). Кроме того, Келли стал автором основной части реализации библиотеки, отвечающей за параллельные вычисления. Он мастер своего дела, а значит, если в ваших параллельных вычислениях появляются ошибки, то они, увы, скорее всего, ваши, а не его. Дон – эксперт в математике вообще и во всех аспектах дробных вычислений в частности. Его огромный труд позволил поднять численные примитивы D на небывалую высоту. Кроме того, Дон до предела использовал способности D по генерированию кода. Как только код эталонной реализации был открыт для широкого доступа, Дон не устоял перед соблазном добавить в него что-то свое. Вот так он и занял второе место среди разработчиков компилятора dmd
. И Шон, и Дон проявляли инициативу, выдвигая предложения по усовершенствованию спецификации D на протяжении всего процесса разработки. Последнее (но не по значению) их достоинство в том, что они чумовые хакеры. С ними очень приятно общаться как в жизни, так и виртуально. Не знаю, чем стал бы язык без них.
Что касается этой книги, я бы хотел сердечно поблагодарить всех рецензентов за отзывчивость, с которой они взялись за эту сложную и неблагодарную работу. Без них эта книга не стала бы тем, что она представляет собой сейчас (так что если она вам не нравится, пусть вас утешит то, что она могла быть гораздо хуже). Поэтому позвольте мне выразить благодарность Алехандро Арагону (Alejandro Aragón), Биллу Бакстеру (Bill Baxter), Кевину Билеру (Kevin Bealer), Тревису Бочеру (Travis Boucher), Майку Касинджино (Mike Casinghino), Альваро Кастро Кастилья (Àlvaro Castro Castilla), Ричарду Чангу (Richard Chang), Дону Клагстону, Стефану Дилли (Stephan Dilly), Кариму Филали (Karim Filali), Мишелю Фортину (Michel Fortin), Дэвиду Хелду (David B. Held), Мишелю Хелвенштейну (Michiel Helvensteijn), Бернарду Хельеру (Bernard Helyer), Джейсону Хаузу (Jason House), Сэму Ху (Sam Hu), Томасу Хьюму (Thomas Hume), Грэму Джеку (Graham St. Jack), Роберту Жаку (Robert Jacques), Кристиану Кэмму (Christian Kamm), Дэниелу Кипу (Daniel Keep), Марку Кегелу (Mark Kegel), Шону Келли, Максу Хесину (Max Khesin), Симену Хьеросу (Simen Kjærås), Коди Кёнингеру (Cody Koeninger), Денису Короскину (Denis Koroskin), Ларсу Кюллингстаду (Lars Kyllingstad), Игорю Лесику (Igor Lesik), Евгению Летучему (Eugene Letuchy), Пелле Манссону (Pelle Månsson), Миуре Масахиро (Miura Masahiro), Тиму Мэтьюсу (Tim Matthews), Скотту Мейерсу, Бартошу Милевски, Фавзи Мохамеду (Fawzi Mohamed), Эллери Ньюкамеру (Ellery Newcomer), Эрику Ниблеру (Eric Niebler), Майку Паркеру (Mike Parker), Дереку Парнеллу (Derek Parnell), Джереми Пеллетье (Jeremie Pelletier), Пабло Риполлесу (Pablo Ripolles), Брэду Робертсу (Brad Roberts), Майклу Ринну (Michael Rynn), Фою Сава (Foy Savas), Кристофу Шардту (Christof Schardt), Стиву Швайхофферу (Steve Schveighoffer), Бенджамину Шропширу (Benjamin Shropshire), Дэвиду Симше (David Simcha), Томашу Стаховяку (Tomasz Stachowiak), Роберту Стюарту (Robert Stewart), Кнуту Эрику Тайгену (Knut Erik Teigen), Кристиану Влащану (Cristian Vlăsceanu) и Леору Золману (Leor Zolman).
Андрей Александреску
Воскресенье 2 мая 2010 г.