34.3.1 Defining Indexing And Indexed Assignment
Objects can be indexed with parentheses or braces, either like obj(idx)
or like obj{idx}
, or even like obj(idx).field
. However, it is up to the programmer to decide what this indexing actually means. In the case of the polynomial class p(n)
might mean either the coefficient of the n-th power of the polynomial, or it might be the evaluation of the polynomial at n. The meaning of this subscripted referencing is determined by the subsref
method.
- : subsref (val, idx)
-
Perform the subscripted element selection operation on val according to the subscript specified by idx.
The subscript idx must be a structure array with fields ‘type’ and ‘subs’. Valid values for ‘type’ are
"()"
,"{}"
, and"."
. The ‘subs’ field may be either":"
or a cell array of index values.The following example shows how to extract the first two columns of a matrix
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 ]
Note that this is the same as writing
val(:, 1:2)
.If idx is an empty structure array with fields ‘type’ and ‘subs’, return val.
For example, this class uses the convention that indexing with "()"
evaluates the polynomial and indexing with "{}"
returns the n-th coefficient (of the n-th power). The code for the subsref
method looks like
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
The equivalent functionality for subscripted assignments uses the subsasgn
method.
- : subsasgn (val, idx, rhs)
-
Perform the subscripted assignment operation according to the subscript specified by idx.
The subscript idx must be a structure array with fields ‘type’ and ‘subs’. Valid values for ‘type’ are
"()"
,"{}"
, and"."
. The ‘subs’ field may be either":"
or a cell array of index values.The following example shows how to set the two first columns of a 3-by-3 matrix to zero.
val = magic (3); idx.type = "()"; idx.subs = {":", 1:2}; subsasgn (val, idx, 0) ⇒ [ 0 0 6 0 0 7 0 0 2 ]
Note that this is the same as writing
val(:, 1:2) = 0
.If idx is an empty structure array with fields ‘type’ and ‘subs’, return rhs.
See also: subsref, substruct, optimize_subsasgn_calls.
- : val = optimize_subsasgn_calls ()
- : old_val = optimize_subsasgn_calls (new_val)
- : optimize_subsasgn_calls (new_val, "local")
-
Query or set the internal flag for
subsasgn
method call optimizations.If true, Octave will attempt to eliminate the redundant copying when calling the
subsasgn
method of a user-defined class.When called from inside a function with the
"local"
option, the variable is changed locally for the function and any subroutines it calls. The original variable value is restored when exiting the function.See also: subsasgn.
Note that the subsref
and subsasgn
methods always receive the whole index chain, while they usually handle only the first element. It is the responsibility of these methods to handle the rest of the chain (if needed), usually by forwarding it again to subsref
or subsasgn
.
If you wish to use the end
keyword in subscripted expressions of an object, then there must be an end
method defined. For example, the end
method for the polynomial class might look like
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
which is a fairly generic end
method that has a behavior similar to the end
keyword for Octave Array classes. An example using the polynomial class is then
p = polynomial ([1,2,3,4]); p{end-1} ⇒ 3
Objects can also be used themselves as the index in a subscripted expression and this is controlled by the subsindex
function.
- : idx = subsindex (obj)
-
Convert an object to an index vector.
When obj is a class object defined with a class constructor, then
subsindex
is the overloading method that allows the conversion of this class object to a valid indexing vector. It is important to note thatsubsindex
must return a zero-based real integer vector of the class"double"
. For example, if the class constructor werefunction obj = myclass (a) obj = class (struct ("a", a), "myclass"); endfunction
then the
subsindex
functionfunction idx = subsindex (obj) idx = double (obj.a) - 1.0; endfunction
could be used as follows
a = myclass (1:4); b = 1:10; b(a) ⇒ 1 2 3 4
Finally, objects can be used like ranges by providing a colon
method.
- : r = colon (base, limit)
- : r = colon (base, increment, limit)
-
Return the result of the colon expression corresponding to base, limit, and optionally, increment.
This function is equivalent to the operator syntax
base : limit
orbase : increment : limit
.See also: linspace.
© 1996–2020 John W. Eaton
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://octave.org/doc/v6.3.0/Defining-Indexing-And-Indexed-Assignment.html