Ответ 1
Я бы определенно назвал это ошибкой в синтаксическом анализаторе; Ошибка, потому что она не начала ошибки, и вместо этого вы позволили вам написать: obj.method.prop
в первую очередь!
Тот факт, что MATLAB разбился в некоторых вариантах этого синтаксиса, является серьезной ошибкой и определенно должен быть сообщен в MathWorks.
Теперь общее правило в MATLAB заключается в том, что вы не должны "индексировать результат" напрямую. Вместо этого вы должны сначала сохранить результат в переменной, а затем проиндексировать эту переменную.
Этот факт ясен, если вы используете форму func(obj)
, а не obj.func()
, чтобы вызывать методы-члены для объектов (точечная нотация или обозначение функции):
>> A = MyClass;
>> A.procData.data % or A.procData().data
ans =
[]
>> procData(A).data
Undefined variable "procData" or class "procData".
Вместо этого, как вы отметили, вы должны использовать:
>> B = procData(A): % or: B = A.pocData;
>> [B.data]
FWIW, это также происходит при работе с простыми структурами и регулярными функциями (в отличие от объектов ООП и функций-членов), так как вы все равно не можете индексировать результат вызова функции. Пример:
% a function that works on structure scalar/arrays
function s = procStruct(s)
if numel(s) > 1
for i=1:numel(s)
s(i) = procStruct(s(i));
end
else
s.data = abs(s.data);
end
end
Затем все следующие вызовы будут вызывать ошибки (как они должны):
% 1x2 struct array
>> s = struct('data',{1 -2});
>> procStruct(s).data
Undefined variable "procStruct" or class "procStruct".
>> procStruct(s([1 2])).data
Undefined variable "procStruct" or class "procStruct".
>> feval('procStruct',s).data
Undefined variable "feval" or class "feval".
>> [email protected]; f(s([1 2])).data
Improper index matrix reference.
Возможно, вы спрашиваете себя, почему они решили не допускать такой синтаксис. Хорошо, что есть хорошая причина, почему MATLAB не позволяет индексировать вызов функции (без необходимости вводить временную переменную), будь то индексирование по индексу или индексирование индекса.
Возьмем следующую функцию, например:
function x = f(n)
if nargin == 0, n=3; end
x = magic(n);
end
Если бы мы разрешили индексировать вызов функции, тогда была бы двусмысленность в том, как интерпретировать следующий вызов f(4)
:
- следует интерпретировать его как:
f()(4)
(то есть функцию вызова без аргументов, затем проиндексировать в результирующую матрицу с помощью линейной индексации, чтобы получить 4-й элемент) - или он должен интерпретироваться как:
f(4)
(вызовите функцию с одним аргументом n = 4 и верните матрицуmagic(4)
)
Эта путаница вызвана несколькими вещами в синтаксисе MATLAB:
-
он позволяет вызывать функцию без аргументов просто по имени, не требуя скобок. Если есть функция
Скобкиf.m
, ее можно назвать либоf
, либоf()
. Это усложняет синтаксический анализ M-кода, потому что неясно, являются ли токены переменными или функциями. -
используются как для индексирования матриц, так и для вызовов функций. Поэтому, если токен
x
представляет переменную, мы используем синтаксисx(1,2)
как индексирование в матрицу. В то же время, еслиx
- это имя функции, тоx(1,2)
используется для вызова функции с двумя аргументами.
Еще одна путаница - это списки и функции, разделенные запятыми, которые возвращают несколько выходов. Пример:
>> [mx,idx] = max(magic(3))
mx =
8 9 7
idx =
1 3 2
>> [mx,idx] = max(magic(3))(4) % now what?
Должен ли мы вернуть 4-й элемент каждой выходной переменной из MAX или 4-й элемент только из первого выходного аргумента вместе с полным вторым выходом? Как насчет того, когда функция возвращает выходы разных размеров?
Все это относится к другим типам индексирования: f()(3)
/f(3)
, f().x
/f.x
, f(){3}
/f{3}
.
Из-за этого MathWorks решила избежать всего вышеперечисленного путаницы и просто не разрешить прямое индексирование результатов. К сожалению, они ограничили синтаксис в этом процессе. Например, Octave не имеет такого ограничения (вы можете написать magic(4)(1,2)
), но опять же новая система OOP все еще находится в процессе разработки, поэтому я не знаю, как Octave имеет дело с такими случаями.
Для интересующихся это напоминает мне еще одну похожую ошибку в отношении пакетов и классов и прямое индексирование для получения свойства. Результаты были разными, если вы вызвали его из командной строки, из script или из функции M файла...