読者です 読者をやめる 読者になる 読者になる

Dartは関数も変数も同じ名前空間。

Dart Google

GoogleからDartと呼ばれる新しいWebプログラミング言語が出てきましたね。
Dart: Structured web apps | DartLang.org

なんとなく、言語仕様が出ているので、ちら見していたら、下記の章が目に止まりました。

3.1 Scoping
Dart is lexically scoped and uses a single namespace for variables, functions and
types. It is a compile-time error if there is more than one entity with the same
name declared in the same scope. Names in inner scopes may hide names in
enclosing scopes, however, it is a static warning if a declaration introduces a
name that is available in a lexically enclosing scope.
Names may be introduced into a scope by declarations within the scope or
by other mechanisms such as imports or inheritance.

和訳すると、

3.1 スコープ
Dartは語彙的にスコープをもっており、変数、関数、型によって単一の名前空間を利用する。
同じスコープ内で同じ名前として宣言されている複数のエンティティがある場合、コンパイル時にエラーになる。
内部スコープに存在する名前がそれを囲んでいるスコープ内に存在する名前を隠す可能性がある、しかし、一つの宣言が囲んでいるスコープ内で利用可能な名前を指し示している場合、警告となる。
スコープ内での宣言もしくはimport文または継承などの他のメカニズムにより、スコープ内にある名前が指し示される可能性がある。

これにより、下記のコードはDart上ではエラーになります。

test() {
return "test2";
}

main() {
var test =  "test1";
  print('Hello,  ' + test());
}
// => Object is not closure

期待としては、test()は関数呼び出しのような印象を与えるので、
"Hello, test2"が返ってくることを期待しますが、このprint文中のtestは関数を指すのではなく、
一つ前の変数のtestを指します。そのため、test()とすると、そのオブジェクトは関数ではないよ、
という意味のエラーが返ってきます。

これが、"内部スコープに存在する名前がそれを囲んでいるスコープ内に存在する"場合ですね。

また、グローバル領域に変数と同じ名前の関数があるとそれもエラーになります。

test() {
return "test2";
}

var test =123;
// => コンパイルエラー

これが、"変数、関数、型によって単一の名前空間を利用し、同じスコープ内で同じ名前として宣言されている複数のエンティティがある場合"ですね。

JavaScriptでも同様の動作をしますが、Webプログラミングの言語を再定義するうえで、スコープはJavaScriptと合わせなくても良かったような気がします。命名規約として変数と同じような名前の関数を付けることはあまりないと考えられますが、
このスコープだけでは大規模開発で継承やimportを多用する場合は不便なことが多いと思われます。

でもJavaScript変換もあるようなので、なるべく合わせたかったのか、、、
という訳で、Dartを利用した場合でもグローバル領域を汚さないように気をつけてプログラミングする必要はありますね。

もう少し勉強してみます。