AutoOpenAttributeについて

F# Advent Calendar 2014 - connpassの2日目です。

今回は、AutoOpenを紹介します。

AutoOpenとは、モジュールを自動でopenする仕組みです。主に言語やフレームワークでよく使うモジュールを提供するときに使います。主にライブラリ開発者に対する機能で、利用者は使うことは無いと思います。 実際に使うときは、AutoOpenAttributeを使用します。

しかし、あまりにも開くモジュールが多すぎると利用者はビックリしてしまうので、ほどほどにしましょう。

MSDNを見ても何の事か分からないので、F#の言語仕様書を見てみましょう。「Special Attributes and Types」という章にAutoOpenAttributeの記述があります。

When applied to an assembly and given a string argument, causes the namespace or module to be opened automatically when the assembly is referenced. When applied to a module without a string argument, causes the module to be opened automatically when the enclosing namespace or module is opened.

アセンブリと、モジュールに対してAutoOpenAttributeを適用できる」と書いてあります。それぞれの使い方を説明します。

モジュールに適用する場合

よく使うパターンです。モジュールに対してAutoOpenをつけると、親のモジュール、名前空間がopenされた時に、自動でopenされます。

使い方はこんな感じ。

module A =
  let f x = x
  [<AutoOpen>]
  module B =
    let g x = x * 2 

open A
let x = g 1 (* Bモジュールの関数を使える *)

アセンブリに適用する場合

アセンブリにAutoOpenを付け、開きたいモジュール名を指定します。AutoOpenが付与されたアセンブリをプロジェクトの参照に追加しただけで、自動でopenされるようになります。

使い方はこんな感じ。例ではモジュール定義のすぐ下に書いてますが、実際に使うときはAssemblyInfo.fsなどに書くといいと思います。

module A =
  let f x = x
  module B =
    let g x = x * 2 
[<assembly: AutoOpen("A.B")>]
do ()

こちらの機能は、強力すぎるので使う機会が少ないと思いますし、使わないほうがいいと思います。

F# では、FSharp.Coreがこの方法を使っています。いつも使えるListモジュール等は、アセンブリに対するAutoOpenで提供されています。 ソースコードこの辺りです。 特別扱いをするのではなく、言語の機能を使って提供しています。素晴らしいですね!

つまり、AutoOpenを外したFSharp.Coreを作れば、明示的にopenしないとListモジュールなどは使えないってことでしょうか? 既存のソースコードコンパイルエラーになるはずです(試してないけど)。仕事場で隣の人が席を外している間に悪戯してやりましょう。