->, -->, proc, name, option, local, begin, end_proc, procname

Задайте процедуру

Блокноты MuPAD® будут демонтированы в будущем релизе. Используйте live скрипты MATLAB® вместо этого.

Live скрипты MATLAB поддерживают большую часть функциональности MuPAD, хотя существуют некоторые различия. Для получения дополнительной информации смотрите, Преобразовывают Notebook MuPAD в Live скрипты MATLAB.

Синтаксис

( x1, x2, … ) -> body
proc(
     x1 <= default1> <: type1>,
     x2 <= default2> <: type2>,
     ...
    ) <: returntype>
  <name pname;>
  <option option1, option2, …>
  <local local1, local2, …>
  <save global1, global2, …>
begin
   body
end_proc

( x1, x2, … ) --> body
_procdef(, …)

Описание

proc - end_proc задает процедуру.

Процедуры f := proc(x1, x2, ...) ... end_proc могут быть названы как системная функция в форме f(x1, x2, ...). Возвращаемое значение этого вызова является значением последней команды, выполняемой в теле процедуры (или значением, возвращенным телом через функциональный return).

Описание процедуры (x1, x2, ...) -> body эквивалентно proc(x1, x2, ...) begin body end_proc. Это полезно для определения простых процедур, для которых не нужны локальные переменные. Например, f := x -> x^2 задает математическую функцию. Если процедура использует больше чем один параметр, используйте скобки в качестве в f := (x, y) -> x^2 + y^2. Cf. Пример 1.

Описание процедуры (x1, x2, ...) --> body эквивалентно fp::unapply(body, x1, x2, ...). Различие от других определений - то, что body оценен прежде, чем задать процедуру. Cf. Пример 2.

Примечание

Оценка body не должна содержать ссылки на параметры или локальные переменные внешней процедуры.

Процедура MuPAD® может иметь произвольное число параметров. Для каждого параметра может быть задано значение по умолчанию. Это значение используется, если никакое фактическое значение не передается, когда процедура называется. Например,

f := proc(x = 42) begin body end_proc

задает значение по умолчанию параметра x, чтобы быть 42. Вызов f() эквивалентен f(42). Cf. Пример 3.

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

f := proc(x : DOM_INT) begin body end_proc

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

Также автоматическая проверка типа возвращаемое значение может быть реализована, задав returntype. Cf. Пример 4.

С ключевым словом name имя может быть задано для процедуры, например,

f := proc(...) name myName; begin body end_proc.

Существует специальная переменная procname, сопоставленный с процедурой, которая хранит ее имя. Когда тело отвечает на символьный звонок procname(args()), подлинным именем заменяют. Это - имя, заданное дополнительной записью name. Если никакая запись name не задана, первый идентификатор, которому была присвоена процедура, используется в качестве имени, т.е. f в этом случае. Cf. Пример 5.

С ключевым словом option специальные функции могут быть заданы для процедуры:

  • escape

    Должен использоваться, если процедура создает и возвращает новую процедуру который доступы локальные значения процедуры включения. Cf. Пример 6. Эта опция должна только использоваться при необходимости. Также обратитесь к Pref::warnDeadProcEnv.

  • hold

    Препятствует тому, чтобы процедура оценила фактические параметры, которыми она вызвана. Смотрите Пример 7.

  • noDebug

    Препятствует тому, чтобы отладчик исходного кода MuPAD ввел эту процедуру. Также обратитесь к Pref::ignoreNoDebug. Cf. Пример 8.

  • noFlatten

    Предотвращает выравнивание последовательностей, переданных в качестве аргументов процедуры. Смотрите Пример 9.

  • remember

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

    Это может убыстриться, например, рекурсивные процедуры решительно. Cf. Пример 10. Однако помнить таблица может стать большой и использовать большую память. Кроме того, полноценность этой функции очень ограничена в свете свойств — идентификация “тех же входных параметров” не зависит от предположений на идентификаторах или глобальных переменных, таких как DIGITS и ORDER, таким образом, возвращенный результат не может быть совместим с новыми предположениями. Использование prog::remember вместо этой опции настоятельно рекомендовано для любой функции, принимающей символьный вход.

  • noExpose

    Дает MuPAD команду скрывать тело процедуры от пользователя. Обратите внимание на то, что это предотвращает отладку процедуры, также. Cf. Пример 15.

С ключевым словом local локальные переменные процедуры заданы, например,

f := proc(...) local x, y; begin body end_proc.

Cf. Пример 11.

