octave: Defining Indexing And Indexed Assignment

 
 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.
 
DONTPRINTYET       See also: Seesubsasgn XREFsubsasgn, *notesubstruct:
DONTPRINTYET       See also: Seesubsasgn XREFsubsasgn, Seesubstruct

      XREFsubstruct.
 
    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.
 
DONTPRINTYET       See also: Seesubsref XREFsubsref, *notesubstruct:
DONTPRINTYET DONTPRINTYET       See also: Seesubsref XREFsubsref, Seesubstruct

      XREFsubstruct, *noteoptimize_subsasgn_calls:
DONTPRINTYET DONTPRINTYET       See also: Seesubsref XREFsubsref, Seesubstruct

      XREFsubstruct, Seeoptimize_subsasgn_calls

      XREFoptimize_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: Seesubsasgn XREFsubsasgn.
 
    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 that ‘subsindex’ must return a zero-based real integer vector
      of the class "double".  For example, if the class constructor were
 
           function obj = myclass (a)
             obj = class (struct ("a", a), "myclass");
           endfunction
 
      then the ‘subsindex’ function
 
           function 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
 
DONTPRINTYET       See also: Seeclass XREFclass, Seesubsref XREFsubsref, *noteDONTPRINTYET       See also: Seeclass XREFclass, Seesubsref XREFsubsref, See
      subsasgn XREFsubsasgn.
 
    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’
      or ‘BASE : INCREMENT : LIMIT’.
 
      See also: Seelinspace XREFlinspace.