Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции по ПАЯ (1-й семестр).doc
Скачиваний:
8
Добавлен:
20.11.2019
Размер:
1.23 Mб
Скачать

Синтаксис использования или обращения к процедурам.

Имя программы (список фактических параметров).

Список фактических параметров, разделённых запятыми, список выражений вида е1,…,еn.

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

Семантика

Прямая подразумеваемая математическая семантика почти тривиальна.

Для нас привычно вход и выход процедуры.

Имена переменных входа называются входными, выхода – выходными.

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

X:=x+y;

Внутри процедуры могут использоваться вспомогательные объекты (локальные объекты). После установления типового соответствия между определениями процедур семантика обращения к процедуре ясна – это вычисление функции в заданной точке.

Это действительно так, если все результаты процедуры объявлены как var-переменные, все оставшиеся коды объявлены как параметры значения, если все остальные используемые в теле процедуры имена локальны.

Мы не обязаны это делать, что чаще всего мотивируется соображениями эффективности.

Пример. Процедура вычисления максимального среди первых элементов массива.

Type tIndex=1..100;

tVector=array [tIndex] of real;

procedure max;

a: tVector;

n: tIndex;

Var m:real;

Begin

M:=a[i];

For i:=2 to n do

If m>a[i] then m:=a[i] ;

End.

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

Как описывать «нестандартную» семантику обращения?

Max(b,10,x);

Понять семантику обращения (то, как оно работает), уметь написать вместо обращения (пользовательского имени) соответствующее ему значение.

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

Правила построения модифицированного тела:

  1. Избавление от коллизии имён. При наличии коллизии заменить имена локальных переменных или других объектов с дублированными именами на новые, ещё не использованные в программе.

M:=a[i];

For i:=1 to n do

If m>a[i] then m:=a[i];

  1. Параметры переменные заменяются на имена фактических параметров

  2. Параметры значения вычисляются и копируются.

Пользовательские процедуры (продолжение)

Решение явно не эффективное, используется дополнительная память и тратится время на копирование, что особенно заметно в случае использования значений сложных типов (массив в динамической системе). Заметим, что понятие выражения над сложными типами скорее теоретическое, чем практическое. Возникает «соблазн» отойти от логики (т.е. чисто математического понятия процедуры как оператора), и в целях эффективности использовать особенности его (понятия) реализации. Так, в целях эффективности, можно объявить параметр сложного типа параметром переменной, даже если он по логике – вход. Второй вариант: вообще не включать это значение в список параметров (использовать как глобальное значение).

Procedure Max;

Var a: tVector; n: tIndex;

Var m: real;

max(b,10,x);

x:=b[1];

for I:=1 to n do

if x>b[I] then m:=b[I];

x:=a[1];

for I:=1 to n do

if x>a[I] then m:=b[I];

{max[10,x]}

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

Пример (к чему приводят соблазны):

Задача. По заданному массиву А породить массив В , содержащий сначала все положительные, затем все неположительные элементы А.

(рисунок).

Procedure Sort(var a: tVector; var b: tVector);

Var i,k,l: tIndex;

Begin

K:=1; l:=na;

For I:=` to na do

If a[I]>0 then

L[k]:= a[I]

Else begin

B[l]:= a[I];

K:=k+1;

End;

End.

Будет ли корректным обращение sort(c,c)? Синтаксически да (c:tVector), семантически – нет. Значение в массиве С заменяются на новые раньше, чем должны быть использованы старые. Приведи пример.

Второй вариант: использование глобальных значений. Имеет ли оно математический смысл?

Глобальные значения можно понимать как мат. параметр, именованную константу.

Правило полной локализации: не использовать глобальных объектов (подразумевалось в предыдущей лекции).

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

Изменение значений глобальных объектов в поле процедуры называется побочным эффектом.