Данный пост начинает серию переводов D Programming Language Tutorial , дабы компенсировать информационный вакуум об этом системном языке. Каждая часть будет содержать константое количество материала из книги, так как оригинальные главы имеют широкий разброс в размере: от пары абзацев до нескольких печатных страниц. Все примеры кода проверяются на текущем релизе компилятора dmd 2.065 , и если возникают проблемы с технической частью, прошу отписываться в комментариях.

Благодарности

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

Главы прошли первоначальную проверку членами турецкого форума Ddili Forum . Я благодарен турецкому коммьюнити D за поддержание моего азарта и мотивации на высоком уровне.

Mert Ataol, Zafer Çelenk, и Salih Dinçer написали отзывы практически на каждую строчку книги. Can Alpay Çiftçi и Faruk Erdem Öncel играли важную роль в развитии и книги и ddili.org.

Спасибо следующим людям за их существенные исправления, рекомендации и идеи: Ergin Güney, Jordi Sayol, David Herberth, Andre Tampubolon, Gour-Gadadhara Dasa, Raphaël Jakse, Andrej Mitrovic, Johannes Pfau, Jerome Sniatecki, Jason Adams, Ali H. Çalışkan, Paul Jurczak, Brian Rogoff, Михаил Страшун, Joseph Rushton Wakeling, Tove, Hugo Florentino, Satya Pothamsetti, Luís Marques, Christoph Wendler.

Эта книга была вычитана Ergin Güney для улучшения моего Инглиша (ориг. Inglish) до нормального Английского.

Введение

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

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

  • текстовый редактор
  • компилятор для D

Вместо того, чтобы скачивать и устанавливать их по отдельности, можно рассмотреть вариант с интегрированной средой разработки (IDE). Вы можете найти информацию о редакторах и IDE для D на страницах Editors и IDE на dlang.org. Обучиться программировать на D (прим. да вообще на любом языке, кроме псевдокода) без текстового редактора или комплилятора невозможно. Инструкции по установке компилятора dmd и как им пользоваться будут рассмотрены чуть позже в следующих главах.

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

Я предполагаю, что вы не пропускаете главы. Если натыкаетесь на главы, которые особенно тяжело даются, это может быть из-за того, что в книге неудачно предоставлены все необходимые понятия. Пожалуйста, напишите автору ([email protected]) (прим. оставьте комментарий) о таких проблемах, чтобы помочь сделать эту книгу полезнее.

Книга не раскрывает программирование с использованием графического интерфейса пользователя (GUI). Хотя многие программы гораздо удобнее использовать вместе с GUI, GUI напрямую не относится к языкам программирования. Более того, проектные решения и стиль программирования с GUI может конфликтовать со стилем самого языка и его стандартной библиотеки, и усложнить изучение языка. Поэтому книга описывает только консольные программы. Как только изучены основы D и его стандартная билиботека, Phobos, вы сможете использовать любую библиотеку для GUI, какую захотите.

Главы книги доступны онлайн по мере перевода с Турецкого языка. Можно использовать ленту RSS , чтобы быть в курсе выхода новых глав.

Изучать программирование гораздо веселее в коллективе. Заходите на D.learn newsgroup , чтобы следить за дискуссиями и задавать вопросы, и отвечать на них.

Практика программирования

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

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

Может быть очень сложно обучиться программированию и преподавать его

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

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

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

The Hello World

Первой программой в большинстве книг по программированию является hello world программой. Это очень короткая и простая программа, которая выводит «привет мир» и завершается. Эта программа важна, так как она включает некоторые базовые понятия языка.

Ниже hello world на D:

import std.stdio ;

void main()
{
writeln("Hello world!" ) ;
}

Исходный код выше должен быть скомпилирован компилятором D для создания вызываемого файла.

Установка компилятора

На момент написания этой главы можно выбирать из трех компиляторов D: dmd , компилятор от Digital Mars; gdc , компилятор D для GCC; и ldc , компилятор, который использует LLVM инфраструктуру.

dmd - D компилятор, который использовался для проектирования и разработки языка в течении многих лет. Все примеры в этой книге были протестированы на dmd . По этой причине самый простой выход - начать с dmd и пробовать другие компиляторы, если для этого есть конкретная необходимость (прим. например, gdc выдает наиболее оптимизированный код).

