each[i_, {1,2,3},
Print[i]
]
或者,更一般来说,要破坏您所循环列表中的任意内容,如:
each[{i_, j_}, {{1,10}, {2,20}, {3,30}},
Print[i*j]
]
通常你想使用Map或其他纯功能的结构,并避开使用副作用的非功能性编程风格。但是这里有一个例子,我认为一个for-each结构是非常有用的:
说我有一个选项(规则)的列表,将符号与表达式配对,如
attrVals = {a -> 7, b -> 8, c -> 9}
现在我想制作一个哈希表,我做这些符号到这些数字的明显映射。我不认为这样做比较干净
each[a_ -> v_, attrVals, h[a] = v]
附加测试用例
在这个例子中,我们转换变量列表:
a = 1;
b = 2;
c = 3;
each[i_, {a,b,c}, i = f[i]]
之后,{a,b,c}应该评估为{f [1],f [2],f [3]}。请注意,这意味着“每个”的第二个参数如果是列表,应该保持不受影响。
如果未评估的表单不是列表,则应评估第二个参数。例如:
each[i_, Rest[{a,b,c}], Print[i]]
那应该打印b和c的值。
附录:为了适当的做法,它应该支持Break []和Continue []。我不知道如何实现。也许它需要以某种方式被实现为For,While或Do,因为这些是唯一支持Break []和Continue []的循环结构。
还有另一个问题,答案到目前为止:他们吃了Return [] s。也就是说,如果您在函数中使用ForEach循环,并希望从循环中的函数返回,则不能。在ForEach循环中发出返回似乎像Continue []工作。这只是(等待它)扔我一个循环。
Do[
Print[i],
{i, {1, 2, 3}}]
就像你一样
ForEach[i_, {1, 2, 3,},
Print[i]]
替代地,如果你真的喜欢特定的ForEach语法,你可以创建一个实现它的HoldAll函数,像这样:
Attributes[ForEach] = {HoldAll};
ForEach[var_Symbol, list_, expr_] :=
ReleaseHold[
Hold[
Scan[
Block[{var = #},
expr] &,
list]]];
ForEach[vars : {__Symbol}, list_, expr_] :=
ReleaseHold[
Hold[
Scan[
Block[vars,
vars = #;
expr] &,
list]]];
这将使用符号作为变量名,而不是模式,但是这些内置的控件结构如Do []和For []的工作原理。
HoldAll []功能允许您组合各种各样的自定义控件结构。 ReleaseHold [Hold […]]通常是组装一堆Mathematica代码以便稍后评估的最简单的方法,Block [{x =#},…]允许您的表达式主体中的变量绑定到所需的任何值。
为了回应下面的dreeves的问题,您可以修改此方法,以允许使用唯一符号的DownValues进行更多的任意解构。
ForEach[patt_, list_, expr_] :=
ReleaseHold[Hold[
Module[{f},
f[patt] := expr;
Scan[f, list]]]]
在这一点上,我认为你可能会更好地在案件之外建立一些东西。
ForEach[patt_, list_, expr_] :=
With[{bound = list},
ReleaseHold[Hold[
Cases[bound,
patt :> expr];
Null]]]
当我抑制函数的返回值时,我喜欢使Null显式。编辑:我修正了下面指出的bug;我总是喜欢使用With来将评估的表达式插入到Hold *表单中。
相关文章
转载注明原文:循环 – 在数学中的ForEach循环 - 代码日志