別に言語は関係なさそうだけど、よくわかっていなかったのでメモ。
ページングの実装でリスナーを生成するときにハマった。初心者は気をつけよう。
Swift
func getF(num:Int) -> Void -> Void {
return {
println(num)
}
}
var list1: [(Void -> Void)] = Array()
var list2: [(Void -> Void)] = Array()
var list3: [(Void -> Void)] = Array()
for (var i = 0; i < 3; i++) {
let n = i
list1.append({println(n)})
list2.append({println(i)})
list3.append(getF(i))
}
for f in list1 { f() } // 0 1 2
for f in list2 { f() } // 3 3 3
for f in list3 { f() } // 0 1 2
Javaについてコメントいただいたので、Javascriptも試してみた。
Javascript
var list1 = []
var list2 = []
var list3 = []
function getF(num) {
return function() {
console.log(num)
}
}
for (var i = 0; i < 3; i++) {
var n = i
list1.push(function(){console.log(n)})
list2.push(function(){console.log(i)})
list3.push(getF(i))
}
list1.forEach(function(f){f()}) // 2 2 2
list2.forEach(function(f){f()}) // 3 3 3
list3.forEach(function(f){f()}) // 0 1 2
こちらは一旦別の変数に入れる対応でもだめみたい。
ES6ならletでイケる!とのコメントをいただいたのでこちらも試してみた。
こんなサービスがあるあたり流石js界隈。
ES6
var list1 = []
var list2 = []
var list3 = []
function getF(num) {
return function() {
console.log(num)
}
}
for (let i = 0; i < 3; i++) {
let n = i // var だとダメだった( 2 2 2 )
list1.push(function(){console.log(n)})
list2.push(function(){console.log(i)})
list3.push(getF(i))
}
list1.forEach(function(f){f()}) // 0 1 2
list2.forEach(function(f){f()}) // 0 1 2
list3.forEach(function(f){f()}) // 0 1 2
let n = i
のところを var n = i
と書いたらダメだった。
まあletがあるということは、ES6は基本var は使わない方がいいということなのかな。