图片缩略图

函数式编程构造

version 1.2.0.1 (52.2 KB) by 麦克卢尔塔克
一组文件,用于将“if”、“for”甚至“()”等操作作为函数处理。
5.0
11评级

3下载

更新2016年9月01日

视图版本历史

查看许可协议

编者按:这个文件被选为MATLAB中心本周精选

这组文件可以更容易地使用函数的函数来编写简洁而强大的代码。
以下是这种工作方式的一些亮点:

*将多个输入映射到多个函数,并使用单行分配多个输出。

*在匿名函数中使用条件句(如"if")、循环和递归。

还包括一个带有这些函数的派生和示例的文档。看到固定。此外,每个函数都包含一个带有示例的“帮助”条目。

此提交要求对函数句柄和匿名函数非常熟悉。如果这些术语不熟悉,请先查看文档!

引用作为

塔克麦克卢尔(2021)。函数式编程构造(//www.tatmou.com/matlabcentral/fileexchange/39735-functional-programming-constructs), MATLAB中央文件交换。检索

意见及评分(25)

麦克卢尔塔克

谢谢你指出了一个重要的主题,约翰!

约翰。史密斯

约翰。史密斯

好吧,我的错——无视之前的帖子。
刚刚RTFM'ed和发现这已经被支持:金宝app
%考虑编写一个匿名函数来安全地规范化x。
% safe_normalize = @ (x) iif(所有(x = = 0), @ () x,…
% true, @() x/根号(sum(x.^2)));

%避免在确定之前计算“所有”可能的条件
%操作执行时,条件可以表示为匿名函数
%执行。这些将按顺序执行,直到条件返回
%为真。这里与上面的例子相同,只是添加了“@()”
%在每个条件之前阻止其执行,直到需要时才执行(和)
%在不需要的时候跳过它)。

就像我说的——恐怖的屈服!

约翰。史密斯

神奇的提交!
我在使用iif()时遇到的一个问题是,它不像if那样使用惰性计算。因此,您不能传入即使不满足条件也会抛出错误的子句。例如,假设你想评估:
如果isempty (x), 0;否则,x + 5;结束
这与iif()不工作,因为Matlab抛出一个错误,如果x是空的,因为它试图计算x + 5。
为了解决这个问题,可以在子句中使用匿名函数,Matlab在需要时才计算。但是,您需要能够将参数传递给这些函数。
这是我最后得到的结果:
iif = @(变长度输入宗量)变长度输入宗量{(找到([变长度输入宗量{1:3:结束}],1,'第一次')1)* 3 + 2}…
(变长度输入宗量{(找到([变长度输入宗量{1:3:结束}],1,'第一次')1)* 3 + 3}{:});

一个用法示例是:
if(ifcond1, @(p1) clause1(p1), {x},…
Elseifcond2, @(p1,p2)子句2(p1,p2), {x,y},…
elseifcond3 @ (p1, p2, p3) clause3 (p1, p2, p3), {x, y, z},……
True, @(p1) elsecause (p1), {x});

希望这个有帮助。
欢迎评论/改进。

朱塞佩•卡斯卡里诺

圭多Previde Massara

神奇的提交!

麦克卢尔塔克

谢谢你的笔记,约翰·史密斯。是的,using:本身在13a和15b之间停止工作,可能是包含了新的MATLAB执行引擎(当MATLAB突然变得更快时)。冒号现在应该用作字符串,如':'。

另外,'end'不能用作输入;这对于MATLAB来说太低级了。相反,您必须使用length(…)或size(…)。

希望这可以帮助!

约翰。史密斯

你怎样用圆括号完成工作?
例如,括号((1,10),end-3:结束)给出:
输入参数不足。
括号错误(第34行)
= x(变长度输入宗量{:});

检查后,瓦拉金是空的。

约翰。史密斯

如果我不引用:(正如David所建议的),我将得到未定义的函数或变量' pareen '。这是在Matlab R2015b上

麦克卢尔塔克

嗨,David, Joerg,

谢谢你的反馈。这些都是很好的建议。下次我更新代码库时,这些会在里面。

——塔克

大卫Szwer

非常棒的函数,这应该是Matlab的一部分。

我建议使用以下技巧更新“paren”的文档。可以使用引号或不使用引号指定冒号操作符
(如括号(魔法(3)2:)和括号(魔法(3)2 ':')
是相同的)。但是,如果使用引号,也可以使用':'进行线性索引
(例如:paren(magic(3), ':'))
但如果没有引号,这是不行的。

我很想知道Matlab认为不带引号的冒号实际上是什么,以及为什么它有时不工作。

Joerg

你好,塔克

非常感谢你的代码。如果允许一个可选参数,"output"函数会更灵活:

