Re: ループ内の無名関数
ウノウラボ Unoh Labs: ループ内の無名関数を読んで、やっぱりPythonとJavaScriptは似ているなぁ、と思ってしまいました。Pythonに慣れた僕にとっては上記エントリのJavaScriptの挙動は自然だと思えてしまいます。
同じ現象は以下のようなPythonコードでも起こせます。
funcList = []
for i in range(2):
funcList.append(lambda :i)
i = 5
print funcList[0]() # 「5」と表示される
print funcList[1]() # 「5」と表示される
少なくともPythonの場合、この現象はループや無名関数とは無関係です。下のようなコードでも同じ現象が起きます。
i = 1
def foo():
return i
i = 5
print foo() # 「5」と表示される
これはどういうことかというと、関数fooの中で使われているiという変数は「グローバルスコープのiという変数」を意味するのであって、「関数fooが定義された時にグローバルスコープのiが指していた値」を意味するわけではない、ということです。古いPythonではこの問題を解決するために以下のようにBuilder関数を作ったりしていました。
i = 1
def foo_builder(x):
def temp_func():
return x
return temp_func
foo = foo_builder(i)
i = 5
print foo() # 「1」と表示される
ちなみにtemp_fileの代わりにfoo、xの代わりにiを使っても問題ないのですが、読み慣れていない人が混乱するかと思って別の名前をつけてみました。このコードでは、fooのxがfoo_builderのローカルスコープにある変数xを意味するので、グローバルスコープの変数iが指す値が変わっても影響を受けないわけです。これを無名関数でやったのがリンク先のmasatoさんの一つめのコメントであり、Pythonで同じことを書くとこうなります。
i = 1 foo = (lambda x: lambda :x)(i) i = 5 print foo() # 「1」と表示される
で、ここからが本題なのですが最新のPythonでは「引数省略時のデフォルトの値」が関数定義時に評価されることを利用して以下のような書き方ができます。JavaScriptに引数省略機能はないのですか?
i = 1
def foo(x = i):
return x
i = 5
print foo() # 「1」と表示される
フィードバック
これはおもしろいですね。 Javascriptでは引数は省略できますが、デフォルト値の定義はできません。 引数が渡されなかった場合は、 変数の値が undefined になるので、 undefined の場合に適切な値を設定してやります。 なので、python のように簡潔には書けないですね