GNU Octave: Defining Indexing And Indexed Assignment

Next: Indexed Assignment Optimization, Up: Indexing Objects [Contents][Index]

#### 34.3.1 Defining Indexing And Indexed Assignment

Objects can be indexed with parentheses, either like `a (idx)` or like `a {idx}`, or even like `a (idx).field`. However, it is up to the user to decide what this indexing actually means. In the case of our 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.

Built-in Function: subsref (val, idx)

  Perform the subscripted element selection operation according to the subscript specified by idx.

  The subscript idx is expected to 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.

  See also: subsasgn, substruct.

For example we might decide that indexing with `"()"` evaluates the polynomial and indexing with `"{}"` returns the n-th coefficient (of n-th power). In this case the `subsref` method of our polynomial class might look like

    function b = subsref (a, s)
      if (isempty (s))
        error ("polynomial: missing index");
      endif
      switch (s(1).type)
        case "()"
          ind = s(1).subs;
          if (numel (ind) != 1)
            error ("polynomial: need exactly one index");
          else
            b = polyval (fliplr (a.poly), ind{1});
          endif
        case "{}"
          ind = s(1).subs;
          if (numel (ind) != 1)
            error ("polynomial: need exactly one index");
          else
            if (isnumeric (ind{1}))
              b = a.poly(ind{1}+1);
            else
              b = a.poly(ind{1});
            endif
          endif
        case "."
          fld = s.subs;
          if (strcmp (fld, "poly"))
            b = a.poly;
          else
            error ("@polynomial/subsref: invalid property \"%s\"", fld);
          endif
        otherwise
          error ("invalid subscript type");
      endswitch
      if (numel (s) > 1)
        b = subsref (b, s(2:end));
      endif
    endfunction

The equivalent functionality for subscripted assignments uses the `subsasgn` method.

Built-in Function: subsasgn (val, idx, rhs)

  Perform the subscripted assignment operation according to the subscript specified by idx.

  The subscript idx is expected to 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.

Built-in Function: val = optimize_subsasgn_calls ()
Built-in Function: old_val = optimize_subsasgn_calls (new_val)
Built-in Function: 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.

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 the user needs to define the `end` method for the class. For example, the `end` method for our 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. It can then be used as follows:

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

Objects can also be used as the index in a subscripted expression themselves and this is controlled with the `subsindex` function.

Function File: idx = subsindex (a)

  Convert an object to an index vector.

  When a 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 that `subsindex` must return a zero-based real integer vector of the class `"double"`. For example, if the class constructor

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

  then the `subsindex` function

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

  can then be used as follows

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

  See also: class, subsref, subsasgn.

Finally, objects can equally be used like ranges, using the `colon` method

Built-in Function: r = colon (base, limit)
Built-in Function: 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` or `base : increment : limit`.

Next: Indexed Assignment Optimization, Up: Indexing Objects [Contents][Index]