# Don't understand why Do-loop index is not evaluated in Play expression

So here is some weird behavior: When I create a list inside a loop whose elements are Play functions, with arguments that depend on the counter, it is as if the counter is being stored symbolically, so all the list elements - not just the last one - change with each iteration. THis only happens with Play. If I do the same thing with Plot, for example, it works as expected. Here is an example, though I have also tried creating the list using Append and AppendTo, I have assigned the outputs, etc. list1 has every part the same, and all equal to the result with the current value of i. list2 has each part equal to what it was when it was first created (so the first with the results evaluated with i=1, the second with i=2, etc.). Why? How do I fix Play?

list1 = {0, 0, 0};
list2 = list1;
Do[
list1[[i]] = Play[Cos[150*i*2*Pi*t], {t, 0, 0.5}];
list2[[i]] = Plot[Cos[i*2*Pi*t], {t, 0, 0.5}];
Print[list1, list2],
{i, 3}
]
Show[list1]
Show[list2]
list1
list2

• Why do you want to show Sound ? – Artes Oct 6 '13 at 22:26

If you were to read the Details and Options section in the documentation for Play, you would find the following statement:

Play has attribute HoldAll, and evaluates $f$ only after assigning specific numerical values to $t$.

That is the "why" you are looking for. The simplest fix is to pass the Cos expression to Evaluate to force the evaluation of i.

list1 = {0, 0, 0};
list2 = list1;
Do[
list1[[i]] = Play[Evaluate @ Cos[150*i*2*Pi*t], {t, 0, 0.5}];
list2[[i]] = Plot[Cos[i*2*Pi*t], {t, 0, 0.5}];
Print[list1, list2],
{i, 3}]


With this single modification, your code should work the way you were expecting.

Get the i out of the Play[] to get it evaluated:

list1 = {0, 0, 0};
Do[list1[[i]] = Play[#, {t, 0, 0.5}] &@Cos[150 i 2 Pi t], {i, 3}]
Column@list1 Another standard trick is to use With:

list1 = {0, 0, 0};
list2 = list1;
Do[
list1[[i]] = With[{i = i}, Play[Cos[150*i*2*Pi*t], {t, 0, 0.5}]];
list2[[i]] = Plot[Cos[i*2*Pi*t], {t, 0, 0.5}],
{i, 3}];
list1
list2  If what you wish to do is to make a list of sounds for later playing, here is one way:

t = Range[0, 0.5, 1/8000];
listSounds = Table[Cos[150*i*2*Pi*t], {i, 1, 3}];
ListPlay[listSounds[[#]]] & /@ Range