5
$\begingroup$

I need to break my for loop in case of an thrown message and append s to the result list. Breaking the loop works, but my result is empty. I can not use Table[] because it does not support Break[].

EDIT: s has the form of list, so I get a Table structure for result

EDIT 2: AppendTo[] yields empty result too.

result = {};
For[i = 0, i < 6, i++, 
 s = {Quiet[
    Check[If[i == 3, Message[FindRoot::jsing, x, 1], i], "Nan", 
     FindRoot::jsing]]};
 If[s == "Nan", Break[], AppendTo[result, s]];
 ]
result

yields:

{}

Any help appreciated.

$\endgroup$

4 Answers 4

5
$\begingroup$

How about:

result = {};
For[i = 0, i < 6, i++, 
 s = Check[If[i == 3, Message[FindRoot::jsing, x, 1], i], "Nan", 
   FindRoot::jsing];
 Print[s];
 If[s == "Nan", Break[], result = {result, s}];]
Flatten[result]

or

result = {};
For[i = 0, i < 6, i++, 
 s = Check[If[i == 3, Message[FindRoot::jsing, x, 1], i], "Nan", 
   FindRoot::jsing];
 Print[s];
 If[s == "Nan", Break[], AppendTo[result, {s, dim}]];]
result
$\endgroup$
2
  • $\begingroup$ this works for one dimensional form of s but not for lists (edited problem, sorry) $\endgroup$ Apr 19, 2012 at 17:30
  • $\begingroup$ second one has table structure, thank you. $\endgroup$ Apr 19, 2012 at 17:42
16
$\begingroup$

The reason Append[] isn't working in your loop is that it returns a new list with your new element added to the end.

If you want to change the list in place, you should use AppendTo[] instead.

$\endgroup$
10
  • $\begingroup$ thx, now I know why Append in loops is evil! $\endgroup$ Apr 19, 2012 at 17:34
  • 3
    $\begingroup$ @MartinScherer Oh no, the main reason for that (Append being evil in loops) is not it. It is that the full list is copied to append a single element. $\endgroup$ Apr 19, 2012 at 17:35
  • $\begingroup$ calling copy constructors all the time :) $\endgroup$ Apr 19, 2012 at 17:40
  • $\begingroup$ @LeonidShifrin, which suggests an interesting follow-up question. Is AppendTo's implementation equally eager to copy things repeatedly? I can imagine an implementation where the Append version is forced to copy with every operation, but where AppendTo is implemented much like C++'s std::vector and only has to copy some of the time instead of on every step. I just ran some Timings and it looks like their behavior is almost identical. $\endgroup$
    – sblom
    Apr 19, 2012 at 17:48
  • 2
    $\begingroup$ @sblom I noticed that I did not really answer your question. The answer is yes, AppendTo is just as bad in this regard as Append. Moreover, you can see that AppendTo has been actually implemented with Set and Append, by using On[Set], and then say a = Range[5]; AppendTo[a, 6]. $\endgroup$ Apr 19, 2012 at 19:31
4
$\begingroup$

You may not be able to use Table with Break[] but you can use Do:

Break[]
    exits the nearest enclosing Do, For or While.

I also prefer Sow and Reap for speed and flexibility.

Reap[
  Do[
    s = Check[If[i == 3, Message[FindRoot::jsing, x, 1], i], "Nan", FindRoot::jsing];
    If[s == "Nan", Break[], Sow@s],
    {i, 0, 5}
  ]
][[2, 1]]
{0, 1, 2}
$\endgroup$
2
$\begingroup$

In an effort to "say no to loops", here is an alternative that substitutes For and Break with Fold and a Throw/Catch construct. There might be another alternative using FoldList and fewer uses of Flatten, but it's late at night here and I wasn't able to get that quite working. This works:

Catch@Fold[
  With[{chk = 
      Check[If[#2 == 3, Message[FindRoot::jsing, x, 1], #2], "Nan", 
       FindRoot::jsing]},
    If[chk == "Nan", Throw[Flatten@{#1, #2}], 
     Flatten@{#1, chk}]] &, {}, Range[6] ]

FindRoot::jsing: Encountered a singular Jacobian at the point x = 1. Try perturbing the initial point(s). >>

{1, 2, 3}

I think approaches such as this are preferable to For loops, since the latter tends to result in iterator variables (in this case, i) that remain globally defined, which is probably not what you want.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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