2016-09-21 20 views
3

我在MathWorks公司博客关于MATLAB函数式编程阅读this article,以及两个辅助功能有:实施“花”和“访问”“链接”功能的MATLAB

paren = @(x, varargin) x(varargin{:}); 
curly = @(x, varargin) x{varargin{:}}; 

明显的第三个完成三重奏(并与五个字母的主题保持一致)是:

acces = @(x, field) x.(field); 

把它是否是实现这种方式还是不能在MATLAB一边(注意链是一个好主意的讨论:八度支持链接默认),paren如预期的那样似乎运作良好;然而,curlyacces有一个主要缺点;考虑下面的代码:

>> C = {1,2,3,4; 2,3,4,5; 3,4,5,6; 4,5,6,7}; 
>> A = [curly(C, 3, ':')] 
A = 
    3 

即预期序列代并没有发生。
(注意,此代码将按预期在八度,即A = [3,4,5,6]

同样,acces不会在MATLAB产生序列

>> S = [struct('name', 'john'), struct('name', 'jim')]; 
>> A = {acces(S, 'name')} 
A = 
    'john' 

(而倍频产生预期A = {'john', 'jim'}

我了解这种差异可能更多的是在执行方面的问题a。函数如何返回matlab vs octave中的内容,和/或b。如何从两种语言的单元格和结构中生成序列。

但是,有没有一种程序化的方式来让matlab执行上面的预期操作?
换句话说,有没有一种方法可以定义curlyacces函数返回一个序列(额外奖金为匿名函数:p)像八度呢?


PS。我正在寻找的答案不是微不足道的 “获取多个参数使用可变参数”之一。
PS2。 我在Matlab 2013b上测试了这个,所以我不知道这个行为是否已经在后来的版本中“固定”(尽管我非常怀疑它)。http://matlab.mathworks.com

回答

4

声明在测试了最新的MATLAB在线:回答的更小,更有些随意沉思的

这里的问题是,在MATLAB,单一的功能(匿名或其他)是无能的以点引用和索引方式返回逗号分隔列表。

即使MATLAB对执行引用内部功能是不能这样做的:

subsref(S, substruct('.', 'name')) 
% john 

builtin('_dot', S, 'name')    % Only works pre-2015b 
% jim 

subsref(C, substruct('{}', {3 ':'})) 
% 3 

builtin('_brace', C, 3, ':')   % Only works pre-2015b 
% 3 

什么功能单一可以在MATLAB做的,就是返回多个输出。这正是如何subsref和其他内建返回你希望多值

S = struct('name', {'john', 'jim'}); 

[val1, val2] = subsref(S, substruct('.', 'name')); 
[val1, val2] = builtin('_dot', S, 'name'); 

C = num2cell(magic(3)); 

[val1, val2, val3] = subsref(C, substruct('{}', {3, ':'})); 
[val1, val2, val3] = builtin('_brace', C, 3, ':'); 

现在,这并不能真正帮助你的助手匿名函数,因为它需要多少产出预期和知识这又取决于投入。

为了您acces功能,它是相对简单的,确定输出的数量,所以你可以很容易地做一些事情,如:

[A{1:numel(S)}] = acces(S, 'name'); 

不幸的是,你不能做的匿名函数里面,并有也没有简单的方法来从后续调用这个包裹得到一个非单元阵列出拆开来cell2mat

[A{1:numel(S)}] = acces(S, 'name'); 
A = cell2mat(A); 

可以创造一些anonymo我们的功能是做这些不同的操作,但是它们很混乱。

access_cell = @(s,n)arrayfun(@(x)acces(x,n), s, 'uniform', 0); 
access_array = @(s,n)arrayfun(@(x)acces(x,n), s, 'uniform', 1); 

至于你curly你也可以使用paren通过它来抓取单元阵列作为细胞的一个子集,然后循环使用cellfun产生的结果。

% This is really just using parenthesis 
curly_sequence_cell = paren; 

curly_sequence_array = @(varargin)cell2mat(paren(varargin{:})); 

真正解决方案只需使用一个临时变量,然后索引,使用MATLAB典型语法:)

S = struct('name', {'john', 'jim'}); 
A = {S.name}; 
+0

我不知道“_dot”和“_brace” ,知道这很酷! 也谢谢你纠正我的结构语法,我没有费心查找它,哈哈。尽管我猜想,很好的解决方法会使可读性比'paren'和'curly'更糟糕,这已经足够令人质疑了......在matlab中没有办法避免那个血腥的临时变量,是否存在:p –

+0

still,I不知道matlab如何从引擎盖下的单元/结构创建序列,以便它在直接调用时工作,但不在用subsref调用时工作。当我尝试使用subsref并且它不工作时,我感到非常惊讶...直到那时,我的印象是()和{}索引只是subsref的语法糖......(例如,在octave,subsref,按预期工作并返回一个序列) –

+1

@TasosPapastylianou通过'subsref'做了更多的探索,并在我的答案中添加了一些信息。虽然你可以强制使用'subsref'来给你所有的值,但是仍然不容易得到逗号分隔列表。 – Suever