我什么时候可以传递一个文字:一个函数?

时间:2013-03-28 15:21:04

标签: matlab syntax slice

在什么情况下我可以将文字:传递给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代码中,我遇到了将切片对象传递给方法的情况。一个用例是针对一个函数,例如灵感来自this answer,其中一个小函数用于绕过Matlabs无法解释magic(5)(3, :),并且可以编写一个辅助函数并用{{1}调用它}。

2 个答案:

答案 0 :(得分:2)

你不应该将文字传递给一个函数。冒号用于索引仅用于直接处理变量(请参阅herehere)。冒号不是真正的对象,没有类型。如果你想将它用作函数参数,它需要是一个类型化的对象。当然,函数调用和变量索引具有相同的语法可能会令人困惑。但是如果你要求使用冒号作为函数参数的合法语法,则没有。

话虽如此,但正如你所观察到的那样,它在某些情况下仍有效。这是由于MATLAB采取的一些预处理步骤,并且只有MathWorks可以处理。当你给它三个或更多个参数(或者两个参数,都是冒号)时,MATLAB似乎通过类似subsref的预处理来调用函数,但是当你给它少于它时,它就不会。去搞清楚。 MathWorks将避免给出任何决定性的解释。我怀疑,MATLAB在应用subsref之后在内部使用了字符串化的冒号,因为这是你在函数中接收文字冒号时所看到的,并且索引操作似乎贯穿始终。例如。试试>> m(3, ':');

我对您的用例的建议基本上是this answer(也在您的问题的评论中引用)但是隐藏了一个名为paren的函数的索引,如您所建议的那样。此外,它使用默认的括号语法而不是调用subsref,但it's the same anyway。使用字符串冒号!

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调用。

即使使用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.

答案 1 :(得分:1)

writeargs(:)和writeargs(:,1)将writeargs视为本地范围的变量,并尝试使用冒号运算符来索引“不存在的”变量。

有三个以上的参数正在调用该函数...抱歉我不明白为什么会出现这种行为,但我怀疑它隐含地使用一个或两个参数调用subsref,而不是三个或更多。

你可以通过在你的函数中的disp调用上设置一个断点来测试它,只有当给出三个以上的参数时才会看到它被击中