MathGroup Archive 1995

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Convert Products to Lists

  • To: mathgroup at
  • Subject: [mg1153] Re: Convert Products to Lists
  • From: villegas (Robert Villegas)
  • Date: Sat, 20 May 1995 00:43:19 -0400
  • Organization: Wolfram Research, Inc.

bob at (Robert Zimmerman) writes:

> Is it possible to convert a product of numbers to a list of numbers.  
> It can be done for symbols, 
> a b c //.Times->List
> {a, b, c}
> but it doesn't work for numbers
> 2  4  6//.Times->List
> 48

The //. operator (which is short for ReplaceRepeated) is like most
functions:  the arguments evaluate before the function takes effect.
The command gets converted from

   ReplaceRepeated[2 4 6, Times -> List]


   ReplaceRepeated[48, Times -> List]

before it does any substitution.

This is another example where wrapping Unevaluated around an argument
can be useful.  Unevaluated will make the structure Times[2, 4, 6]
sit still while ReplaceRepeated performs substitutions on it.

In[27]:= Unevaluated[2 4 6] /. Times -> List

Out[27]= {2, 4, 6}

Once you make Times[2, 4, 6] sit still, a lot of familiar expression
manipulations become available:

In[28]:= List @@ Unevaluated[2 4 6]

Out[28]= {2, 4, 6}

In[29]:= ReplacePart[Unevaluated[2 4 6], List, 0]

Out[29]= {2, 4, 6}

In[33]:= Level[Unevaluated[2 4 6], {1}]

Out[33]= {2, 4, 6}

Here are a couple operations different from yours taking place on
Plus or Times objects.  In comments after the inputs, I've written
the command that is getting executed by the internal code as a result
of Unevaluated forcing structures like Plus to be left alone.

Extract explicit Integers, leaving out Symbols that happen to evaluate to

In[34]:= {a, b} = {999, 777}

Out[34]= {999, 777}

In[35]:= Cases[Unevaluated[2 3 b 7 a], _Integer]

(* Cases[Times[2, 3, b, 7, a], _Integer] *)

Out[35]= {2, 3, 7}

Distribute f over addition, just as if 1, 2, 3, 4 were symbols, because the
addition is prevented.

In[50]:= Distribute[Unevaluated @ f[1 + 2, 3 + 4] ]

(* Distribute[f[ Plus[1, 2], Plus[3, 4] ]] *)

Out[50]= f[1, 3] + f[1, 4] + f[2, 3] + f[2, 4]

These are simple illustrations of what you can do, much along the lines
of your original problem that needed to keep an arithmetic operation
held.  They're made up to illustrate the kinds of things you can do,
and I think they show how unevaluated structures can be operated on.
And I wouldn't be surprised if there are practical uses, although I
can't think of any right this moment (you must have some, since
you asked).

But here is something which is more clearly in the practical vein
for programming.  What it does is pretty simple:  it takes a sequence
of instructions separated by ";" (a CompoundExpression) and inserts
an instruction after each.  The new instructions, which I'm thinking
of as progress indicators, are in one-to-one correspondence with
the main instructions, and would be input by a user, or possibly
generated, wishing to test a program.

Attributes[PrintProgress] = HoldAll

PrintProgress[main_CompoundExpression, progress_CompoundExpression] :=
  Inner[Sequence, Unevaluated[main], Unevaluated[progress],

A test:

In[6]:= Clear[a, b, c]

In[7]:= PrintProgress[a = 1; b = 2; Abort[]; c = 3,
          Print[1]; Print[2]; Print[3]; Print[4] ]

Out[7]= $Aborted

If you want the same progress command executed after each instruction,
add a definition that inserts it after each instruction in the main

PrintProgress[main_CompoundExpression, progress_] :=
  Thread[Unevaluated[main ; progress], CompoundExpression]

Just count the number of instructions that succeed:

In[9]:= instructionCounter = 0

Out[9]= 0

In[10]:= PrintProgress[1 ; 2 ; 3 ; 4 ; Abort[] ; 5 ; 6, ++instructionCounter]

Out[10]= $Aborted

In[11]:= instructionCounter

Out[11]= 4

Accumulate the values of MemoryInUse[] in a list so you can see how
much memory the instructions are consuming:

In[17]:= PrintProgress[MemoryUsage = {MemoryInUse[]}; Integrate[1/Sqrt[x^3 -  
1], x]; Series[BesselK[5, z], {z, Infinity, 3}], AppendTo[MemoryUsage,  
MemoryInUse[]] ]

Out[17]= {675548, 675580, 812676, 1265580}

This can be done without Unevaluated, but I like Unevaluated because
I don't have to worry about an extra level of Hold, which deepens the
level of everything by one, and I don't have to ReleaseHold at the end,
because once the structural operation is done, the result evaluates.

Robby Villegas

  • Prev by Date: "Topographical" Coloring?
  • Next by Date: Re: MathLink and CodeWarrior
  • Previous by thread: Convert Products to Lists
  • Next by thread: Re: Convert Products to Lists