Локальные переменные не могут использоваться в качестве “символьных переменных” (идентификаторы). Они должны быть присвоенными значениями, прежде чем они смогут использоваться в вычислениях.

Обратите внимание на то, что имена глобальных переменных MuPAD такой DIGITS, READPATH и т.д. не должен использоваться в качестве локальных переменных. Также отошлите к ключевому слову save.

С ключевым словом save локальный контекст для глобальных переменных MuPAD создается, например,

f := proc(...) save DIGITS; begin DIGITS := newValue; ... end_proc.

Это означает, что значения, которые эти переменные имеют при вводе процедуры, восстанавливаются при выходе из процедуры. Это верно, даже если из процедуры выходят из-за ошибки. Cf. Пример 12.

Можно задать процедуры, которые принимают переменное количество аргументов. Например, можно объявить процедуру без любых формальных параметров. В теле к фактическим параметрам, которыми вызвана процедура, можно получить доступ через функциональный args. Cf. Пример 13.

При вызове имени процедуры f, скажем, обычно не распечатывает исходный код тела на экран. Используйте expose(f), чтобы видеть тело. Cf. Пример 14.

Переменная окружения MAXDEPTH ограничивает “глубину вложения” рекурсивных вызовов процедуры. Значением по умолчанию является MAXDEPTH = 500. Cf. Пример 10.

Если процедура является область слот, специальная переменная, dom содержит имя области, которой принадлежит слот. Если процедура не является доменным слотом, значением dom является NIL.

Вместо end_proc также ключевое слово может использоваться end.

Обязательное объявление proc - end_proc внутренне приводит к вызову функции ядра _procdef. Нет никакой потребности вызвать _procdef непосредственно.

При оценке процедуры MuPAD анализирует целую процедуру сначала, и только затем выполняет ее. Если вы хотите ввести новый синтаксис (например, задайте новый operator), сделайте это вне процедуры. Смотрите Пример 16.

Примеры

Пример 1

Простые процедуры могут быть сгенерированы с “оператором стрелки” ->:

f := x -> x^2 + 2*x + 1:
f(x), f(y), f(a + b), f(1.5)

f := n -> isprime(n) and isprime(n + 2):
f(i) $ i = 11..18

Следующая команда сопоставляет “анонимную” процедуру с элементами списка:

map([1, 2, 3, 4, 5, 6], x -> x^2)

delete f:

Пример 2

Объявление процедур с “оператором стрелки” является мощным инструментом. В некоторых ситуациях, однако, это приводит к потенциально неожиданным результатам:

f := x -> sin(x^2)

g := x -> f'(x)

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

g := x --> f'(x)

Конечно, в этом примере, существует еще более короткий путь:

g := f'

Пример 3

Объявление значений по умолчанию продемонстрировано. Следующая процедура использует значения по умолчанию, если вызов процедуры не обеспечивает все значения параметров:

f := proc(x, y = 1, z = 2) begin [x, y, z] end_proc:
f(x, y, z), f(x, y), f(x)

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

f()
Warning: Uninitialized variable 'x' is used.
  Evaluating: f

delete f:

Пример 4

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

f := proc(n : Type::PosInt) begin n! end_proc:

Ошибка повышена, если неподходящий параметр передается:

f(-1)
Error: Invalid object '-1'. Type of argument number 1 must be 'Type::PosInt'.
  Evaluating: f
Error: Wrong type of 1. argument (type 'Type::PosInt'
expected,        got argument '-1');   Evaluating: f 

В следующей процедуре вызывается автоматическая проверка типа возвращаемого значения:

f := proc(n : Type::PosInt) : Type::Integer
begin 
  n/2 
end_proc:

Ошибка повышена, если возвращаемое значение не является целым числом:

f(3)
Error: Invalid return value '3/2'. It must be of type 'Type::Integer'.
  Evaluating: f
Error: Wrong type of return value (type 'Type::Integer'
expected,        value is '3/2');   Evaluating: f 
delete f:

Пример 5

Запись name процедур продемонстрирована. Процедура отвечает на символьный звонок к себе при помощи переменной procname, которая содержит текущее имя процедуры:

f := proc(x)
begin
  if testtype(x,Type::Numeric) 
    then return(float(1/x))
    else return(procname(args()))
  end_if
end_proc:
f(x), f(x + 1), f(3), f(2*I)

Также сообщения об ошибке используют это имя:

f(0)
Error: Division by zero. [_invert]
  Evaluating: f

Если процедура имеет запись имени, эта запись используется:

