Подтвердить что ты не робот

Когда я могу передать литерал: функции?

При каких обстоятельствах я могу передать литерал : функции Matlab? Я обнаружил с помощью экспериментов, что иногда буква : передается как строка ':', но в других ситуациях возникает ошибка. Например:

>> type writeargs

function writeargs(varargin)

disp(varargin);

end

>> writeargs(:)
Undefined variable writeargs.

>> writeargs(:, 1)
Undefined variable writeargs.

>> writeargs(:, 1, :)
    ':'    [1]    ':'

>> writeargs(:, :, :)
    ':'    ':'    ':'

>> writeargs(1, 2, :, 4, 5)
    [1]    [2]    ':'    [4]    [5]

>> writeargs(1, 2, :, end)
Error using writeargs
Too many output arguments.

У меня создается впечатление, что этот синтаксис разрешен, если передано не менее трех аргументов. Это кажется произвольным. Что такое юридический синтаксис здесь?

Изменить: комментарий, запрошенный для использования. Случай использования может быть, когда мои аргументы будут использоваться как фрагменты или индексы. В коде Python у меня были случаи, когда я передавал объекты slice методу. Один вариант использования - это функция, например, вдохновленная этим ответом, где небольшая функция используется для того, чтобы обойти Matlabs неспособность интерпретировать magic(5)(3, :), и можно было бы написать помощника и вызовите его с помощью paren(magic(5), 3, :).

4b9b3361

Ответ 1

Вы не должны передавать литерал: функции. Использование двоеточия для индексирования работает только на переменные напрямую (см. здесь и здесь). Двоеточие не является реальным объектом и не имеет типа. Если бы вы использовали его как аргумент функции, он должен был быть типизированным объектом. Конечно, может быть запутанным, что вызовы функций и индексирование переменных имеют одинаковый синтаксис. Но если вы запрашиваете юридический синтаксис для использования аргумента функции двоеточия, его нет.

Тем не менее, тем не менее, он работает в некоторых случаях, как вы заметили. Это связано с некоторыми этапами предварительной обработки MATLAB, и только MathWorks справляется. Похоже, что MATLAB вызывает функцию через subsref-like preocessing, когда вы даете ему три или более аргумента (или два аргумента, оба являются двоеточиями), но не тогда, когда вы даете ему меньше. Идите фигуру. MathWorks избегает давать какие-либо решительные объяснения этому. Я подозреваю, что MATLAB использует строгие двоеточия внутри, применяя subsref, потому что то, что вы видите, когда вы получаете буквальные двоеточия в своей функции, и операции индексирования, похоже, работают так же, как и во всем. Например. попробуйте >> m(3, ':');

Мое предложение для вашего случая использования в основном этот ответ (также упоминается в комментариях к вашему вопросу), но скрывает индексацию в функции с именем paren, как вы предложили, Кроме того, он использует синтаксис столбцов по умолчанию вместо вызова subsref, но он одинаковый в любом случае. Используйте строковые двоеточия!

function result = paren(variable, varargin)

    result = variable(varargin{:});

Затем вызовите что-то вроде:

>> paren(magic(5), 3, ':');

В заключение вы не должны рассчитывать на использование литерала: как аргумент функции в MATLAB, даже если он может работать для особых случаев. Используйте строку двоеточия ':'.

Боковое примечание

Вы можете использовать subsref для вызывающих функций:

>> subsref(@magic, substruct('()', {3}))

Таким образом вы можете связать вызов функции и ссылку:

>> subsref(subsref(@magic, substruct('()', {3})), substruct('()', {':'}))

Но это действительно так же, как использование временной переменной. Внутренний subsref сначала оценивается, и его результат передается в качестве входного аргумента во внешний вызов subsref.

Даже с помощью механизма привязки подстроки вы не можете заставить MATLAB принимать две последующие пары круглых скобок, например magic (3) (:).

>> magic(3)(:)
??? Error: ()-indexing must appear last in an index expression.

>> subs(1) = substruct('()', {3});
>> subs(2) = substruct('()', {':'});
>> subsref(str2func('magic'), subs)
??? Error using ==> subsref
Only a dot field name can follow ()'s.

Ответ 2

writeargs (:) и writeargs (:, 1) обрабатывают writearg как переменную с локальным охватом и пытаются использовать оператор двоеточия для индексации "несуществующей" переменной.

с более чем тремя аргументами, вызываемой функцией... извините, я не понимаю, почему это поведение существует, но я подозреваю, что он неявно вызывает subsref с одним или двумя аргументами, а не с тремя или более.

вы можете протестировать его, поставив точку останова на вызов disp в вашей функции, вы увидите, что он попадает только в том случае, если задано более трех аргументов