Вызовы по ссылке и вызовы по значению

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

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

Вызовы по значению

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

f := x -> (x := x/10):

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

x := 10:
f(x), x

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

Когда вы вызываете эту процедуру, MuPAD® выделяет новый блок памяти и копирует значение x с тем блоком. В то время как процедура выполняется, система сопоставляет локальную переменную x с этим новым блоком памяти. В конце вызова процедуры это освобождает этот блок памяти. Блок памяти, который содержит значение глобальной переменной x не изменяется.

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

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

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

Например, когда вы вызываете f(x), MuPAD указывает обеим глобальным переменным x (DOM_IDENT) и локальный (DOM_VAR) переменная x к тому же блоку памяти. Только, когда локальная переменная x изменяет его значение, MuPAD выделяет новый блок памяти для него.

Вызовы по ссылке

Как правило, когда вы вызываете процедуру MuPAD с некоторыми аргументами, система использует подход вызова значением и создает копии значений этих аргументов. Этот подход препятствует тому, чтобы процедуры изменили объекты, переданные процедуре в качестве аргументов. Для некоторых функций, таких как присвоение, MuPAD использует подход вызова ссылкой. В вызове по ссылке система не копирует значения аргументов к новым блокам памяти. Вместо этого это копирует ссылки (указатели) на эти аргументы.

Некоторые языки программирования позволяют вам задать который подход использовать в каждой конкретной функции. MuPAD не предлагает определенные построения языка для вызова ссылкой. Тем не менее, вы можете все еще вызов по ссылке в MuPAD.

Примечание

Для опытных пользователей MuPAD объекты со ссылочной семантикой могут неожиданно вести себя. Будьте осторожны при представлении ссылочной семантики пользователям, потому что она может сбить с толку.

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

A := linalg::hilbert(3)

A := linalg::gaussElim(A)

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

Также можно достигнуть эффекта вызова ссылкой в использовании MuPAD:

Лексическое определение объема

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

f :=
proc(x)
  local n, incr;
begin
  n := 0;
  incr := () -> (n := n + 1);
  while x > n do
    incr();
  end_while;
end_proc:

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

Закрытия в объектах

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

domain d
  local get, set;
  inherits Dom::BaseDomain;
  
  new := proc(x)
    option escape;
  begin
    new(dom, () -> x, y -> (x := y));
  end;

  incr := x -> set(x, get(x) + 1);
  print := x -> get(x);

begin
  get := x -> extop(x, 1)();
  set := (x, y) -> extop(x, 2)(y);
end_domain:

e := d(4)

d::incr(e)

e

Дополнительную информацию см. в Закрытиях.

Области в объектах

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

domain dd
  local get, set;
  inherits Dom::BaseDomain;

  new := proc(x)
    local d;
  begin
    d := newDomain(genident());
    d::number := x;
    new(dom, d);
  end;

  get := (x, entry) -> slot(extop(x, 1), entry);
  set := (x, entry, value) -> slot(extop(x, 1), entry, value);

  incr := x -> (dom::set(x, "number",
      dom::get(x, "number") + 1); x);
  print := x -> dom::get(x, "number");

end_domain:

e := dd(4)

dd::incr(e)

e

Примитивы plot использование библиотеки эта стратегия. Например, когда вы выполняете следующий код, доменный plot::Function2d перегружает slot функция:

f := plot::Function2d(sin(x), x=-PI..PI):
f::Color := RGB::Green:

Контекстное переключение

context функция и option hold также позвольте вам реализовать вызов быть ссылочным эффектом в ваших процедурах. option hold препятствует тому, чтобы процедура оценила свои аргументы прежде, чем выполнить код в теле процедуры. context функция позволяет вам выполнить операции, как будто они происходят в процедуре вызова.

Например, в этом коде option hold предотвращает incr процедура от оценки ее аргумента. Поэтому система не копирует значение x к новому блоку памяти:

incr :=
proc(x)
  option hold;
begin
  context(hold(_assign)(x, x + 1));
end_proc:
operator("++", incr, Prefix, 500):

При выполнении этой процедуры система выполняет операцию присвоения в контексте процедуры f (процедура вызова для incr). Таким образом, incr изменяет значение аргумента, n, которым это было вызвано:

f :=
proc(x)
  local n;
begin
  n := 0;
  while x > n do
    ++n;
  end_while;
end_proc:

Если вы используете ++ оператор на неизменном объекте, MuPAD выдает ошибку. Например, вы не можете присвоить значение 2 значению 1:

++1
Error: Invalid left side. [_assign]

Это сообщение об ошибке не упоминает incr потому что ошибка происходит в присвоении, которое выполняется в различном контексте оценки. incr процедура ведет себя по существу как динамический макрос.

Для просмотра документации необходимо авторизоваться на сайте