Re: Challenge!

• To: mathgroup at christensen.cybernetics.net
• Subject: [mg998] Re: Challenge!
• From: villegas (Robert Villegas)
• Date: Mon, 8 May 1995 04:08:24 -0400
• Organization: Wolfram Research, Inc.

```jorma.virtamo at vtt.fi (Jorma Virtamo) writes:

> An alternative to write this is:
>
>         If[Random[]<.5, First, Last] /@ Transpose[{list1, list2}]

This idea works, but the implementation needs a slight correction.
The problem with this function as written is that the If gets
evaluated only once:  at the beginning before the Map begins its
work.  Like most functions, Map lets its arguments be evaluated
before it does its thing.  So if list1 = {a, b, c, d, e} and
list2 = {v, w, x, y, z}, the command will start out as

Map[ If[Random[]<.5, First, Last], Transpose[{list1, list2}] ]

but will get re-written as either of

Map[ First, {{a, v}, {b, w}, {c, x}, {d, y}, {e, z}} ]
or
Map[ Last,  {{a, v}, {b, w}, {c, x}, {d, y}, {e, z}} ]

depending on the outcome of Random[].  The function being applied
to all the elements is determined in advance.  We want it determined
anew for each element.

Unevaluated will protect the function from pre-evaluation:

In[21]:= Unevaluated[ If[Random[] < 0.5, First, Last] ] /@
Transpose[{list1, list2}]

Out[21]= {v, b, c, d, z}

With Unevaluated, the If statement itself, not its evaluation, is
taken to be the function.  Each time it is applied to an element,
its value will be re-generated, sometimes becoming First, sometimes
Last.

You can see the general behavior in action by making up a simplified
Map command and tracing it with and without the Unevaluated.  One
way to trace is with Trace or TracePrint.  Compare the printouts
of these two commands, and look for the If sequences.  You'll see
just one for the first command, but one at each element for the
second command.  I'm omitting the output since it's a little long
(not horribly -- just around a page each)

TracePrint[ If[Random[] < 0.5, f, g] /@ {x, y} ]

TracePrint[ Unevaluated[If[Random[] < 0.5, f, g]] /@ {x, y} ]

When you've seen several Trace outputs and feel a little more comfortable
with what's going on, you can omit all but the If evaluations, just give
a second argument of If:

TracePrint[ If[Random[] < 0.5, f, g] /@ {x, y}, If ]

TracePrint[ Unevaluated[If[Random[] < 0.5, f, g]] /@ {x, y}, If ]

A different method to count the If evaluations is by switching on general
tracing for the If function.  Thanks to Dave Withoff for pointing out the
usefulness of this window into the evaluator:

In[31]:= On[If]

In[32]:= Unevaluated[If[Random[] < 0.5, f, g]] /@ {x, y}

If::trace: If[Random[] < 0.5, f, g] --> If[True, f, g].

If::trace: If[True, f, g] --> f.

If::trace: If[Random[] < 0.5, f, g] --> If[False, f, g].

If::trace: If[False, f, g] --> g.

Out[32]= {f[x], g[y]}

The various Trace functions and option are discussed in section 2.5.10
of the Mathematica book.  Also, there is a Tutorial on MathSource at

http://www.wri.com/MathSource/Enhancements/Language/0203-858/Debugging.ma

Robby Villegas

```

• Prev by Date: Few MMA questions - need some help!
• Next by Date: Re: copy-paste bitmaps?
• Previous by thread: Re: Challenge!
• Next by thread: Re: Error in graphical display