->
, -->
, 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;> <optionoption1, option2, …
> <locallocal1, local2, …
> <saveglobal1, 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.
Простые процедуры могут быть сгенерированы с “оператором стрелки” ->
:
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:
Объявление процедур с “оператором стрелки” является мощным инструментом. В некоторых ситуациях, однако, это приводит к потенциально неожиданным результатам:
f := x -> sin(x^2)
g := x -> f'(x)
Причина проста: тело определения процедуры не оценено во время определения. Для тех случаев, где оценка желаема, должна использоваться долгая версия оператора стрелки:
g := x --> f'(x)
Конечно, в этом примере, существует еще более короткий путь:
g := f'
Объявление значений по умолчанию продемонстрировано. Следующая процедура использует значения по умолчанию, если вызов процедуры не обеспечивает все значения параметров:
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:
Автоматическая проверка типа аргументов процедуры и возвращаемых значений продемонстрирована. Следующая процедура принимает только положительные целые числа как аргумент:
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:
Запись 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:
Опция 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:
Опция 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:
Опция 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:
Создайте процедуру, которая принимает два аргумента и возвращает таблицу, содержащую аргументы:
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:
Опция 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:
Мы демонстрируем использование локальных переменных:
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:
Объявление 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:
Следующая процедура принимает произвольное число аргументов. Это получает доступ к фактическим параметрам через 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:
Используйте 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:
Опция 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
.
Когда вы оцениваете процедуру, 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
|
Формальные параметры процедуры: идентификаторы |
|
Значения по умолчанию для параметров: произвольные объекты MuPAD |
|
Допустимые типы для параметров: текстовые объекты, как принято функциональным |
|
Допустимый тип для возвращаемого значения: текстовый объект, как принято функциональным |
|
Имя процедуры: выражение |
|
Доступные параметры: |
|
Локальные переменные: идентификаторы |
|
Глобальные переменные: идентификаторы |
|
Тело процедуры: произвольная последовательность операторов |
Процедура типа DOM_PROC
.
MAXDEPTH
| Pref::ignoreNoDebug
| Pref::typeCheck
| Pref::warnDeadProcEnv
| args
| context
| debug
| expose
| fp::unapply
| hold
| newDomain
| return
| save
| testargs