f := proc(x)
name myName;
begin
  if testtype(x,Type::Numeric) 
    then return(float(1/x))
    else return(procname(args()))
  end_if
end_proc:
f(x), f(x + 1), f(3), f(2*I)

f(0)
Error: Division by zero. [_invert]
  Evaluating: myName
delete f:

Пример 6

Опция escape продемонстрирована. Эта опция должна использоваться, если процедура возвращает другую процедуру, которая ссылается на формальный параметр или локальную переменную генерирующейся процедуры:

f := proc(n) 
begin 
  proc(x) begin x^n end_proc
end_proc:

Без опции escape формальный параметр n f оставляет свой осциллограф: ссылки g := f(3) n внутренне. Когда g называется, он не может оценить n к значению 3, который n имел в осциллографе функционального f:

g := f(3): g(x)
Warning: Uninitialized variable 'unknown' is used.
  Evaluating: g
Error: Invalid operand. [_power]
  Evaluating: g

Опция escape дает процедуре команду f иметь дело с переменными, выходящими из локального осциллографа. Теперь, процедура, g := f(3) ссылается на значение 3, а не формальный параметр n f и g, может быть выполнена правильно:

f := proc(n) 
option escape;
begin  
  proc(x) begin x^n end_proc 
end_proc:
g := f(3): g(x), g(y), g(10)

delete f, g:

Пример 7

Опция hold продемонстрирована. С hold процедура видит фактический параметр в форме, которая использовалась в вызове процедуры. Без hold функция только видит значение параметра:

f := proc(x) option hold; begin x end_proc:
g := proc(x) begin x end_proc:
x := PI/2: 
f(sin(x) + 2) = g(sin(x) + 2), f(1/2 + 1/3) = g(1/2 + 1/3)

Процедуры с помощью option hold могут оценить аргументы с функциональным context:

f := proc(x) option hold; begin x = context(x) end_proc:
f(sin(x) + 2), f(1/2 + 1/3)

delete f, g, x:

Пример 8

Опция noDebug продемонстрирована. Команда debug запускает отладчик, который продвигается в процедуре f. После ввода команды отладчика (продолжается) c, отладчик продолжает оценку:

f := proc(x) begin x end_proc: debug(f(42))
Activating debugger...   #0 in f($1=42) at
/tmp/debug0.556:4 mdx> c Execution completed.                 
               42 

С опцией noDebug отладчик не продвигается в процедуру:

f := proc(x) option noDebug; begin x end_proc: debug(f(42))
Execution completed.                      
          42 
delete f:

Пример 9

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

f := proc(x, y) begin table(x = y) end_proc:

Параметры x, y процедуры форма f последовательность. Если вы вызываете эту процедуру для последовательности (a, b) и переменная c, MuPAD сглаживает вложенную последовательность ((a, b), c) в (a, b, c). Процедура f принимает только два аргумента. Таким образом это использует a и b, и игнорирует c:

f((a, b), c)

Когда вы используете опцию noFlatten, MuPAD не сглаживает аргументы процедуры:

g := proc(x, y) option noFlatten; begin table(x = y) end_proc:
g((a, b), c)

Для дальнейших вычислений удалите f и g:

delete f, g:

Пример 10

Опция remember продемонстрирована. Команда print в следующей процедуре указывает, выполняется ли тело процедуры:

f:= proc(n : Type::PosInt)
option remember;
begin
   print("computing ".expr2text(n)."!");
   n!
end_proc:
f(5), f(10)

При вызове процедуры снова, все значения, которые были вычислены прежде, приняты от внутреннего, “помнят таблицу”, не выполняя тело процедуры снова:

f(5)*f(10) + f(15)

remember option используется в следующей процедуре, которая вычисляет Числа Фибоначчи F (0) = 0, F (1) = 1, F (n) = F (n - 1) + F (n - 2) рекурсивно:

f := proc(n : Type::NonNegInt)
option remember;
begin
   if n = 0 or n = 1 then return(n) end_if;
   f(n - 1) + f(n - 2)
end_proc:
f(123)

Из-за рекурсивной природы f, аргументы ограничиваются максимальной рекурсивной глубиной (см. MAXDEPTH):

f(1000)
Error: Recursive definition: Reached maximal depth for nested procedure calls.
  Evaluating: f

Без option remember рекурсия является довольно медленной:

f := proc(n : Type::NonNegInt)
begin
   if n = 0 or n = 1 then return(n) end_if;
   f(n - 1) + f(n - 2)
end_proc:
f(28)

