Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I am running Mathematica 7. The following is admittedly a silly example, but suppose that I have a list list whose entries are either True or False. Suppose that I have some function truthFun[] which evaluates randomly to either True or False. I would like to call truthFun[] and print False until truthFun[] evaluates to True for the first time.

One way to do this is using a For loop. We can exit the loop "early" using Break[]. (As the documentation states, Break[] exits the nearest enclosing Do, For, or While loop.) For example, the following works:

truthFun[] := RandomChoice[{True, False}]

For[i = 1, i <= 10^8, i++,
   If[truthFun[] === False, Print[False], Break[]]];
Print["Finished"]

False

False

Finished

However, it is often recommended that Mathematica users avoid using loops (which are relatively slow in Mathematica, I think). Is it possible to accomplish the above using Table, which is probably faster?

I tried the following, but unfortunately it appears that Break[] does not work with Table:

truthFun[] := RandomChoice[{True, False}]

Table[If[truthFun[] === False, Print[False], Break[]], {i, 1, 10^8}];

False

False

False

Hold[Break[]]

Also, Mathematica gives me this error message:

Break::nofwd: No enclosing For, While, or Do found for Break[].

Is there an analogue to Break in Table? Thanks for your time.

share|improve this question
1  
This would work: Map[Print, First@Split@list] –  Jens Jan 26 '13 at 17:33
3  
If you want to keep the results accumulated by Table so far, have a look at my implementation of abortable table here. It can be easily modified to work with Break or any other custom form of interruption, rather than Abort[]. –  Leonid Shifrin Jan 26 '13 at 18:13
1  
Could use Scan to go over the table, and Return or Throw to exit on condition. If the latter, enclose the Scan in a Catch. –  Daniel Lichtblau Jan 26 '13 at 22:38
1  
Andrew, thanks for the Accept. By the way, I did not state it explicitly in my answer but you can use Return[Null, Table] or the equivalent Return[,Table] to get behavior similar to Break without the syntax error highlighting. –  Mr.Wizard Jan 28 '13 at 18:57

2 Answers 2

up vote 8 down vote accepted

The lightly-documented second argument of Return works:

Table[
 If[i < 3, Print@i, Return["Exit", Table]],
 {i, 100}
]

1

2

"Exit"

Other examples of use: (1), (2)

Additional information:
What can be used as the second argument to Return on your own functions?


Break also accepts a second argument but at least on my system the syntax highlighting is ugly:

Table[
 If[i < 3, Print@i, Break[Null, Table]],
 {i, 100}
]

1

2


Somewhat more standard but IMHO less convenient is Throw and Catch:

Table[
 If[i < 3, Print@i, Throw["Exit", "tableBreak"]],
 {i, 100}
] ~Catch~ "tableBreak"
share|improve this answer
1  
+1 since it answers the question, but I wouldn't do it that way. Except maybe in compiled functions - I wonder if that second arg works with Compile... –  Jens Jan 26 '13 at 18:17
2  
Actually, I wouldn't use it in compiled functions either. Then For and While seems fine. –  Jens Jan 26 '13 at 18:22
2  
@Jens Thanks. I cannot always write a-guide-to-a-better-way answers (though I try) and sometimes the direct answer is more interesting to me. –  Mr.Wizard Jan 26 '13 at 18:22
    
+1 I agree. The particular example in the question might have better solutions, but the Q&A in general is very interesting. –  Ajasja Jan 26 '13 at 18:58
4  
@Jens Return is very dangerous in compiled functions. If you in-line a compiled function with Return into another compiled function, the first Return will exit both. I can find an example if you like... –  Ajasja Jan 26 '13 at 19:01

Clarification: this answer refers to the first the first version of the question, before its entire premise was changed.

So what you're trying to do is take an existing list and then go through its elements until a stopping criterion is reached. But since you already have the list

list={False,False,False,True,False,False};

it's not necessary to construct another Table, just as it's not necessary to use For and Do. Instead, use a function that can select the desired elements of your list according to a criterion you specify. In your case a simple approach is to use Split because it creates lists of "runs" (i.e., contiguous stretches in your input), based on a criterion that specifies what makes the elements of a run equivalent.

Your simple example doesn't even need any test argument for the criterion:

First@Split@list

{False, False, False}

The run stops when the first element is reached that's just different from the others.

Then you want to Print the results (actually, I think the above list is what you'd usually be looking for). If that's required, then you can do it now, after having collected the elements above:

Map[Print, %] 

False

False

False

Edit

In response to the edited question, one could first identify the position of the first element that satisfies the truthFunction, and then extract the part of the list up to that position:

truthFunction[x_] := TrueQ[x]
Most[
 list[[1 ;; First@First[Position[list, _?truthFunction, 1, 1]]
   ]
  ]]

(* ==> {False, False, False} *)

Here I decided to use Position with the fourth argument that says to look for the first occurrence. Since Position requires a search pattern, the truthFunction has to be preceded by _? or PatternTest.

share|improve this answer
    
Thanks for your time. Sorry for being silly. I was trying to make a simple working example, but I failed to include a test function. I have revised my question to reflect this. I would like to evaluate truthFun[] as few times as possible. I am really sorry take up your time. –  Andrew Jan 26 '13 at 17:47

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.