Для установки последней версии dmd зайдите на страницу скачивания на Digital Mars и выберите версию компилятора, которая подходит под окружение компьютера. Вы должны выбрать версию dmd , которая соответствует установленной операционной системе и пакетному менеджеру, и совпадает с архитектурой процессора: 32-разрядная или 64-разрядная. Не устанавливаете компилятор для D1 (прим. первая версия - уже история)! Эта книга освещает только D второй версии .

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

Исходник

Файл, который пишет программист для компиляции, называется файлом исходных кодов или просто исходник. Так как D - компилируемый язык, исходники сами по себе не являются исполняемыми файлами. Исходный код должен быть переведен в исполняемую программу компилятором.

Как и все файлы, исходник должен иметь имя. Хотя это имя может любым, которое дозволяется операционной системой, обычно используется расширение .d для файлов с исходными кодами на D, так как среды разработки, инструменты программирования и программисты ожидают именно такое расширение. Например, test.d , game.d , invoice.d и т.д. подходят как имена для исходника.

Компилирование hello world

Скопируйте текст программы выше в текстовый файл и сохраните под именем hello.d .

Компилятор скоро проверит корректность синтаксиса исходного кода (т.е. на соответствие правилам языка) и создаст из него программу переводом в машинные коды. Для компиляции следуйте следущим шагам:

  1. Откройте окно консоли
  2. Перейдите к директории, где сохранен hello.d
  3. Введите следующую комманду (Не пишите символ $ , он для обозначения командной строки.) $ dmd hello.d

Если вы не совершили ошибок, то может показаться, что ничего не произошло. Иначе, это означает, что все прошло хорошо. В папке должен появится исполняемый файл с именем hello (или hello.exe под Windows), который только что был создан компилятором.

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

Как только программа удачно создалась, напишите имя исполняемого файла для ее запуска. Программа должна вывести «Hello world!»:

$ ./hello ← запуск программы Hello world! ← сообщение, которое она вывела

(прим. под Windows вместо./hello нужно вводить hello)

Поздравляю! Ваша первая программа на D работает как ожидается.

Флаги компилятора

Компилятор имеет множество параметров командной строки, которые используются для влияния на процесс компиляции. Чтобы увидеть список параметров, введите только имя компилятора:

$ dmd ← введите только имя DMD64 D Compiler v2.065 Copyright (c) 1999-2013 by Digital Mars written by Walter Bright Documentation: http://www.dlang.org/index.html Usage: dmd files.d ... { -switch } files.d D source files ... -unittest compile in unit tests ... -w enable warnings ...

Сокращенный вывод выше показывает только флаги, которые я рекомендую всегда использовать. Хотя это не имеет значения для hello world программы в этой главе, следующая комманда скомпилирует программу с включенными предупреждениями и модульными тестами . Мы рассмотрим эти и другие параметры детальнее в следующих главах:

$ dmd hello.d -w -unittest

Полный список параметров dmd можно найти в оффициальной документации DMD .

Еще один флаг, который может быть полезен: -run . Он компилирует исходный код, создает исполняемый файл, и запускает его за одну комманду:

$ dmd -run hello.d -w -unittest Hello world! ← программа автоматически запустилась

IDE

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

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

Если же решили установить IDE, перейдите на страницу с IDE на dlang.org , чтобы увидеть список доступных IDE (прим. пер. я пользуюсь DDT).

Разбор hello world программы

Вот краткий список из многих понятий из D, которые появились в этой короткой программе:

Ядро: Каждый язык определяет свой синтаксис, фундаментальные типы, ключевые слова, правила и т.п. Все они формируют ядро этого языка. Круглые скобки, точки с запятой и слова, такие как: main и void - все в соответствии с правилами D. Это похоже на правила Английского (Русского) языка: подлежащие, глаголы, пунктуация, структура предложения и т.д.

Ключевое слово: Специальные слова, которые являются частью ядра языка называются ключевыми . В этой программе есть два ключевых слова: import , которое используется для подключения модулей к программе; и void , которое означает «ничего не возвращает».

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

writeln выше является функцией в стандартной библиотеке D. Она используется для вывода строки текста, как можно догадаться по ее имени: write line - написать строку.

Модуль: Содержимое библиотек собраны по типам задач, для решения которых они предназначены. Такая группа называется модулем. Единственный модуль, который использует наша программа - std.stdio , который отвечает за ввод и ввод данных.