delete f:

Пример 11

Мы демонстрируем использование локальных переменных:

f := proc(a)
local x, y;
begin
  x := a^2; 
  y := a^3;
  print("x, y" = (x, y));
  x + y
end_proc:

Локальные переменные x и y не совпадают с глобальными переменными x, y вне процедуры. Вызов f не изменяет глобальные значения:

x := 0: y := 0: f(123), x, y

delete f, x, y:

Пример 12

Объявление save продемонстрировано. Следующая процедура изменяет переменную окружения DIGITS внутренне. Из-за save DIGITS восстанавливается исходное значение DIGITS, после возвращаются из процедуры:

myfloat := proc(x, digits)
save DIGITS;
begin
  DIGITS := digits;
  float(x);
end_proc:

Текущее значение DIGITS:

DIGITS

С настройкой по умолчанию DIGITS = 10, следующее преобразование плавающее страдает от числовой отмены. Из-за более высокой внутренней точности, myfloat приводит к более точному результату:

x := 10^20*(PI - 21053343141/6701487259): 
float(x), myfloat(x, 20)

Значение DIGITS не было изменено вызовом myfloat:

DIGITS

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

f := proc(n)
save x;
begin
  delete x;
  int(x^n*exp(-x), x = 0..1)
end_proc:
x := 3: f(1), f(2), f(3)

Из-за save x ранее присвоенное значение x восстанавливается после интегрирования:

x

delete myfloat, x, f:

Пример 13

Следующая процедура принимает произвольное число аргументов. Это получает доступ к фактическим параметрам через args, помещает их в список, инвертирует список через revert и возвращает его аргументы в обратном порядке:

f := proc()
local arguments;
begin
   arguments := [args()];
   op(revert(arguments))
end_proc:
f(a, b, c)

f(1, 2, 3, 4, 5, 6, 7)

delete f:

Пример 14

Используйте expose, чтобы видеть исходный код процедуры:

f := proc(x = 0, n : DOM_INT)
begin 
  sourceCode;
end_proc

expose(f)
proc(x = 0, n : DOM_INT)
  name f;
begin
  sourceCode
end_proc
delete f:

Пример 15

Опция noExpose препятствует тому, чтобы пользователи читали определение процедуры:

f := proc(a)
  option noExpose;
begin
  print(sin(a));
  if is(a>1)=TRUE then
    cos(a)
  else
    cos(a + 2)
  end_if
end_proc

f(x), f(0), f(3)

expose(f)
proc(a)
  name f;
  option noDebug, noExpose;
begin
  /* Hidden */
end_proc

Как вы видите, устанавливая опцию, noExpose неявно устанавливает опцию noDebug, также.

Для получения дополнительной информации о надлежащем использовании этой опции обратитесь к документации write.

Пример 16

Когда вы оцениваете процедуру, MuPAD анализирует целую процедуру, и только затем выполняет ее. Таким образом вы не можете задать и использовать новый оператор в процедуре. Например, когда MuPAD анализирует эту процедуру, он не распознает новый оператор <<. Причина состоит в том, что процедура еще не выполняется, и поэтому, новый оператор не задан:

f := proc(A, B)
begin
  bitshiftleft := (a, b) -> a * 2^b:
  operator("<<", bitshiftleft, Binary, 950):

  C := A<<B;

end_proc:
Error: Invalid input. Expected 'expression'. [line 6, col 10]

Задайте оператор << на интерактивном уровне:

bitshiftleft := (a, b) -> a * 2^b:
operator("<<", bitshiftleft, Binary, 950):

Теперь можно использовать << в процедурах на интерактивном уровне:

f := proc(A, B)
begin 
  C := A<<B;
end_proc:
f(2, 1)

m<<n

Параметры

x1, x2, …

Формальные параметры процедуры: идентификаторы

default1, default2, …

Значения по умолчанию для параметров: произвольные объекты MuPAD

type1, type2, …

Допустимые типы для параметров: текстовые объекты, как принято функциональным testtype

returntype

Допустимый тип для возвращаемого значения: текстовый объект, как принято функциональным testtype

pname

Имя процедуры: выражение

option1, option2, …

Доступные параметры: escape, hold, noDebug, noExpose, noFlatten, remember

local1, local2, …

Локальные переменные: идентификаторы

global1, global2, …

Глобальные переменные: идентификаторы

body

Тело процедуры: произвольная последовательность операторов

Возвращаемые значения

Процедура типа DOM_PROC.

Смотрите также

Функции MuPAD