PythonとJavaScriptはちょっと似てると思ってる
先週の金曜日にちょっとした集まりがあって、どういう流れでそうなったのか思い出せないんだけど、なぜかPythonistaがJavaScriptをDisって私がJSを弁護するという展開になった。
まぁでもここではそれの場外乱闘をしたいわけではなくて、ただそんとき言い忘れたことを思い出したので、それについてちょっと書きたい。
要は「PythonとJavaScriptってわりと似てね?」って話。
Pythonの勉強を始めて最初に思ったことなんだけど、PythonとJS、この二つはなんだか他人と思えない。別に上のPythonistaに喧嘩売ってる訳ではなくて、以前ホントにそう思った・・・んだけどなぁ。
・・・
ずっと以前にJavaScriptの本読んでかなり驚いたことの一つに変数のスコープの話がある。JSだと変数がブロックのどの位置で宣言されてもその変数はブロックの先頭から有効になるという奴。例えば
function fooIsUndefined() { alert(foo); var foo = 'hello'; }
上のはfooがブロック内部で宣言されてるのでalertは「undefined」と表示してくれるんだけど
function raiseError() { alert(foo); }
こっちは宣言されてないのでエラー。
あとこれはおまけだけど
function fooIsUndefined() { alert(foo); if (false) var foo = 'hello'; }
宣言文は実行されなくても大丈夫。これも「undefined」と表示される。
で、この動作、Pythonでも同じ。まぁ同じって言っても両方ともエラーだけど。
def foo_is_undefined(): print foo foo = 'hello'
のエラーは
UnboundLocalError: local variable 'foo' referenced before assignment
「まだ束縛されてない変数ですよ」だけど
def raise_error(): print foo
は
NameError: global name 'foo' is not defined
「そんな変数ねぇよ」
で、
def foo_is_undefined(): print foo if False: foo = 'hello'
は
UnboundLocalError: local variable 'foo' referenced before assignment
「まだ束縛されてない変数ですよ」
ほらJSと一緒。この挙動って自分にはちょっと驚きだったんだけど、他にもこういう動作する言語たくさんあったりするんだろうか?
あとJSだと関数の内部でも関数を定義できたりするね。
function outer() { function inner() { alert('inner!'); } inner(); // もちろんここでは呼べる } // inner(); // これは関数が見つからなくてエラー new outer().inner(); // これなら大丈夫
Pythonでも関数のネストは可能。つかevalが貧弱すぎるPythonには必須。まぁさすがに関数をnewするのは無理だけど。
def outer(): def inner(): print 'inner' inner() # 大丈夫 #inner() # エラー #outer.inner() # さすがに無理
関数のネストができる言語はいっぱいあるけどRubyはできないんだよな。できたらうれしいんだけど。
あとあれ、関数名が関数オブジェクトで()演算子で実行されるとかも一緒。
function bar() { alert('bar'); } var xyzzy = bar; xyzzy();
def bar(): print 'bar' xyzzy = bar xyzzy()
まぁこれはCとかでも一緒か。Rubyが特殊なだけかも。
あとはー、あれ?なんも思いつかないな。
なんかあれだな、考えてみれば最初のやつ以外は別に珍しくもないし、最初のやつも実は自分で書きながら思ったけど、似てるっていうにはちと微妙だ。最近Pythonさぼってるから覚えてないけど、以前はもっと似てると感じた気がしたんだけど・・・。
うむ、残念ながらPythonとJavaScriptはちょっと似てると思ってたけどそうでもなかった。まぁそれはそれとしてJSも言語としてはそう悪くないはずなのでそんなに嫌わなくていいと思うよ。てことで、まとまらずにおわる。