foreachを書いているとき、意図せず変数が変化してたことがあったので少し確認してみました。
PHPのforeachでは変数に代入される
環境はPHP 7.2.7です。
<?php $val1 = 1; foreach([2, 3, 4, 5] as $val1) { printf("in foreach $val1\n"); } printf("val1: $val1\n");
これを実行すると、
in foreach 2
in foreach 3
in foreach 4
in foreach 5
val1: 5
こうじゃ。
val1が代入されて変化してしまっています。
ローカル変数として定義していたものとforeachを回すときに使っていた変数の変数名がたまたま同じものになったとき、foreach抜けたらローカル変数のほうが変わってて最初気付かなかったところです。foreachのkeyとvalueって意識的には一時的なものとしか思ってなくて。
このへんを踏まえて公式ドキュメントを見ると、foreachの「警告」と書かれている項にある、参照を使った事例はだいぶイヤな予感しかしない…
foreachで使う変数はだいたいループないでのテンポラリ的な扱いのつもりで、「$k => $v」とか割と適当に設定したりしてますから、迂闊に参照を絡めたりするとなんでそうなるのかわからないバグとかになりそうです。
pythonの場合
今をときめくPython(3.5.2)。
val1 = 1 for val1 in [2, 3, 4, 5]: print("in foreach "+str(val1)) print ("val1: "+str(val1))
これを実行すると
in foreach 2
in foreach 3
in foreach 4
in foreach 5
val1: 5
こうじゃ。
やっぱりval1が変化しています。
rubyの場合
ruby (2.4.2p198)の場合も、
val1 = 1 for val1 in 2..5 print("in foreach ", val1, "\n") end print("val1: ", val1, "\n")
やっぱりこう。
in foreach 2
in foreach 3
in foreach 4
in foreach 5
val1: 5
あとrubyにはeachメソッドがあり、
val1 = 1 range = 2..5 range.each{|val1| print("in each ", val1, "\n") } print("val1: ", val1, "\n")
そちらを使うと
in each 2
in each 3
in each 4
in each 5
val1: 1
こうじゃ。
eachの実行だとブロックの中に隔離される感じでしょうか。