What else would you do? For loops either introduce a scope or they don’t. There’s no such thing as half a scope. If you want loop variables to be local to for loops then there has to be a scope for them to be local to.
It’s easy to look at a short for loop with an assignment and think “Of course that should write to an outer variable, what else would I have meant by that?” But in real world, non-toy programs it’s quite common for a large amount of code to exist inside a loop body, with assignments at the top to variables that are used further down and never used outside of the loop body. In those cases you don’t want the variables that are only used inside the loop to hang around afterwards.
In general there’s no perfect solution to this because people want to do different things at different times. Forcing people to be explicit about it all the time is one approach—requiring var
to declare new variables, for example—but that’s annoying all of the time. Otherwise you have rules that try to “do the right thing” most of the time. The best you can do is have rules that are right most of the time, fairly simple to understand, and favor better programming practices over worse ones. In general local is better than global and statically predictable is better than unpredictable, so that’s what Julia’s scope rules do.
Julia’s for loop scope behavior is also carefully designed so that the difference between for loops and comprehensions is minimal. You probably haven’t noticed because there’s nothing to complain about—because they work the same way. But I can assure you from experience with earlier versions of the langauge where they did not work the same that if they didn’t then everyone would be complaining about that instead.