2
$\begingroup$

I'm trying to use the form

b = {...}, While[test[b], body]

but do not get any results. My code is:

b = {1, 1, 1}; While[b < {4, 4, 4}, Print[b]; b++]

It is the right way to proceed?

$\endgroup$
  • 1
    $\begingroup$ what are you trying to achieve exactly? Lists cannot be compared that way, but you could for example compare their first elements, given that in your code all elements of b are always the same. For example with something like b = {1, 1, 1}; While[First[b] < 4, Print[b]; b++] $\endgroup$ – glS Aug 23 '16 at 11:06
  • 1
    $\begingroup$ Your test within the While must evaluate to True for the loop to proceed. {1,1,1} < {4,4,4} doesn't return True, it doesn't run, why should it, what should the results be? Perhaps you want to test And @@ Thread[b < {4, 4, 4}] $\endgroup$ – Quantum_Oli Aug 23 '16 at 11:07
  • 1
    $\begingroup$ You are performing operations on lists like they are variables. $\endgroup$ – Feyre Aug 23 '16 at 11:58
11
$\begingroup$

Trying to guess at what may be confusing to a beginner about Mathematica, the following may be helpful:

In many other languages if you call a function it either stops with an error or returns with a result. Due to the symbolic nature of Mathematica, some things simply do not evaluate instead of showing an error.

1 < 2
(* True *)

2 < 1
(* False *)

x < 2
(* x < 2 *)

The last one is in fact just a symbolic way to represent an inequality (it is not an error!)

While expects its first argument to evaluate either to True or False. It treats everything else as False.

Some languages allow array comparisons. Mathematica doesn't. {1,1,1} < {4,4,4} will not evaluate, as you can (and should) test.

To do element-wise comparison, use Thread.

Thread[{1, 2, 3} < {2, 2, 2}]
(* {True, False, False} *)

Use And and Apply to test that element of a boolean list are True:

And @@ Thread[{1, 2, 3} < {2, 2, 2}]

As you can see, Mathematica is different. It is a good idea to go through a proper tutorial when you start out:

$\endgroup$
4
$\begingroup$

Assuming you are trying to pick the elements < 4 from a list, here are several ways to do it.

Procedural

Module[{r = {}, i = 0, n = Length[b]},
  While[i < n, If[b[[++i]] < 4, AppendTo[r, b[[i]]]]];
  r]

This is the most bug-prone and inefficient of all the methods presented in this answer.

Quasi-procedural

Table[If[b[[i]] < 4, b[[i]], Nothing], {i, Length[b]}]

Functional

If[# < 4, #, Nothing] & /@ b

or

Pick[b, Thread[b < 4]]

This last one is probably best, since Pick is optimized for this kind of problem.


With

SeedRandom[2]; b = RandomInteger[{1, 6}, 10]

{6, 2, 3, 3, 6, 3, 2, 6, 6, 1}

all of the above methods give the result

{2, 3, 3, 3, 2, 1}

$\endgroup$

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