Лекция 09 (лекции (2002))
Описание файла
Файл "Лекция 09" внутри архива находится в папке "лекции (2002)". Документ из архива "лекции (2002)", который расположен в категории "". Всё это находится в предмете "языки программирования" из 7 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Онлайн просмотр документа "Лекция 09"
Текст из документа "Лекция 09"
Различия между базисами ЯП достаточно тривиальны. Особенно это проявляется на примере операторного базиса.
Минимальные требования с точки зрения развития, которые предъявляются к языку, достаточные для программирования отчуждаемого продукта (индустриальное программирование), это
-
Модульность. Включает в себя
-
разделение на физические модули (раздельная трансляция)
-
концепцию процедурной абстракции.
-
Разделение данных
С помощью процедурных абстракций создаются библиотеки стандартных подпрограмм. С помощью раздельной трансляции объединяется работа нескольких программистов в одно целое (индустриальный проект не может быть создан одним программистом).
Алгол имел процедурные абстракции, немного более развитую структуру данных, чем FORTRAN, но у него не было понятия раздельной трансляции. Поэтому всерьез использовать Алгол как коммерческий язык было невозможно. FORTRAN при всех его недостатках до сих пор остается индустриальным ЯП. В 60-ые г.г. на FORTRAN были созданы мощные успешные коммерческие проекты.
Самое простое и самое основное из средств развития – процедурная абстракция.
Глава 4: Процедуры и функции.
Впервые появились в языке FORTRAN. Программирование в терминах процедур и функций является базисным навыком программиста. Процедура –независимый кусок управляющих конструкций, который содержит заголовок, содержащий имя и параметры, т.е. процедура – параметризованная абстракция.
заголовок
Первые коммерческие продукты – переносимые библиотеки стандартных подпрограмм. Библиотеки, которые были созданы в 60-ые г.г. продолжают успешно существовать до сих пор. В этом одна из причин популярности FORTRAN среди его достаточно многочисленных пользователей. Но в FORTRAN очень неудобный способ взаимодействия различных подпрограмм. Было 2 способа взаимодействия:
-
через передачу параметров.
-
через общий блок. Была общая память, которая доступна всем программам. Общий блок описывался в каждой подпрограмме с помощью директивы COMMON. Таким образом мы в каждой подпрограмме ссылались на одни и те же данные. Интересно, что первоначально понятие общего блока было введено исключительно с целью экономии места.
SUBROUTINE S(X, Y, Z)
COMMON …
…
END
Внутри процедур существовали локальные переменные, но все они, также как и общие блоки располагались в статической памяти, т.к. в FORTRAN вся память была статичной. А, следовательно, не было ни понятия рекурсии, ни вложенных подпрограмм.
В Алголе 60 появились локальные среды ссылок. Внутри одной процедуры можно было описывать другие процедуры, которые локально ссылались на переменные, описанные внутри объемлющих процедур. Глубина вложенности могла быть произвольной. Появилось понятие рекурсии, и у каждого рекурсивного вызова должна быть своя порция одноименных локальных переменных. Возник стек. В первых компьютерных архитектурах стека не было. В первых реализациях Алгола компилятор определял, является ли процедура рекурсивной. Если не является, то реализовывал ее в стиле языка FORTRAN. А рекурсивные процедуры компилятор программировал иначе, создавая для хранения локальных переменных системный стек. Даже в такой распространенной архитектуре, как IBM 360, понятие стека аппаратно реализовано не было. Программист, пишущий компилятор, должен был промоделировать соответствующие концепции. Во всех без исключения компьютерных архитектурах начиная с конца 60-ых г.г. начинают появляться конструкции, которые явным образом поддерживают понятие процедуры в ЯП высокого уровня.
Механизм передачи управления.
С современной точки зрения процедура представляет собой структурную конструкцию, т.е. она имеет один вход и один выход. Вход идентифицируется по имени. В момент входа происходит связывание формальных параметров функции или процедуры с фактическими параметрами. В большинстве ЯП есть явный оператор возврата
RETURN
если это возврат из функции, то
RETURN выражение
Синтаксис этой конструкции практически не меняется с 60-ых г.г., когда она появилась в языке FORTRAN. Этот оператор может стоять в произвольном месте подпрограммы, но главное, что со структурной точки зрения конструкция имеет один вход и один выход.
В ранних ЯП существовали процедуры с множественными входами. Точки входа могли быть разными, и с разными наборами параметров.
В FORTRAN 77 до сих пор осталась конструкция ENTRY, которая позволяет по-разному именовать одну и туже подпрограмму. Надежность подобного рода конструкций сомнительна.
Во многих ранних ЯП были так называемые параметры-метки. Можно было указать в качестве фактического параметра метку. Параметры нумеровались от 0 до N, и RETURN I означал, что возврат осуществляется не в место вызова, а в некоторую точку программы, на которую указывал соответствующий аргумент-метка.
… P
CALL P …
… RETURN
… P
CALL P …
… RETURN I
I:
…
Это завуалированная форма оператора перехода. Конструкция не структурная.
В ЯП была еще одна концепция, которая также имела один вход и один выход. Это сопрограмма. В случае с подпрограммой одна подпрограмма главная, другая – подчиненная. Их отличие в том, что выполнение процедуры всегда начинается с первого оператора (в современных ЯП у процедуры только один вход). Главная программа знает имя подпрограммы, а подпрограмма не знает, кто ее использует.
г лавная P
CALL P RETURN
CALL P
Из понятия подпрограммы возникает понятие сопрограммы, если сделать главную и подчиненную равноправными. В подпрограммах не симметричны понятия вызова и возврата. В сопрограммах CALL и RETURN объединяются в одну конструкцию RESUME (возобновить).
S 1 S2
RESUME S2 RESUME S1
RESUME S2 RESUME S1
В ранних ЯП понятие сопрограммы появилось потому, что оно очень хорошо моделировало семантику квазипараллельных процессов, и это один из способов реализации параллелизма на однопроцессорной машине. RESUME – явная передача управления. Отличие от концепции процессов в ОС – ОС может насильно с помощью прерывания по времени передать управление от одного процесса к другому.
Уже в начале 60-ых г.г. многие коммерческие проекты были сделаны с помощью понятия сопрограммы. Это понятие появилось во многих ЯП: в Симуле 67, в Модуле 2 (достаточно низкоуровневое)…
В современных языках понятия сопрограммы нет. Основным назначением сопрограмм было моделирование квазипараллельных процессов, а в большинстве современных ОС концепция параллелизма присутствует. Имеются различия в реализации параллелизма в разных ОС.
В С#, C++ и Delphi концепции, которая поддерживает параллелизм явным образом, нет.
В языках Ада и Java концепция параллелизма есть. Ада в свое время претендовала на роль универсального ЯП, который должен собой заменить все другие языки, и поэтому параллелизм в нем явным образом присутствует. В Аде 95 были существенные добавления к механизму параллелизма, который за время прошедшее с момента принятия первого стандарта Ады очень сильно критиковался. Java не претендовала на роль универсального ЯП, но она претендовала на роль мультиплатформной системы, т.е. код, написанный на Java, должен выполняться на всех системах, где установлена виртуальная Java-машина. Поэтому создатели языка были обязаны включить параллельные конструкции в ЯП, чтобы программа не зависела от операционной среды.
Какие-то частные конструкции, которые моделируют параллелизм, в современных ЯП излишни. Можно использовать соответствующие библиотечные средства. При этом возникает системная зависимость. Вместо сопрограммы, можно использовать концепцию легковесного процесса, которая есть практически во всех современных ОС. В Java концепция легковесного процесса (потока, нити) присутствует явным образом. Можно сказать, что в C# концепция потока также присутствует потому, что C# основан на платформе .NET, в которой есть управление процессами. Но эти средства находятся не в самом языке, а в соответствующей системной библиотеке.
Передача данных между главной программой и подпрограммой.
В отличие от передачи управления, передача данных может быть организована по-разному.
Передача данных возникает в общем случае в двух местах: в момент вызова и в момент возврата. В момент вызова передается информация из фактических параметров в формальные. В момент возврата может передаваться информация как из формальных параметров в фактические, так и возвращаемое значение функции. В принципе в языке можно обойтись вообще без функций, ограничившись процедурами, которые модифицируют свои параметры. Это не удобно. Кроме того, если мы умеем передавать информацию из формального параметра в фактический, то достаточно просто организовать передачу возвращаемого значения функции. Рассмотрим передачу информации между формальными параметрами и фактическими, и все сказанное распространяется и на возвращаемое значение функции.
Есть три семантики передачи параметров:
-
Ввод (режим in). Информация передается только из фактического параметра в формальный. От фактического параметра требуется статус определенности, и его значение используется в вычислениях. Например: sin(x). Для вычисления значения надо знать значение х. Значение фактического параметра при вычислении никак не меняется.
-
Вывод (режим out). Информация передается из формального параметра в фактический. Например: Pop(S, x). S – стек, х –фактический параметр, который должен получить свое значение из соответствующего формального параметра. При входе от фактического параметра не требуется статус определенности, в него передается информация при выходе, и он обретает статус определенности. При выполнении процедуры состояние фактического параметра меняется.
-
Ввод Вывод (режим in out). Смешанная семантика.
В языке Ада 83 при описании формальных параметров процедур и функций требуется указать режим передачи соответствующего формального параметра. Например:
function Sin(x: in REAL) return REAL;
procedure Pop(S: in out Stack, x: out INTEGER);
Если Pop выполняется корректно, то переменная, указывающая на вершину стека, меняет свое значение, т.е. меняется состояние стека. Следовательно, параметр S должен находится в режиме вывода. В то же время от него требуется статус определенности. Поэтому S – типичный пример параметра in out.