Символы и строки: Выражения такие, как "Hello world!" называются строками , и элементы строк называются символами . Единственная строка в нашей программе содержит символы "H" , "e" , "!" и другие.

Порядок выполнения: Программы выполняют свои задачи с помощью вызова операций в определенном порядке. Выполнение задач начинается с операций, которые написаны в функции с названием main . Единственная операция в нашей программе выводит строку "Hello world!" .

Важность регистра: Можно выбирать любые символы внутри строк, но вы должны использовать остальные символы точно так, как они появляются в программе. Это так, так как в программах на D важен регистр. Например, writeln и Writeln являются двумя разными именами.

Мы рассмотрим все эти особенности D подробнее в следующих главах.

Упражнения

  • Написать программу, которая выводит что-нибудь другое.
  • Измените программу, чтобы она выводила более чем одну строку.
  • Попробуйте скомпилировать программу после других изменений: например, уберите точку с запятой в конце строки с writeln и изучите ошибку компиляции.

Решения

  • import std.stdio ;

    void main()
    {
    writeln("Something else... :p" ) ;
    }

  • import std.stdio ;

    void main()
    {
    writeln("A line..." ) ;
    writeln("Another line..." ) ;
    }

  • Следующая программа не может быть скомпилирована, так как отстутсвует точка с запятой в конце строки с writeln :

    import std.stdio ;

    void main()
    {
    writeln("Hello world!" )
    }

writeln and write

В предыдущей главе мы увидели, что writeln берет строку внутри круглых скобок и печатает ее.

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

Заметка: Слово параметр описывает информацию, которая передается в функцию на концептуальном уровне. Конкретная информация, которая на самом деле передается во время выполнения программы называется аргументом. Хотя и неправильно, но эти термины иногда заменяют друг друга в индустрии программного обеспечения.

writeln может брать более одного аргумента. Она печатает их последовательно, один за другим на той же самой строке:

import std.stdio ;

void main()
{
writeln("Hello world!" , "Hello fish!" ) ;
}

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

writeln переходит на следующую строку, write остается на той же:

import std.stdio ;

void main()
{
// Напишем то, что можем на данный момент
write("Hello" ) ;

// ... предположим, что здесь есть еще операции...

Write("world!" ) ;

// ... и наконец:
writeln() ;
}

Вызов writeln без параметров просто завершает текущую строку.

Строки, которые начинаются с // , называются строками комментариев или просто

Он является языком высокого уровня , но сохраняет возможности прямого взаимодействия с программным интерфейсом операционной системы и с оборудованием. D предназначен для написания средних и крупных систем с миллионами строк исходного кода , для ведения командной разработки. Язык D имеет C-подобный синтаксис , он лёгок в изучении, поддерживает многие возможности в помощь программисту, а также пригоден для проведения агрессивной оптимизации кода компилятором.

Стабильная версия 1.0 работает на Windows , Linux , Mac OS , а с версии 1.043 также и на FreeBSD . Так же с недавнего времени стали доступны исходные коды DMD (официальная реализация компилятора от Digital Mars).

Основные особенности D

  • Облегчает написание кросс-платформенного кода;
  • Лёгкость изучения языка для тех, кто имел дело с языками C и C++;
  • Обеспечение прямого низкоуровневого доступа к оборудованию ;
  • Наличие контекстно-независимой грамматики ;
  • Легкость создания интернациональных программ ;
  • Возможность создания легковесных и самостоятельных программ

Возможности, унаследованные от C++

Синтаксис языка D схож с синтаксисом C++, что облегчает его изучение людям, знакомым с С++, а также перенос исходного кода с С++.

Отсутствие макросов

Отказ создателей языка от препроцессора (как например в языке Cи) многие расценивают как рискованный и неверный шаг. Но в Ди имеются встроенные средства, которые позволяют обходиться без препроцессора.

  • Перевод
  • Tutorial

Данный пост начинает серию переводов D Programming Language Tutorial , дабы компенсировать информационный вакуум об этом системном языке. Каждая часть будет содержать константое количество материала из книги, так как оригинальные главы имеют широкий разброс в размере: от пары абзацев до нескольких печатных страниц. Все примеры кода проверяются на текущем релизе компилятора dmd 2.065 , и если возникают проблемы с технической частью, прошу отписываться в комментариях.

Другие части:

  • Часть 1

Благодарности

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

