I'm grading for a class using Mathematica right now, and one of the students ran into a weird issue. When he ran code like this:

examplefun[n_] :=
SetDirectory["/Users/"];
Module[{output = ""},
Do[output = output <> RandomInteger[{1, 4}], {i, n}];
Print[output]]


He get's an error: Do::iterb: "Iterator {i,n} does not have appropriate bounds. "

But if he moves Module up:

examplefun[n_] :=
Module[{output = ""},
SetDirectory["/Users/"];
Do[output = output <> RandomInteger[{1, 4}], {i, n}];
Print[output]]


The error disappears. I'm not sure what the problem is, though I suspect it has something to do with scoping. Could someone provide me with some insight here?

Thanks!

Edit: Ohhhhhhhh, that makes sense! Thanks for the prompt responses, everyone! I hadn't considered that his code didn't use the proper syntax for a multi-line function since I haven't used multi-line syntax before. I've accepted an answer, but thanks for all the responses!

-
Multi-line functions should be encapsulated with parenthesis. In the first version, Module is not part of the function but is executed on its own. So n is not defined. – C. E. Sep 5 '13 at 20:46
I think you would benefit from reading these: (3146), (30430) – Mr.Wizard Sep 6 '13 at 5:22

This is a precedence issue. SetDelayed (:=) has a higher precedence than CompoundExpression (;), so the first form does not include the Module in the definition at all. This is why the iterator in Do does not have the appropriate bounds, n is defined only in the function.

Personally, I would use white-space in the function, to highlight where the scope boundaries are

examplefun[n_] :=
Module[{output = ""},
SetDirectory["/Users/"];
Do[output = output <> RandomInteger[{1, 4}], {i, n}];
Print[output]
]


This will not help with the first form, but it makes the second much easier to read.

-

+1 to rcollyer for an excellent answer. But it's also good to know that parenthesis will fix the precedence issue:

examplefun[n_] := (
SetDirectory["/Users/"];
Module[
{output = ""},
Do[output = output <> ToString[RandomInteger[{1, 4}]], {i, n}];
Print[output]
]
)


And it's good to know how to figure out precedence issues using FullForm and Hold.

Hold[examplefun[n_] := (
SetDirectory["/Users/"];
Module[
{output = ""},
Do[output = output <> ToString[RandomInteger[{1, 4}]], {i, n}];
Print[output]
]
)] // FullForm


Hold[SetDelayed[examplefun[Pattern[n,Blank[]]],CompoundExpression[SetDirectory["/Users/"],Module[List[Set[output,""]],CompoundExpression[Do[Set[output,StringJoin[output,ToString[RandomInteger[List[1,4]]]]],List[i,n]],Print[output]]]]]]

And

Hold[examplefun[n_] :=
SetDirectory["/Users/"];
Module[
{output = ""},
Do[output = output <> ToString[RandomInteger[{1, 4}]], {i, n}];
Print[output]
]
] // FullForm


Hold[CompoundExpression[SetDelayed[examplefun[Pattern[n,Blank[]]],SetDirectory["/Users/"]],Module[List[Set[output,""]],CompoundExpression[Do[Set[output,StringJoin[output,ToString[RandomInteger[List[1,4]]]]],List[i,n]],Print[output]]]]]

In Mathematica, so called standard-evaluation is to evaluate from the inside and out. This applies here, so we can see that in the first case CompoundExpression get evaluated before SetDelayed because it appears inside it. But in the second version SetDelayed is separated from the Module code, we clearly see that n is not available to Do but just looking at this. You could also use TreeForm on this expression to see that the different parts belong to different "branches."

-