函数varargout = output(f, out_indices, varargin)

(细节{1:马克斯(out_indices)}] = f(变长度输入宗量{:});

varargout =出局(out_indices);

费利佩•g . Nievinski

我想应该不是单独的。M函数这可以是原始iif的一个补丁。m(向后兼容的):

Isodd = @(x)逻辑(mod(x,2));
如果isodd(元素个数(变长度输入宗量))
Varargin (end:end+1) = [{true}, Varargin (end)];
结束

费利佩•g . Nievinski

%内联if-else(一般内联if-elseif的特殊情况):
%(省略了将true作为倒数第二个输入参数)
函数varargout = iiff(varargin)
Varargin (end:end+1) = [{true}, Varargin (end)];
[varargout {1: nargout}] = iif(变长度输入宗量{:});
结束

菲利普

输出。M可以重复使用包装。米,看来:
函数varargout = output(f, out_indices)
Varargout = wrap(f, out_indices);
结束

菲利普

谢谢你花时间发表评论,塔克。

麦克卢尔塔克

嗨,菲利普,

你提出了一个很好的观点。没有办法调整|花括号|,以便它将单元格数组的所有内容作为参数展开到一个函数中(或者至少我还没有想出一个好的方法),因为这是由MATLAB处理的,它只寻找|f(x{:})|的形式。因为|f(curly(x, ':'))|不适合这种形式,所以它不能工作(调用|curly(x, ':')|只会在直接传递给函数时返回第一个输出。

然而,仍然有一些方法可以完成想要的事情,比如使用|use|命令;它们只是不涉及使用|卷曲的|。例如,如果|f|返回一个单元格数组,我们想调用|f|,将其单元格数组输出中的所有项展开为一个新函数|g|,像这样:

>> g(f(){:}) % <-生成语法错误

我们可以这样做:

使用(f(), @(x) g(x{:}));

这表示,“运行f()并将其输出传递给下一个参数,这是一个函数句柄。这个函数现在可以使用输出(这里我们称之为|x|)。”因为|使用|允许用户运行命令并多次“使用”其输出,而不需要将其保存为变量,所以|在复杂的匿名函数中非常有用。

如果这是一个常见的模式,你还可以定义:

>> expand_into_fcn = @(f, x) f(x{:});

现在我们可以用这个展开函数来模拟MATLAB的操作。例如,将|f|返回的单元格数组中的所有元素展开到|cat|函数中,它非常紧凑:

> > expand_into_fcn (@cat f ())

这和:

>> x = f();
> >猫(x {:})

让我们更进一步。让我们从一个函数中获取多个输出,并将它们传递给一个新函数。我们得好好收拾一下。我们将从|min([5 2 3])中获取两个输出|,|将|封装到一个单元格数组中,并将该数组扩展到|cat|函数中,以沿维度1连接它们。

> >使用(包装(@()分钟([5 2 3]),1:2),@ (x)猫(1,x {:}))
ans =
2
2

希望这可以帮助!

菲利普

我想知道是否有可能调和卷曲的行为。M函数与内置的{}函数在本例中:
X = {'a' 'b'}, {X {:}}, {curly(X,':')}
x =
“a”“b”
ans =
“a”“b”
ans =
“一个”
我不认为这是卷毛的问题。M,因为这些匿名函数也表现出同样的不和:
Curlycolon = @(x) x{:};{curlycolon (x)}
ans =
“一个”
curlycolon = @ (x) subsref (x, substruct ('{}',{':'}));{curlycolon (x)}
ans =
“一个”
I似乎是冒号操作符的一个特异性;从doc冒号:“冒号符号可以与单元格数组一起使用,以产生一个逗号分隔的列表. ...逗号分隔的列表语法是有效的inside()用于函数调用,[]用于连接和函数返回参数,以及inside{}用于生成单元格数组。

我在定义这个函数时遇到了这个问题:
使用(num2cell(subvecnum), @(subveccell) sub2ind(siz, subveccell{:}));
Subvec2ind ([5 5 5], [1 2 3])
Sub2ind ([5 5 5], 1,2,3)

na任

它是有帮助的!

麦克卢尔塔克

嘿,谢谢大家的好反馈。我感谢你花时间留下一个评级!

费利佩•g . Nievinski

YONGSUNG

埃里克·桑普森

塔克伟大的工作!:)

伊恩

这是一个很好的介绍Matlab函数式编程,谢谢Tucker!!

马太福音

MATLAB版本兼容性
创建R2012b
与任何版本兼容
平台的兼容性
窗户 macOS Linux

社区寻宝

在MATLAB中心找到宝藏,并发现社区如何可以帮助你!

开始狩猎!