循环 – 在数学中的ForEach循环

我想要这样的东西:

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 []工作。这只是(等待它)扔我一个循环。

最佳答案
Mathematica(6.0)的较新版本通过采用迭代器参数的替代形式,将Do []和Table []的一般化版本几乎完全符合您的要求。例如,

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循环 - 代码日志