Is there any way around Error: ()-indexing must ap

2020-07-30 03:30发布

问题:

For whatever reason, Matlab does not allow repeating round brackets () - the iterator. This blocks direct access to outputs of functions which are multidimensional array and makes dictionary object immutable, among other applications.

For example,

func1=@(x)[sin(x);cos(x)];
% let S be some large struct where everything is stored
func2=@(str)S.(str);
% let D be some containers.Map object where everything is stored
D(key)=[1;2];

In all of the 3 cases above, it is useful to be able to access the array elements directly. But any of

func1(Pi)(i); func2(f1)(i); D(key)(i)

will result in the error

()-indexing must appear last in an index expression.

Is there anyway around this besides creating a temporary variable?

As well, if your answer is that temporary variable is the ONLY way to go, would you kindly show me whether the creation of a second variable will result in duplication of the data in memory?

回答1:

  1. For the first function you could use getfield (but this use of getfield is not documented, so I wouldn't recommend it):

    >> func1 = @(x) [sin(x); cos(x)];
    >> func1(4.8)
    ans =
       -0.9962
        0.0875
    >> getfield(func1(4.8), {1})
    ans =
       -0.9962
    

    Or you could define an indexing function to extract the desired element(s):

    >> index = @(x,n) x(n);
    >> index(func1(4.8), 1)
    ans =
       -0.9962
    

    Another possibility is to define func1 as a (cell)-array of functions, instead of an array-valued function, so that you can separately refer to each value :

    >> func1 = {@(x) sin(x), @(x) cos(x)};
    >> func1{1}(4.8)
    ans =
       -0.9962
    
  2. For the second function the first two methods above are applicable:

    >> S.fieldA = [11 22 33];
    >> func2 = @(str) S.(str);
    >> getfield(func2('fieldA'), {3})
    ans =
         33
    >> index(func2('fieldA'), 3)
    ans =
         33
    
  3. For containers.Map, applying getfield twice seems to work as well (again, I wouldn't recommend it):

    >> D = containers.Map({'abc', 'def'}, {10, [20 30]});
    >> getfield(getfield(D,{'def'}), {2})
    ans =
        30    
    

    Or use the indexing function:

    >> index(D('def'), 2)
    ans =
        30
    

I would recommend the indexing function approach, which is safe and general.



回答2:

I believe there is a way, and it's right here on SO: this question. However, like the comments said it is quite ugly and the temp variable way is much more readable.

As for your follow up question, in general assigning the same array to a different variable will not generate a deep copy and only the reference is duplicated. This holds true until you modify the array using the copied reference, at which point Matlab steps in and performs the deep copy. See this Mathworks article on the subject.



标签: matlab