具有非标准评估的自定义函数(行为类似于表)

发布于 2024-10-02 06:34:48 字数 934 浏览 1 评论 0原文

我想要一个函数 AnyTrue[expr,{i,{i1,i2,...}}] 来检查 expr 是否为 True 对于任何 i1,i2... 应该就像 AnyTrueTable 后跟 Or@@% ,不同之处在于它只计算 expr 直到找到第一个 True

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

更新 11/14

这是 Michael 提供的解决方案,您可以使用它来链接“for all”和“there isn't”检查

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]]]

I'd like a function AnyTrue[expr,{i,{i1,i2,...}}] which checks if expr is True for any of i1,i2... It should be as if AnyTrue was Table followed by Or@@%, with the difference that it only evaluates expr until first True is found.

Short-circuiting part is optional, what I'd really like to know is the proper way to emulate Table's non-standard evaluation sequence.

Update 11/14

Here's a solution due to Michael, you can use it to chain "for all" and "there exists" checks

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]]]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

执手闯天涯 2024-10-09 06:34:48

这个怎么样?

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< /code> 也是短路的,就其价值而言。 (但我意识到使用例如 Table 构建未评估的术语是一件痛苦的事情):

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

How about this?

SetAttributes[AnyTrue, HoldAll];

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

Includes short-circuiting via LengthWhile and keeps everything held where necessary so that things work as expected with var has a value outside the function:

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

The built-in Or is short-circuiting, too, for what it's worth. (but I realize building up the unevaluated terms with e.g. Table is a pain):

In[173]:= Or[Print[1];True, Print[2];False]
During evaluation of In[173]:= 1
Out[173]= True
温柔戏命师 2024-10-09 06:34:48

这与您的规范不符,但我经常使用以下实用函数,它们与您的想法类似(它们使用纯函数而不是具有指定变量的表达式)并且还进行短路:

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).   *)

例如,Michael Pilat 的例子会变成这样:

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

This doesn't match your spec but I often use the following utility functions, which are similar to what you have in mind (they use pure functions instead of expressions with a specified variable) and also do short-circuiting:

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).   *)

For example, Michael Pilat's example would become this:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文