Главы прошли первоначальную проверку членами турецкого форума Ddili Forum . Я благодарен турецкому коммьюнити D за поддержание моего азарта и мотивации на высоком уровне.

Mert Ataol, Zafer Çelenk, и Salih Dinçer написали отзывы практически на каждую строчку книги. Can Alpay Çiftçi и Faruk Erdem Öncel играли важную роль в развитии и книги и ddili.org.

Спасибо следующим людям за их существенные исправления, рекомендации и идеи: Ergin Güney, Jordi Sayol, David Herberth, Andre Tampubolon, Gour-Gadadhara Dasa, Raphaël Jakse, Andrej Mitrovic, Johannes Pfau, Jerome Sniatecki, Jason Adams, Ali H. Çalışkan, Paul Jurczak, Brian Rogoff, Михаил Страшун, Joseph Rushton Wakeling, Tove, Hugo Florentino, Satya Pothamsetti, Luís Marques, Christoph Wendler.

Эта книга была вычитана Ergin Güney для улучшения моего Инглиша (ориг. Inglish) до нормального Английского.

Введение

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

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

  • текстовый редактор
  • компилятор для D

Вместо того, чтобы скачивать и устанавливать их по отдельности, можно рассмотреть вариант с интегрированной средой разработки (IDE). Вы можете найти информацию о редакторах и IDE для D на страницах Editors и IDE на dlang.org. Обучиться программировать на D (прим. да вообще на любом языке, кроме псевдокода) без текстового редактора или комплилятора невозможно. Инструкции по установке компилятора dmd и как им пользоваться будут рассмотрены чуть позже в следующих главах.

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

Я предполагаю, что вы не пропускаете главы. Если натыкаетесь на главы, которые особенно тяжело даются, это может быть из-за того, что в книге неудачно предоставлены все необходимые понятия. Пожалуйста, напишите автору ([email protected]) (прим. оставьте комментарий) о таких проблемах, чтобы помочь сделать эту книгу полезнее.

Книга не раскрывает программирование с использованием графического интерфейса пользователя (GUI). Хотя многие программы гораздо удобнее использовать вместе с GUI, GUI напрямую не относится к языкам программирования. Более того, проектные решения и стиль программирования с GUI может конфликтовать со стилем самого языка и его стандартной библиотеки, и усложнить изучение языка. Поэтому книга описывает только консольные программы. Как только изучены основы D и его стандартная билиботека, Phobos, вы сможете использовать любую библиотеку для GUI, какую захотите.

Главы книги доступны онлайн по мере перевода с Турецкого языка. Можно использовать ленту RSS , чтобы быть в курсе выхода новых глав.

Изучать программирование гораздо веселее в коллективе. Заходите на D.learn newsgroup , чтобы следить за дискуссиями и задавать вопросы, и отвечать на них.

Практика программирования

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

Может быть очень сложно обучиться программированию и преподавать его

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

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

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

The Hello World

Первой программой в большинстве книг по программированию является hello world программой. Это очень короткая и простая программа, которая выводит «привет мир» и завершается. Эта программа важна, так как она включает некоторые базовые понятия языка.

Ниже hello world на D:

import std.stdio ;

void main()
{
writeln("Hello world!" ) ;
}

Исходный код выше должен быть скомпилирован компилятором D для создания вызываемого файла.

Установка компилятора

На момент написания этой главы можно выбирать из трех компиляторов D: dmd , компилятор от Digital Mars; gdc , компилятор D для GCC; и ldc , компилятор, который использует LLVM инфраструктуру.

dmd - D компилятор, который использовался для проектирования и разработки языка в течении многих лет. Все примеры в этой книге были протестированы на dmd . По этой причине самый простой выход - начать с dmd и пробовать другие компиляторы, если для этого есть конкретная необходимость (прим. например, gdc выдает наиболее оптимизированный код).

Для установки последней версии dmd зайдите на страницу скачивания на Digital Mars и выберите версию компилятора, которая подходит под окружение компьютера. Вы должны выбрать версию dmd , которая соответствует установленной операционной системе и пакетному менеджеру, и совпадает с архитектурой процессора: 32-разрядная или 64-разрядная. Не устанавливаете компилятор для D1 (прим. первая версия - уже история)! Эта книга освещает только D второй версии .

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

Исходник

Файл, который пишет программист для компиляции, называется файлом исходных кодов или просто исходник. Так как D - компилируемый язык, исходники сами по себе не являются исполняемыми файлами. Исходный код должен быть переведен в исполняемую программу компилятором.

