There is a subtle but important difference. You are using
$i in the callback, which is a variable. In the C-style loop, you are creating a closure, and the variable does not disappear when the for loop ends: it is kept in the sub to be printed later. In the foreach case, though,
$i is aliased to the elements you are iterating over. $i in this case is not a normal variable, it is an alias of the actual number. Try adding
\$i into your test print to see the difference.