Служебные функции

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

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

Служебные функции в процедурах

Можно задать служебные функции в процедуре. Например, задайте служебную функцию, helper, в процедуре f:

f :=
proc(arguments)
  local helper, ...;
begin
  helper :=
  proc(...)
  begin
    ...
  end:

  ... code using helper(...) ...
end:

Функция helper не видима или доступна вне f. Ваши пользователи не видят, что helper функционирует, и поэтому, они не полагаются на конкретную реализацию этой процедуры. Можно изменить его реализацию, не повреждая их код. В то же время helper может получить доступ и изменить аргументы f.

Главный недостаток этого подхода - то, что ваши тестовые файлы не могут получить доступ к helper непосредственно. Поскольку обычно рекомендуется начать тестировать в самых маленьких стандартных блоках, это - действительный недостаток. Тем не менее, для многих задач преимущества этого подхода преобладают над этим недостатком, особенно если служебная функция должна смочь изменить аргументы функции вызова.

Служебные функции вне процедур

Можно задать служебные функции вне процедуры. Например, задайте служебную функцию, helper, в функциональной среде f:

f := funcenv(
proc(arguments)
  local ...;
begin
  ... code using f::helper(...) ...
end):
f::helper :=
proc(...)
begin
  ...
end:

Этот подход не требует, чтобы вы задали служебную функцию в функциональной среде процедуры, которая использует его. Определение служебной функции в функциональной среде только помогает вам разъясниться людям, читающим ваш код, что вы намереваетесь вызвать f::helper, в основном, или только в f. Если вы позже решаете использовать f::helper в другой процедуре, можно переместить служебную функцию в более типичную служебную библиотеку. Снова, эта рекомендация только помогает вам улучшить удобочитаемость своего кода.

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

  • Протестируйте служебные функции непосредственно.

  • Задайте служебную функцию и функцию, которая использует ее в файлах другого источника.

  • Используйте ту же служебную функцию для различных процедур.

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

  • Ваши пользователи могут получить доступ к служебным функциям. Если они полагаются на конкретную реализацию служебной функции, изменение той реализации может влиять на их код.

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

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

  • Определение служебной функции, далекой от строки кода, где вы вызываете его, уменьшает удобочитаемость кода.

Будьте осторожны при определении служебных функций в слотах функциональной среды, потому что MuPAD® использует эти слоты для перегрузки. Не задавайте служебные функции с такими именами как f::print, f::diff, f::evaluate или f::simplify, если вы не хотите использовать эти служебные функции для перегрузки.

Служебные функции в закрытиях

Можно задать служебную функцию и все процедуры, которые используют ее в одной процедуре. В этом случае необходимо также задать служебную функцию как локальную переменную той внешней процедуры. Внешняя процедура может быть анонимной. Например, создайте анонимную процедуру, которая имеет локальную переменную helper и включает служебную функцию helper и две других процедуры, f и g, то использование служебная функция:

proc()
  local helper;
  option escape;
begin
  helper :=
  proc(...)
    ...
  end:
  
  f :=
  proc(arguments)
    local ...;
  begin
    ... code using helper(...) ...
  end:
  
  g :=
  proc(arguments)
    local ...;
  begin
    ... code using helper(...) ...
  end:
end():

Для получения дополнительной информации о таких структурах, смотрите Закрытия и Статические переменные.

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

Недостаток этого подхода - то, что функция помощника не может получить доступ к локальным переменным процедур, которые используют его. Чтобы преодолеть это ограничение, можно использовать функцию context или совместно использованные статические переменные.

Примечание

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

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