Как и все файлы, исходник должен иметь имя. Хотя это имя может любым, которое дозволяется операционной системой, обычно используется расширение .d для файлов с исходными кодами на D, так как среды разработки, инструменты программирования и программисты ожидают именно такое расширение. Например, test.d , game.d , invoice.d и т.д. подходят как имена для исходника.

Компилирование hello world

Скопируйте текст программы выше в текстовый файл и сохраните под именем hello.d .

Компилятор скоро проверит корректность синтаксиса исходного кода (т.е. на соответствие правилам языка) и создаст из него программу переводом в машинные коды. Для компиляции следуйте следущим шагам:

  1. Откройте окно консоли
  2. Перейдите к директории, где сохранен hello.d
  3. Введите следующую комманду (Не пишите символ $ , он для обозначения командной строки.)
    $ dmd hello.d
Если вы не совершили ошибок, то может показаться, что ничего не произошло. Иначе, это означает, что все прошло хорошо. В папке должен появится исполняемый файл с именем hello (или hello.exe под Windows), который только что был создан компилятором.

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

Как только программа удачно создалась, напишите имя исполняемого файла для ее запуска. Программа должна вывести «Hello world!»:
$ ./hello ← запуск программы Hello world! ← сообщение, которое она вывела
(прим. под Windows вместо./hello нужно вводить hello)

Поздравляю! Ваша первая программа на D работает как ожидается.

Флаги компилятора

Компилятор имеет множество параметров командной строки, которые используются для влияния на процесс компиляции. Чтобы увидеть список параметров, введите только имя компилятора:
$ dmd ← введите только имя DMD64 D Compiler v2.065 Copyright (c) 1999-2013 by Digital Mars written by Walter Bright Documentation: http://www.dlang.org/index.html Usage: dmd files.d ... { -switch } files.d D source files ... -unittest compile in unit tests ... -w enable warnings ...

Сокращенный вывод выше показывает только флаги, которые я рекомендую всегда использовать. Хотя это не имеет значения для hello world программы в этой главе, следующая комманда скомпилирует программу с включенными предупреждениями и модульными тестами . Мы рассмотрим эти и другие параметры детальнее в следующих главах:
$ dmd hello.d -w -unittest

Полный список параметров dmd можно найти в оффициальной документации DMD .

Еще один флаг, который может быть полезен: -run . Он компилирует исходный код, создает исполняемый файл, и запускает его за одну комманду:
$ dmd -run hello.d -w -unittest Hello world! ← программа автоматически запустилась

IDE

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

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

Если же решили установить IDE, перейдите на страницу с IDE на dlang.org , чтобы увидеть список доступных IDE (прим. пер. я пользуюсь DDT).

Разбор hello world программы

Вот краткий список из многих понятий из D, которые появились в этой короткой программе:

Ядро: Каждый язык определяет свой синтаксис, фундаментальные типы, ключевые слова, правила и т.п. Все они формируют ядро этого языка. Круглые скобки, точки с запятой и слова, такие как: main и void - все в соответствии с правилами D. Это похоже на правила Английского (Русского) языка: подлежащие, глаголы, пунктуация, структура предложения и т.д.

Ключевое слово: Специальные слова, которые являются частью ядра языка называются ключевыми . В этой программе есть два ключевых слова: import , которое используется для подключения модулей к программе; и void , которое означает «ничего не возвращает».

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

writeln выше является функцией в стандартной библиотеке D. Она используется для вывода строки текста, как можно догадаться по ее имени: write line - написать строку.

Модуль: Содержимое библиотек собраны по типам задач, для решения которых они предназначены. Такая группа называется модулем. Единственный модуль, который использует наша программа - std.stdio , который отвечает за ввод и ввод данных.

Символы и строки: Выражения такие, как "Hello world!" называются строками , и элементы строк называются символами . Единственная строка в нашей программе содержит символы "H" , "e" , "!" и другие.

Порядок выполнения: Программы выполняют свои задачи с помощью вызова операций в определенном порядке. Выполнение задач начинается с операций, которые написаны в функции с названием main . Единственная операция в нашей программе выводит строку "Hello world!" .

Важность регистра: Можно выбирать любые символы внутри строк, но вы должны использовать остальные символы точно так, как они появляются в программе. Это так, так как в программах на D важен регистр. Например, writeln и Writeln являются двумя разными именами.

