Spec-Zone.ru › Octave 9

Далее: Оптимизация индексированного присваивания, Вверх: Индексирование объектов [Оглавление][Индекс]

34.3.1 Определение индексирования и индексированного присваивания ¶

Объекты могут быть индексированы с помощью скобок или фигурных скобок, как obj(idx) или как obj{idx}, или даже как obj(idx).field. Однако программист решает, что это индексирование фактически означает. В случае класса полиномов p(n) может означать либо коэффициент n-й степени полинома, либо вычисление полинома в точке n. Смысл этого индексированного обращения определяется методом subsref.

: newval = subsref (val, idx) ¶

Выполнить операцию выбора элемента с индексом на val в соответствии с индексом, указанным в idx.

Индекс idx должен быть массивом структуры с полями ‘type’ и ‘subs’. Допустимые значения для ‘type’ — "()", "{}", и ".". Поле ‘subs’ может быть либо ":" , либо массивом ячеек индексов.

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

val = magic (3)
    ⇒ val = [ 8   1   6
               3   5   7
               4   9   2 ]
idx.type = "()";
idx.subs = {":", 1:2};
subsref (val, idx)
     ⇒ [ 8   1
          3   5
          4   9 ]

Обратите внимание, что это то же самое, что запись val(:, 1:2).

Если idx — это пустой массив структуры с полями ‘type’ и ‘subs’, вернуть val.

Ключевое слово end не может использоваться в subsref для присваивания по индексу.

См. также: subsasgn, substruct.

Например, этот класс использует соглашение, что индексирование с "()" вычисляет полином, а индексирование с "{}" возвращает n-й коэффициент (от n-й степени). Код для метода subsref выглядит следующим образом

function r = subsref (p, s)

  if (isempty (s))
    error ("@polynomial/subsref: missing index");
  endif

  switch (s(1).type)

    case "()"
      idx = s(1).subs;
      if (numel (idx) != 1)
        error ("@polynomial/subsref: need exactly one index");
      endif
      r = polyval (fliplr (p.poly), idx{1});

    case "{}"
      idx = s(1).subs;
      if (numel (idx) != 1)
        error ("@polynomial/subsref: need exactly one index");
      endif

      if (isnumeric (idx{1}))
        r = p.poly(idx{1}+1);
      else
        r = p.poly(idx{1});
      endif

    case "."
      fld = s.subs;
      if (! strcmp (fld, "poly"))
        error ('@polynomial/subsref: invalid property "%s"', fld);
      endif
      r = p.poly;

    otherwise
      error ("@polynomial/subsref: invalid subscript type");

  endswitch

  if (numel (s) > 1)
    r = subsref (r, s(2:end));
  endif

endfunction

Эквивалентная функциональность для индексированного присваивания использует метод subsasgn.

: newval = subsasgn (val, idx, rhs) ¶

Выполнить операцию индексированного присваивания в соответствии с индексом, указанным в idx.

Индекс idx должен быть массивом структуры с полями ‘type’ и ‘subs’. Допустимые значения для ‘type’ — "()", "{}", и ".". Поле ‘subs’ может быть либо ":" , либо массивом ячеек индексов.

Следующий пример показывает, как установить две первые колонки 3x3 матрицы в ноль.

val = magic (3);
idx.type = "()";
idx.subs = {":", 1:2};
val = subsasgn (val, idx, 0)
     ⇒  [ 0   0   6
           0   0   7
           0   0   2 ]

Обратите внимание, что это то же самое, что запись val(:, 1:2) = 0.

Если idx — это пустой массив структуры с полями ‘type’ и ‘subs’, вернуть rhs.

Ключевое слово end не может использоваться в subsasgn для присваивания по индексу.

См. также: subsref, substruct, optimize_subsasgn_calls.

: val = optimize_subsasgn_calls () ¶
: old_val = optimize_subsasgn_calls (new_val) ¶
: old_val = optimize_subsasgn_calls (new_val, "local") ¶

Запрос или установка внутреннего флага для оптимизаций вызовов метода subsasgn.

Если значение истинно, Octave попытается исключить избыточное копирование при вызове метода subsasgn пользовательского класса.

При вызове из функции с опцией "local", переменная изменяется локально для функции и всех вызываемых подпрограмм. Исходное значение переменной восстанавливается при выходе из функции.

См. также: subsasgn.

Обратите внимание, что методы subsref и subsasgn всегда получают всю цепочку индексов, в то время как обычно они обрабатывают только первый элемент. Ответственность этих методов — обработать остальную часть цепочки (если необходимо), обычно перенаправив её методам subsref или subsasgn.

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

function r = end (obj, index_pos, num_indices)

  if (num_indices != 1)
    error ("polynomial object may only have one index");
  endif

  r = length (obj.poly) - 1;

endfunction

что является довольно общим методом end, имеющим поведение, подобное ключевому слову end для классов массивов Octave. Пример с использованием класса полиномов:

p = polynomial ([1,2,3,4]);
p{end-1}
  ⇒ 3

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

: idx = subsindex (obj) ¶

Преобразовать объект в вектор индексов.

Когда obj — объект класса, определённый конструктором класса, то subsindex — это перегруженный метод, который позволяет преобразовать этот объект класса в допустимый индексный вектор. Важно отметить, что subsindex должен возвращать вектор целых чисел с плавающей запятой с нулевым началом класса "double". Например, если конструктор класса был

function obj = myclass (a)
  obj = class (struct ("a", a), "myclass");
endfunction

то функция subsindex

function idx = subsindex (obj)
  idx = double (obj.a) - 1.0;
endfunction

могла бы использоваться следующим образом

a = myclass (1:4);
b = 1:10;
b(a)
⇒ 1  2  3  4

См. также: class, subsref, subsasgn.

Наконец, объекты могут использоваться как диапазоны путём предоставления метода colon.

: r = colon (base, limit) ¶
: r = colon (base, increment, limit) ¶

Возвращает результат выражения «двоеточие», соответствующего base, limit и (необязательно) increment.

Эта функция эквивалентна синтаксису оператора base : limit или base : increment : limit.

См. также: linspace.

Далее: Оптимизация индексированного присваивания, Вверх: Индексирование объектов [Оглавление][Индекс]

© 1996–2023 The Octave Project Developers
Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.
Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.
Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions.
https://docs.octave.org/v9.2.0/Defining-Indexing-And-Indexed-Assignment.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API