2010-11-15 27 views
3

我想的功能AnyTrue[expr,{i,{i1,i2,...}}]其中检查是否exprTrue任何的i1,i2...它应该是仿佛AnyTrue其次[email protected]@%Table,不同之处在于它只有评估expr,直到找到第一个True自定义函数(行为类似于表)

短路部分是可选的,我真的很想知道的是正确的方法来模拟Table的非标准评估序列。

更新11/14

这里有一个解决方案,由于迈克尔,你可以用它来链“所有”和“存在”检查

SetAttributes[AllTrue, HoldAll]; 
SetAttributes[AnyTrue, HoldAll]; 
AllTrue[{var_Symbol, lis_List}, expr_] := 
    LengthWhile[lis, 
    TrueQ[ReleaseHold[Hold[expr] /. HoldPattern[var] -> #]] &] == 
    Length[lis]; 
AnyTrue[{var_Symbol, lis_List}, expr_] := 
    LengthWhile[lis, 
    Not[TrueQ[ReleaseHold[Hold[expr] /. HoldPattern[var] -> #]]] &] < 
    Length[lis]; 
AllTrue[{a, {1, 3, 5}}, AnyTrue[{b, {2, 4, 5}}, EvenQ[a + b]]] 
AnyTrue[{a, {1, 3, 5}}, AllTrue[{b, {2, 4, 5}}, EvenQ[a + b]]] 

回答

5

这个怎么样?

SetAttributes[AnyTrue, HoldAll]; 

AnyTrue[expr_, {var_Symbol, lis_List}] := 
    LengthWhile[lis, 
    Not[TrueQ[ReleaseHold[Hold[expr] /. HoldPattern[var] -> #]]] & 
    ] < Length[lis] 

通过LengthWhile包括短路,并且一直保持在必要的一切,让事情按预期工作与var所具有的功能之外的值:

In[161]:= x = 777; 

In[162]:= AnyTrue[Print["x=", x]; x == 3, {x, {1, 2, 3, 4, 5}}] 
During evaluation of In[162]:= x=1 
During evaluation of In[162]:= x=2  
During evaluation of In[162]:= x=3 
Out[162]= True 

内置Or是短路也是值得的。 (但我意识到建立未计算的条款如与Table是一种痛苦):

In[173]:= Or[Print[1];True, Print[2];False] 
During evaluation of In[173]:= 1 
Out[173]= True 
+0

烨,工程perfe ct – 2010-11-15 07:31:31

+1

迟到了,我只想指出参数模式中的过多细节通常不适合Hold特性。例如,以下调用失败:AnyTrue [i <10,{i,Range [5]}],原则上它不应该(模式不匹配,因为在模式匹配时它不知道Range [ 5]是List)。这个稍微更一般的签名将会消除这个问题:AnyTrue [expr_,{var_Symbol,lis_}]。此外,AnyTrue不能在M8的打包列表中工作 - 长度似乎存在一个错误:LengthWhile [Range [5],! TrueQ [#<10]&]给出5,我要报告它。 – 2011-01-13 02:15:37

+0

是的,好点的狮子座。在评估它之后,有一个更一般的模式并验证论点会更好。 'HoldAll'而不是'HoldFirst'是必要的,因为我们希望除'expr'之外还保留'var',否则就不会有更挑剔的模式出现问题。 – 2011-01-13 02:22:51

4

这不符合你的天赋,但我经常使用下面的效用函数,这类似于你心里有什么(他们使用纯函数,而不是与指定变量表达式),也做短路:

some[f_, l_List] := True ===    (* Whether f applied to some  *) 
    Scan[If[f[#], Return[True]]&, l];   (* element of list is True.  *) 

every[f_, l_List] := Null ===    (* Similarly, And @@ f/@l   *) 
    Scan[If[!f[#], Return[False]]&, l];  (* (but with lazy evaluation). *) 

例如,迈克尔·派拉特的例子就是成为这个:

In[1]:= some[(Print["x=", #]; # == 3)&, {1, 2, 3, 4, 5}] 

    During evaluation of In[1]:= x=1 
    During evaluation of In[1]:= x=2  
    During evaluation of In[1]:= x=3 
Out[1]= True 
+1

有用的技巧。请注意,使用“If”而不是“TrueQ”需要更多注意句法,即'every [False,{a,{1,3,5}}]'给出“True” – 2010-11-18 09:15:59

+0

你让我担心起初,但我认为这里没有错误。请注意,第一个参数需要是一个函数。 “每一个[False&,{1,3,5}]'都按预期工作。 – dreeves 2010-11-18 09:31:18

+0

正确,没有错误,只是一种微妙的语义差异,因为如果f对列表中的每个元素都评估为“False以外的东西”,它就是“真” – 2010-11-18 09:43:33