Мы рассмотрим все эти особенности D подробнее в следующих главах.

Упражнения

  • Написать программу, которая выводит что-нибудь другое.
  • Измените программу, чтобы она выводила более чем одну строку.
  • Попробуйте скомпилировать программу после других изменений: например, уберите точку с запятой в конце строки с writeln и изучите ошибку компиляции.

Решения

  • import std.stdio ;

    void main()
    {
    writeln("Something else... :p" ) ;
    }

  • import std.stdio ;

    void main()
    {
    writeln("A line..." ) ;
    writeln("Another line..." ) ;
    }

  • Следующая программа не может быть скомпилирована, так как отстутсвует точка с запятой в конце строки с writeln :
    import std.stdio ;

    void main()
    {
    writeln("Hello world!" )
    }

writeln and write

В предыдущей главе мы увидели, что writeln берет строку внутри круглых скобок и печатает ее.

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

Заметка: Слово параметр описывает информацию, которая передается в функцию на концептуальном уровне. Конкретная информация, которая на самом деле передается во время выполнения программы называется аргументом. Хотя и неправильно, но эти термины иногда заменяют друг друга в индустрии программного обеспечения.

writeln может принимать более одного аргумента. Она печатает их последовательно, один за другим на той же самой строке:

import std.stdio ;

void main()
{
writeln("Hello world!" , "Hello fish!" ) ;
}

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

writeln переходит на следующую строку, write остается на той же:

import std.stdio ;

void main()
{
// Напишем то, что можем на данный момент
write("Hello" ) ;

// ... предположим, что здесь есть еще операции...

Write("world!" ) ;

// ... и наконец:
writeln() ;
}

Вызов writeln без параметров просто завершает текущую строку.

Строки, которые начинаются с // , называются строками комментариев или просто

Лозунги "надо писать программы без ошибок и тогда не будут нужны вспомогательные инструменты" не имеют смысла. Мы все делали, делаем и будем делать ошибки при программировании. Конечно, нужно улучшать стиль кодирования, делать обзоры кода, использовать различные методологии, которые снизят количество ошибок. Однако ошибки всё равно будут. И если компилятор поможет выявить хотя бы часть из них, это замечательно. Именно поэтому я считаю отличной идей, вводить специальные механизмы в язык программирования, которые помогут избежать ошибок. В языке D этому уделяется существенное внимание и это замечательно.

Надо понимать, что дизайн языка и компилятор способны защитить только от части ошибок. Если программист написал алгоритм, который считает по неправильной формуле, ему ничем не помочь. Чтобы искать такие ошибки, нужен искусственный интеллект. Однако многие типовые ошибки достаточно просты и связаны с человеческой невнимательностью, усталостью, опечатками. Вот здесь синтаксис языка программирования и предупреждения компилятор могут существенно помочь в выявлении дефектов.

Каковы ошибки, возникающие из-за невнимательности? Сложный вопрос. Однако у меня есть кое-что, что позволит правдоподобно ответить на него. Испытывая анализатор PVS-Studio, мы анализируем различные open-source проекты. Найденные ошибки мы помещаем в базу данных. И чем больше ошибок определенного типа мы находим, тем больше примеров появляется у соответствующей диагностики. Конечно, анализатор ищет не все возможные типы ошибок. Однако диагностик уже много, чтобы выявлять закономерности.

Просто так нельзя взять и посмотреть, какие диагностики обнаружили максимальное количество ошибок. Новые диагностические правила появляются постепенно. Поэтому, чем раньше была реализована диагностика, тем большее проектов было проверено с её помощью. Я объединил схожие диагностики, ввёл поправочный конфидент и произвёл некоторые расчёты. Не буду утруждать читателя подробностями. Просто приведу список из 10 диагностик, которые выявляют максимальное количество ошибок: V547 +V560 , V595 , V501 , V512 +V579 , V557 , V567 +V610 , V597 , V519 , V576 , V530 . По приведённым ссылкам можно увидеть примеры обнаруженных ошибок. Можно сказать, что это "top 10" типовых ошибок, которые делают программисты на языке Си/Си++.

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

  • Есть ли какие-то механизмы в языке D, которые помогут защитить программиста от таких ошибок?
  • Если нет, то планируется ли что-то для этого сделать и как это может выглядеть?
  • Какие можно дать рекомендации программистам, использующих Си++ или D, чтобы избегать таких ошибок?

