RE: Early out with Map?

• To: mathgroup at smc.vnet.net
• Subject: [mg16044] RE: [mg16036] Early out with Map?
• From: "Ersek, Ted R" <ErsekTR at navair.navy.mil>
• Date: Sun, 21 Feb 1999 00:15:19 -0500
• Sender: owner-wri-mathgroup at wolfram.com

```Oscar Stiffelman wrote:
__________________________

Is it possible to interrupt Map before it reaches then end of the list?

For example, how would I convert the following from procedural to
functional?

(* This is the procedural version *)
foundSolution = False;
For[i =1, i <= numChildren && ! foundSolution, i++,
If[testChild[children[[i]]],
foundSolution = True;
];
];
foundSolution

____________________

This is a great place to use Throw and Catch (a complementary pair that took
a long time for me to grasp).  You didn't indicate what you are using for
children, numChildren, and testChild.  I will use the definitions below.

In[1]:=
children={2,3,-4,3,7,-2,4,-5,1,3,-6,1};
numChildren=Length[children];
testChild[a_]:=a<0

____________________
Then your procedural version returns True since children contains negative
numbers.

In[4]:=
(* This is the procedural version *)
foundSolution = False;
For[i =1, i <= numChildren && ! foundSolution, i++,
If[testChild[children[[i]]],
foundSolution = True;
];
];
foundSolution

Out[7]=
True

____________________
Below I show how Throw and Catch can be used to make Map quit early.

In[8]:=
children1={2,3,4,3,7,2,4,5,1,3,6,1};
children2={2,3,-4,3,7,-2,4,-5,1,3,-6,1};

In[10]:=
Catch[
Map[If[Negative[#],Throw[True]]&,children1];
False
]

Out[10]=
False

In[11]:=
Catch[
Map[If[Negative[#],Throw[True]]&,children2];
False
]

Out[11]=
True

____________________

But I think simplest solution uses Select.

In[12]:=
?Select
"Select[list, crit] picks out all elements ei of list for which crit[ei] is
True. Select[list, crit, n] picks out the first n elements for which
crit[ei] is True."

In[13]:=
Select[children1,Negative,1]
Out[13]=
{}

In[14]:=
Select[children2,Negative,1]
Out[14]=
{-4}

But you don't want the one that passed the test.  You want True or False, so
I compare the result to {} in the next line.

In[15]:=
Select[children2,Negative,1]=!={}
Out[15]=
True
______________________

Look-up Cases in the Help Browser and you will see
Cases[expr, pattern, levspec, n] gives the first (n) parts in expr which
match the pattern.  If anyone wants a discussion of 'levelspec' let me know.

In the lines below I do the same with Cases.

In[16]:=
Cases[children1,_?Negative,1,1]
Out[16]=
{}

In[17]:=
Cases[children2,_?Negative,1,1]
Out[17]=
{-4}

In[18]:=
Cases[children2,_?Negative,1,1]=!={}
Out[18]=
True

_______________________

Cases is a very powerful feature because:

- Pattern matching is VERY versatile.

- 'pattern' can be (pattern->expr)
or (pattern:>expr).

- Levelspec gives a wealth of possibilities.

- As with all functional programming in Mathematica
Cases works with any expression (not only lists).
_____________________

But as I recently warned, be wary of (pattern->expr).
If (pattern) has a name (e.g.   n_?Negative) and the pattern name is used in
(expr) then you get the wrong result if (n) has a global value.