пользовательская функция с нестандартной оценкой (ведет себя как таблица) - PullRequest
3 голосов
/ 15 ноября 2010

Я бы хотел функцию AnyTrue[expr,{i,{i1,i2,...}}], которая проверяет, является ли expr True для любого из i1,i2.... Это должно быть, как если бы AnyTrue было Table, за которым следует Or@@%, с той разницей он оценивает только 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]]]

Ответы [ 2 ]

5 голосов
/ 15 ноября 2010

Как насчет этого?

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
4 голосов
/ 18 ноября 2010

Это не соответствует вашей спецификации, но я часто использую следующие служебные функции, которые похожи на те, которые вы имеете в виду (они используют чистые функции вместо выражений с указанной переменной), а также делают короткие замыкания:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...