1. V547/V560. Всегда ложные или истинные условия

Причин когда возникает бессмысленное условие множество. Это может быть опечатка, неаккуратный рефакторинг, неправильный тип. Компилятор Си/Си++ лояльно относится к условиям, которые всегда истинны или ложны. Иногда такие выражения полезны. Например, можно встретить подобный код:

#define DEBUG_ON 0 if (DEBUG_ON && Foo()) Dump(X);

Однако, от этой возможности очень много вреда (примеры , примеры) . Вот один из типовых примеров:

Std::string::size_type pos = dtaFileName.rfind("/"); if (pos < 0) { pos = dtaFileName.rfind("\\"); }

Переменная "pos" имеет без знаковый тип. Поэтому условие (pos < 0) всегда ложно.

Комментарий Уолтера:

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

Конструкция unsigned<0 обычно является ошибкой в том случае, если она существует в коде высшего уровня. Однако она вполне допустима в обобщённом коде в качестве граничного случая. Она также может использоваться в коде для проверки на тип unsigned, как в случае с in -(T)1<0. Так что я бы не стал однозначно называть такой код всегда ошибочным.

2. V595. Неправильно проверенный указатель

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

Buf = buf->next; pos = buf->pos; if(!buf) return -1;

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

Комментарий Уолтера:

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

3. V501. Опечатки и Code-Paste

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

If(m_GamePad.wButtons || m_GamePad.sThumbLX || m_GamePad.sThumbLX || m_GamePad.sThumbRX || m_GamePad.sThumbRY || m_GamePad.bLeftTrigger || m_GamePad.bRightTrigger)

В подобном коде так соблазнительно скопировать строчку и немного поправить её. Результатом такого желания, будет странное поведение программы при специфическом стечении обстоятельств. Если читатель не заметил ошибку, то подскажу. Два раза проверяется член класса "sThumbLX", но нет проверки для "sThumbLY"

Комментарий Уолтера:

Я изучал этот вопрос для реализации в D. Но проблема в том, чтобы проверить, не имеет ли дублированное условие побочных эффектов и не имеют ли какие-нибудь условия между копиями побочных эффектов, которые могут повлиять на результат дублированного условия. Чтобы проверка работала надёжно и не давала ложных срабатываний, требуется качественный анализ потока данных.

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

4. V512/V579. Обработка только части буфера

Типовой ошибкой при использовании таких функций как memset, memcpy, strncmp, является обработка только части буфера. Ошибка возникает, когда вместо размера буфера вычисляется размер указателя. Кажется, такая ошибка должна сразу быть выявлена. Однако такие ошибки живут в программах многие годы (примеры , примеры). Например, приведённый ниже код для проверки целостности таблицы почти работает.

Const char * keyword; .... if (strncmp(piece, keyword, sizeof(keyword)) != 0) { HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum());

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

Комментарий Уолтера:

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

If (piece.startsWith(keyword)) ...

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

5. V557. Выход за границы массива

Классика программистского жанра. Способов совершить такие ошибки огромное множество:

  • Ошибка в алгоритме вычисления индекса.
  • Можно ненадолго забыть, что элементы в массиве нумеруются с 0.
  • Неаккуратный рефакторинг (размер массива изменили, а цикл - нет).
  • Опечатка или Copy-Paste.

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

#define FINDBUFFLEN 64 // Max buffer find/replace size static char findWhat = {"\0"}; .... findWhat = "\0";

Комментарий Уолтера:

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

6. V567/V610. Неопределённое поведение программы

Этот тип ошибки является наиболее дискуссионным. Хотя стандарт четко говорит, что какая-то конструкция приведёт к неопределённому поведению , разработчики часто с этим не соглашаются. Их аргументы:

  • Опасный код у них работал больше 10 лет и продолжает работать.
  • Да, здесь потенциальная ошибка. Но любой нормальный компилятор поймет, что я имел ввиду, и всё будет хорошо.
  • Я не буду менять платформу и компилятор. Значит всё и дальше будет работать хорошо.

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

Разнообразные примеры можно посмотреть и . Приведу пару опасных конструкций:

M_Quant.IQuant = m_Quant.IQuant--; intptr_t Val = -1; Val <<= PointerLikeTypeTraits::NumLowBitsAvailable;

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