1

I am initializing a table inside a function as follows:

f[a1_, a2_, a3_] := Module[{RM = Table[a1+a2+a3+i1, {i1, 1, 10}]}, Plus@@RM]

I am calling the function f multiple times with different values of a1, a2, a3 and want the function to exit, if 300<a1+a2+a3+i1<500

How can I do it elegantly by not initializing the table and later checking to proceed or Break?

This is what I have started to do, but could not go too far:

LL[a1_, a2_, a3_, x_] := 300 < a1+a2+a3+i1 < 500;
f[a1_, a2_, a3_] := Module[{RM = Table[If[L[a1, a2, a3, i1]==True,L[a1, a2, a3, i1],
        Break[]] , {i1, 1, 10}]},Plus@@RM]
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
brama
  • 898
  • 5
  • 18

3 Answers3

3
f[a1_, a2_, a3_] /; (IntervalIntersection[Interval[{300, 500}], 
     Interval[a1 + a2 + a3 + {1, 10}]] === Interval[]) := 
 Module[{RM = Table[a1 + a2 + a3 + i1, {i1, 1, 10}]}, Plus@@ RM]

Is probably the most direct way to accomplish this. Called with non-satisfying values, it simply returns unevaluated.

ciao
  • 25,774
  • 2
  • 58
  • 139
  • Thanks, but the condition has the cell index i1 as 300<a1+a2+a3+i1<500. This is a simplified condition, but the original condition is much more complex – brama Apr 15 '14 at 18:15
  • @brama: Ah, missed that in OP. Will adjust or delete, give me a moment... – ciao Apr 15 '14 at 18:17
  • @brama: OK - I think this does what you've asked for (completely misread OP first time). This only returns if no value of a1+a2+a3+i1 is in the range of 300 to 500. Frankly, I think it more convoluted than your idea of just adding an If to your function definition... – ciao Apr 15 '14 at 18:49
  • +1 for answering the question as written, but I'm guessing that brama cannot test only the end-points of the Table iterator. – Mr.Wizard Apr 15 '14 at 19:46
  • @Mr.Wizard - yes, I think perhaps a clarification of the "much more complex" condition in the OP is warranted. Thanks much for +... – ciao Apr 15 '14 at 19:48
3

I think your own method can be refined into something useful:

f1[a1_, a2_, a3_] := Module[{test, RM},
  test = If[300 < # < 500, #, Return[{}, Module]] &;
  RM = Table[test[a1 + a2 + a3 + i1], {i1, 1, 10}];
  Total @ RM
 ]

Now:

f1[100, 101, 102]
f1[1, 2, 3]
f1[100, 195, 200]
3085

{}

{}

Note that I used a special syntax of Return to exit without error. I am assuming that you cannot simply test the end points of your Table range, but rather need to test every value generated by some function. Otherwise use a condition as rasher did, in one formulation or another.

If you want the function to return unevaluated you can achieve it with two small modifications:

f2[a1_, a2_, a3_] := Module[{test, RM},
  test = If[300 < # < 500, #, Return[{}, Table]] &;
  RM = Table[test[a1 + a2 + a3 + i1], {i1, 1, 10}];
  Total @ RM /; RM =!= {}
 ]

f2[100, 101, 102]
f2[1, 2, 3]
f2[100, 195, 200]
3085

f2[1, 2, 3]

f2[100, 195, 200]

Note that Return is changed to exit from Table rather than the entire Module. Then a special form of Condition is used. See: Using a PatternTest versus a Condition for pattern matching

If failure to match is an uncommon event it is better to write the function to be faster in the common case where it does not exit or return unevaluated. For that you would leave the test until after the Table is generated, e.g.:

f3[a1_, a2_, a3_] := Module[{RM},
  RM = Table[a1 + a2 + a3 + i1, {i1, 1, 10}];
  Total @ RM /; 300 < Min[RM] && Max[RM] < 500
 ]

Speed comparison within a matching range:

Table[
 Do[fn[100, 100, x], {x, 100, 280, 0.01}] // Timing // First,
 {fn, {f1, f2, f3}}
]
{0.374, 0.375, 0.249}
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
0

You can not "break" from a table like that, try something like this:

     i=0;
     First@Last@Reap[While[++i; !(300<a1+a2+a3+i1<500) && i<=10, Sow[result] ] 

(your condition and result are a bit vague in your question by the way.)

Also I'm assuming you want to keep the values computed up to the exit condition.

If you wanted to just discard everything then you can do:

    Catch[Table[ If[!condition, Throw[{}], value], {i, 10}]]
george2079
  • 38,913
  • 1
  • 43
  • 110