Т. Пратт, М. Зелковиц - Языки программирования - разработка и реализация (4-е издание_ 2002) (1160801), страница 12
Текст из файла (страница 12)
Поддержка включает в себя и исправяепие ошибок, выявленных уже после того, как программа отдана в эксплуатацию, и изменения, которые необходимо внести в программу в связи собновлением аппаратной части пли операционной системы, и усовершенствование и расширение возможностей программы для удовлетворения новых потребностей.
Язык, который позволяет без особых проблем вносить многочисленные изменения и исправления в программу и создавать различные расширения (причем разными программистами и в течение многих лет), окажется в конечном счете более выгодным, чем любой другой. Синтаксис и семантика Синтаксис языка программирования определяет то, как выглядит программа на эзолз языке. Определить синтаксические правила — значит объяснить, как пишут- 42 Глава 1. Проблемы разработки языка ся операторы, объявления и другие языковые конструкции.
Свианшика языка программирования определяет смысловые значения различшях синтаксических конструкций. Например, чтобы в языке С задать вектор у из десяти целочисленных элементов, необходимо написать следуюшее обьявленпе: алг УПОВ В языке же Рааса! то же самое будет выглядеть по-другому; у: аггауГ0. 9! оГ 1лседег Как видно, их синтаксис сильно различается, хотя во время выполнения программы создаются одинаковые объекты данных. Чтобы понять смысл этих объявлений, необходимо знать семантику объявлений массивов в языках С и Рааса!.
То есть вы должны знать, что если поместить подобное обьявлсние в начало подпрограммы, то при каждом ее вызове будет создаваться вектор, содержащий указанное число элементов, а по завершении программы он будет уничтожаться. Во время выполнения подпрограммы на вектор можно ссылаться по имени у. В обоих примерах элементами всктора у будут уь Однако, если вы объявляете объект Н как список в языке Е!ВР, необходимо знать, что размер его может быть произвольным и определяется непосредственно в момент создания.
Более того, обьект может быть создан в любой момент во время выполнения программы и на первый элемент можно ссылаться одним из следующих способов: (саг У) пли Глеаб У1. В руководствах по языкам программирования и в справочниках принято строить описание языка на основе его синтаксических конструкций.
Как правило, сначала прпводится синтаксис некоторой языковой конструкции, например конкретного оператора или объявления, а затем поясняется семантика этой конструкции, то есть описывается ее смысл. В главе 3 приведена система обозначений НФБ, которая является в настоящее время основной системой обозначений, используемой для описания синтаксиса языка програаиап!>пианин.
В этой книге мы придерживаемся другого способа описания; он основан на структурах, связанных с выполнением программы. Иногда такие структуры данных и операции непосредственно связаны с конкретными синтаксическими конструкциями, но чаще эта связь является более опосредованной. Например, выполняемая программа на языке С может использовать вектор у, где у имеет структуру, определенную приведенным выше объявлением. Однако скомпилированная программа может иметь другие структуры данных, такис как центральный стек, содержащий активационные записи подпрограмм, которые напрямую не связаны с синтаксисом программы.
Эти скрытые структуры так же важны для гюннмания языка, как и видимые структуры, напрямую соответствующие тому, что программист написал в программе. Именно поэтому в данной книге рассмотрение элементов языка организовано вокруг выполняемых структур, а не синтаксических элементов. Конкретнгяй элемент, создаваемьш во время выполнения программы, может не иметь синтаксического представления в программе, может быть представлен напрямую единственным синтаксическим элементом, может выражаться через нссколько различных синтаксических элементов, которые собираются транслятором воедино для создания одного элемента виртуального компьютера. КЗ. Роль языков программирования 43 1.3.2. Парадигмы языка Когда собираются приверженцы различных языков, разговор обычно принимает форму политического митинга. Жаркая дискуссия об эффективности объявления массивов в С++ по сравнению с ) ага или о преимуществе интерпретации программ перед их компиляцией здесь обеспечена.
Хотя, по правде говоря, способ объявления массивов и вопросы трансляции слабо связаны с различиями, которые существуют между этими языками. Всегда имеются незначительные синтаксические отличия, которые просто отражают индивидуальные склонности разработчиков языков и которые практически не влияют на программы, написанные на этих языках, Чтобы понять, как устроен язык, необходимо заглянуть глубже.
Существуют четыре основные вычислительные модели, которые описывшот большинство сегодняшних методов программирования; илтперативная, аппликативная, основанная на системе правил и объектно-ориентированная. Далее мы приводим краткое описание ка>кдойт модели, Императивные языки. Илтператиепьте, или процедурные, языки — это управляемые командами или операторно-ориентированные языки программирования. Основной концепцией является состояние машины — множество всех значений всех ячеек памяти компьютера.
Программа состоит из последовательности операторов, выполнение каждого из которых влечет за собой изменение значения в одной или нескольких ячейках памяти, то есть переход машины в новое состояние. В целом синтаксис такого языка имеет впд: оператор,; оператор,; Рпс. 1.1, и отображает этот процесс. Представим, что память состоит пз набора ширикоо в коробочках, а выполнение оператора (папримср, сложение двух переменных для получения значения третьей) может быть представлено как обращение к ячейке памяти (коробочке), комбинирование тем или иным способом значений (шариков) и сохранение результата (нового шарика) в новой ячейке.
Разработка программы состоит в построении последовательных состояний машины, необходимых для достижения результата. Обычно при первом знакомстве с концепциями программирования люди сталкиваются именно с этой моделью, и многие широко распространенныеязыки подлержившот именно ее(например, С, С++, ГОВТКАК, А1 601, Р1.,т1, Рааса!, Ат)а, Вша!1та1к и СОВО1.). Эта модель вытекает из особенностей аппаратной части стандартного компьютера, вьнтолняющей инструкции (команды) последовательно.
Неудивительно, что большинство традиционных языков следуют именно этой модели. Аппликативные языки. Другим взглядом на вычисления, производимые с помощью языка программирования, является рассмотрение функции, которую выполняет программа, а не отслеживание изменяемых состояний машины во время выполнения программы, оператор за оператором. Мьт можем достичь этого, сосредоточив внимание на ожидаемом результате, а не на имеющихся в нашем распоряжении данных. Другими словами, вместо того чтобы рассматривать последовательность состояний, через которые должна пройти машина для получения ответа, вопрос следует поставить по-другому: какую функцию необходимо применить к начальному состоянию машины (путем выбора начального набора переменных и ком- 44 Глава 1, Проблемы разработки языка бинирования их определенным образом), чтобы получить требуемый ответ? Язы- ки, в которых акцентирован именно этот взгляд на вычисления, называются ап- пликатиеными, или функциональными.
4 +ж"" Императивные языки— память состоит из коробочек Аппликативные языки— определяют изменения данных в процессе извлечения их из памяти я о. Такая же операция, что и в а Каждая сетка представляет возможный фильтр, определяя операции и операнды Языки, основанные на системе правил,— используют фильтры для разрешения изменения состояния Рис. 1.1.
Вычислительные модели языков программирования Эта модель представлена на рис, 1.1, б с помощью линзы, которая получает начальные данные и путем воздействия на их представление в памяти (как при прохождении света через линзу) производит желаемый ответ. Разработка программ сводится к созданию из уже имеюшихся простых функций более сложных функций, которые поочередно воздействуют на начальный набор данных до тех пор, пока последняя функция не выдаст требуемый результат. Вместо того чтобы рассматривать последовательные состояния машины, в данной модели мы концентрируем наше внимание на последовательных преобразованиях начальных данных с помощью функций. Как только у нас есть конечный ответ (последовательность функций), его можно применить к начальным данным и получить результат Синтаксис такого языка, как правило, выглядит следующим образом: функция„(..функция,(функция,(ваянием.Л 1.3.
Роль языков программирования 45 Из описанных в данной книге языков функциональную модель поддерживают М1. и 1.1ВР. Языки, основанные на системе правил. Языки, основанные на системе правил, осуществляют проверку наличия необходимого разрешающего условия и в случае его обнаружения выполняют соответствующее действие. Наиболее распространенный язык, основанный на системе правил, — Рго!ой. Он называется такгке языком логического ггрогртьтьиирооаггия, поскольку базовые разрешающие условия относятся к классу выражений логики предикатов (более подробно данная тема будет рассмотрена в разделе ВА.2).
На рис. 1.1, в языки, основанные на системе правил, схематически представлены с помощью набора фильтров, которые нужно применить к данным, паходягцимся в памяти. Выполнение программы на подобном языке похоже на выполнение программы, написанной на императивном языке, за исключением того, что операторы выполняются не в той последовательности, в которой они определены в программе. Разрешающие условия определяют порядок выполнения. Синтаксис таких языков выглядит следующим образом: разреюаюшее условие1 -г действие1 разрешающее условие2 -г деиствие2 разреюаююее условиел -г действиел (Иногда правила записываются ввиде действие ту разреюаюдее условие, в кгггором выполняемое действие записывается слева.) Хотя Рго!оя — наиболее известный из языков такого класса, существует также множество других языков, использующих эту парадигму.