namespace
ある程度規模が大きいプログラムでは
関数や変数の名前が衝突したりすることが問題になってきました。
このような問題を解決するために
名前空間(namespace)というものが考えられました。
.Netのライブラリなんかは良い例で
.Netは様々な言語で動作するために
Microsoft.FSharp
Microsoft.CSharp
Microsoft.VisualBasic
といった名前空間が定義されています。
このように名前空間へのアクセスにもドット記法を用いるため
ぱっと見は、それがモジュールなのか名前空間なのか
(あるいはクラス/構造体/レコード)
判断は出来ませんが
VisualStudioのインテリセンスによって確認できます。
また、名前の衝突を解決、という意味では
どの表記であってもたいした違いはないということなのかもしれません
namespaceを用いるための構文は次のように定義されています。
- namespaceの構文
- 実装ファイル:= [名前空間の断片]*
名前空間の断片:=
| namespace 名前空間名 トップレベルのモジュール定義
| module モジュール名 モジュールの要素
| モジュールの要素
さっそく例を挙げてみます。
namespaceの例
namespace Test
module A = begin let a = 1 end;;
namespaceの例(軽量構文)
namespace Test
module A = let a = 1
この例ではnamespace Testとその中にモジュールAを定義しています。
namespaceもモジュールと同様にopenキーワードを使用できます。
namespaceとモジュールの使用
//File1.fs
namespace Test
module A = begin let a = 1 end;;
//Main.fs
open Test;;
printfn "%d" A.a;;
namespaceとモジュールの使用(軽量構文)
//File1.fs
namespace Test
module A = let a = 1
//Main.fs
open Test
printfn "%d" A.a
この例では、File1.fsにて定義したTestというnamespaceを
Main.fs側でオープンして使用しています。
なお、この時に気をつけるべきこととして
Main.fsを先にコンパイルすると動作しないという点が挙げられます。
ここについては、コンパイラの使い方で説明している
プログラムのロード順序を参照ください。
namespaceキーワードを使う場合
モジュールと異なっている点としては
(他にもあるとは思いますが)
1:namespaceには値(letなど)は定義出来ない
2:namespaceの前にはコンパイラ指示文しか記述してはいけない
3:上記理由によりnamespaceにはAutoOpenは使えない
4:namespaceは入れ子に出来ない
5:namespaceには省略名を付けることは出来ない(1.9.6.2から)
といった点が挙げられます。
例えば1:については、次の例がコンパイルエラーになることで確認できます。
また上記の定義では、namespaceは入れ子が可能な定義になっていません。
後ほど説明する、デフォルトでオープンされる名前空間は
入れ子になっているように見えますが
これはおそらく次のように実現されていると思われます
入れ子っぽい名前空間
namespace N
module A = begin let a = 1 end;;
namespace N.M
module B = begin let b = 2 end;;
入れ子っぽい名前空間(軽量構文)
namespace N
module A = let a = 1
namespace N.M
module B = let b = 2
namespace NとnamespaceN.Mは完全に別の名前空間で
入れ子関係は特にありません。
(定義で言えば、別の名前空間の断片に相当)
以前は上の定義でも、次のように段階的にオープン出来ましたが、現在はFS0893というエラーになります。
段階的なオープン
open N;
open M; //ここでエラー。open N.Mとすべき
printfn "%d" B.b;;
これは、F#が元々次のような書き方を許していたためで
現在は完全に名前を修飾してopenすることが必要です。
(付属のREADME-fsharp.htmlより)
付属マニュアルより
open System
open Windows //現在はここでエラーが出るようになっている
open Forms
// open System.Windows.Forms //推奨されたやり方
また、名前空間の断片での
2,3行目はそれぞれ名前付きモジュール/匿名モジュールと呼ぶそうです。
これまで暗黙的に使用してきたコードは
匿名モジュールであった、ということが分かります。
最後に、デフォルトでオープンされる名前空間について説明します。
F#を含む全ての.NET言語ではmscorlib.dllが自動的に参照され
F#ではさらに、FSharp.Core.dllも自動的に参照されます。
このdllによって
F#のプログラムの実行ではデフォルトで
以下の名前空間がopenされるそうです。
自動的にオープンされる名前空間
open FSharp
open FSharp.Core
open FSharp.Core.LanguagePrimitives
open FSharp.Core.Operators
open FSharp.Text
open FSharp.Collections
open FSharp.Core.ExtraTopLevelOperators
参考:The F# 4.1 spec 18