/
n-dimens
/
pascalabcnet
Обзор
Документация
Войти
/
n-dimens
/
pascalabcnet
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
PABCNetHelp/LangGuide/Types/proctype.html
184 строки
11 KB
samuraiGH
adding working-tree-encoding attribute (#3325)
07 ноя 2025, 16:12
Не верифицирован
07 ноя 2025, 16:12
cf1fd29
Код
Авторство
О чём код?
<html> <head> <object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e"> <param name="Keyword" value="Процедурный тип и процедурные переменные"> <param name="Keyword" value="Операции с процедурными переменными"> </object> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <title></title> <link rel="StyleSheet" href="../../default.css"> </head> <body> <H1>Процедурный тип</H1> <p>Тип, предназначенный для хранения ссылок на процедуры или функции, называется процедурным, а переменная такого типа - процедурной переменной. Основное назначение процедурных переменных - хранение и косвенный вызов действий (функций) в ходе выполнения программы и передача их в качестве параметров. </p> <h2>Описание процедурного типа</h2> <p>Описание процедурного типа совпадает с заголовком соответствующей процедуры или функции без имени. Например:</p> <blockquote> <p><code><b>type</b> <br> ProcI =<b> procedure </b>(i: integer);<br> FunI = <b>function</b> (x,y: integer): integer;</code></p> </blockquote> <p>Процедурной переменной можно присвоить процедуру или функцию с совместимым типом, например:</p> <blockquote> <p><code><b>function</b> Mult(x,y: integer): integer;<br> <b>begin</b><br> Result := x*y;<br> <b>end</b>;</code></p> <p><code><b>var</b> f: FunI := Mult;</code></p> </blockquote> <p>Процедурной переменной можно также присвоить <a href="../FuncProgramming/lambdas.html">лямбда-выражение</a> с соответствующим количеством параметров и типом возвращаемого значения:</p> <blockquote> <p><code><strong>var</strong> f2: FunI := (x,y) -> x+2*y;</code></p> </blockquote> <p>После этого можно вызвать процедуру или функцию через эту процедурную переменную, пользуясь обычным синтаксисом вызова:</p> <blockquote> <p><code>write(f(2)); // 8<br>write(f2(3)); // 10</code></p> </blockquote> <h2>Cинонимы для процедурных типов</h2> <p>Для <a href="../PABCSystemUnit/Files/Standard%20types.html">наиболее распространенных процедурных типов</a> в системном модуле определен ряд синонимов. Приведем примеры с их использованием:</p> <blockquote> <p><code><strong>var</strong> f3: IntFunc := x -> 2*x-1;<br><strong>var</strong> f4: Func<integer,real> := x -> 2.5*x;<br><strong>var</strong> f3: Action<real> := x -> write(x,' ');<br><strong>var</strong> pr: Predicate<string> := s -> s.Length>0;</code></p> </blockquote> <h2>Cокращенные конструкции для процедурных типов</h2> <p>Для процедурных типов определены также сокращенные конструкции:</p> <blockquote> <p><code>() -> T; // функция без параметров, возвращающая T<br>T1 -> T; // функция c параметром T1, возвращающая T<br>(T1,T2) -> T // функция c параметрами T1 и T2, возвращающая T<br>(T1,T2,T3) -> T // функция c параметрами T1, T2 и T3, возвращающая T<br> и т.д.<br>() -> (); // процедура без параметров<br>T1 -> (); // процедура c параметром T1<br> (T1,T2) -> () // процедура c параметрами T1 и T2<br> (T1,T2,T3) -> () // процедура c параметрами T1, T2 и T3<br> и т.д.</code></p> </blockquote> <p>Сокращенные конструкции не могут описывать процедурные переменные с параметрами, передаваемыми по ссылке.</p> <p>Для процедурных переменных принята <a href="typecompatibility.html">структурная эквивалентность типов</a>: можно присваивать друг другу и передавать в качестве параметров процедурные переменные, совпадающие по структуре (типы и количество параметров, тип возвращаемого значения). </p> <h2>Процедурные переменные в качестве параметров</h2> <p>Обычно процедурные переменные передаются как параметры для реализации <i>обратного вызова</i> - вызова подпрограммы через процедурную переменную, переданную в качестве параметра в другую подпрограмму:</p> <blockquote> <p><code><b>procedure</b> forall(a: <b>array</b> <b>of</b> real; f: real->real);<br> <b>begin</b><br> <b>for</b> <b>var</b> i := 0 <b>to</b> a.Length-1 <b>do</b><br> a[i] := f(a[i]);<br> <b>end</b>;</code></p> <p><code>...<br> forall(a,x->x*2); // умножение элементов массива на 2<br> forall(a,x->x+3); // увеличение элементов массива на 3 </code></p> </blockquote> <p>Процедурная переменная может хранить нулевое значение, которое задается константой <code>nil</code>. Вызов подпрограммы через нулевую процедурную переменную приводит к ошибке.</p> <h2>Операции += и -= для процедурных переменных</h2> <p>Процедурные переменные реализуются через делегаты .NET. Это означает, что они могут хранить несколько подпрограмм. Для добавления/отсоединения подпрограмм используются операторы <code>+=</code> и <code>-=</code>:</p> <blockquote> <p><code>p1 += mult2;<br> p1 += add3;<br> forall(a,p1); </code></p> </blockquote> <p>Подпрограммы в этом случае вызываются в порядке прикрепления: вначале умножение, потом сложение.</p> <p>Отсоединение неприкрепленных подпрограмм не выполняет никаких действий:</p> <blockquote> <p><code>p1 -= print;</code></p> </blockquote> <p>Кроме того, к процедурной переменной можно прикреплять/откреплять <a href="../Classes/methods.html">классовые и экземплярные методы классов</a>. В последнем случае процедурная переменная в полях объекта запоминает некоторое состояние, которое меняется между вызовами метода, связанного с этой процедурной переменной. </p> <h2>Пример</h2> <blockquote> <p><code><b>type</b> <br> A = <b>class<br> </b> x0: integer := 1;<br> h: integer := 2; <br> <b> procedure</b> PrintNext;<br> <b> begin</b><br> Print(x0);<br> x0 *= h; <br> <b> end</b>;<br> <b> end</b>;</code></p> <p><code><b>begin<br> var</b><b> </b>p: <b>procedure</b>; <br> <b> var</b> a1 := new A();<br> p := a1.PrintNext;<br> <strong>for var </strong>i:=1 <strong>to</strong> 10 <strong>do </strong><br> p;<br> // 1 2 4 8 16 32 64 128 256 512<br> <b>end</b>.</code></p> </blockquote> <p>Подобное поведение гораздо проще реализовать с помощью <a href="../FuncProgramming/capture_variables.html">захвата переменной</a> лямбда-выражением:</p> <blockquote> <p><code><b>begin<br> var </b>x0 := 1;<b> <br> var</b> p: Action0 := <strong>procedure </strong>-><strong> begin</strong> Print(x0); x0 *= 2 <strong>end</strong>;<br> <strong>for var </strong>i:=1 <strong>to</strong> 10 <strong>do </strong><br> p;<br><b>end</b>.</code></p> </blockquote> <h2>Операции + и * для процедурных переменных</h2> <p>Процедурные переменные типа procedure, а также имена процедур без параметров, можно складывать:</p> <blockquote> <p><code><strong>var</strong> p := p1 + p2;<br> p;</code></p> </blockquote> <p>Вызов через такую процедурную переменную состоит в последовательном вызове процедур p1 и p2.</p> <p>Процедурные переменные типа procedure а также имена процедур без параметров, можно умножать на число:</p> <blockquote> <p><code><strong>var</strong> p := p1 * 5;<br> p;</code></p> </blockquote> <p>Вызов через такую процедурную переменную состоит в последовательном вызове процедуры p1 указанное количество раз.</p> <p>Можно вызывать выражение, состоящее из сумм процедур и произведения процедур на число, не используя промежуточную переменную - для этого достаточно взять такое выражение в скобки:</p> <blockquote> <p><code>(p1 * 5 + p2 * 5);<br> (5 * (p1 * p2));</code></p> </blockquote> <p> </p> <p> </p> <p> </p> <p> </p> </body> </html>