2011-12-14 11 views
5

私は小さなerlangサービスを作成していますので、私のタイプに制約を入れたいと思います。erlangで-spec機能を使用する方法

私は-specの機能を見つけました。これは、これが機能のシグネチャを特定のタイプに「ロックする」方法のようです。

私の例では、関数のようになります:

fib(N) when N < 3 -> 
    1; 
fib(N) -> 
    fib(N-1) + fib(N-2). 

-spec fib_cps(pos_integer()) -> pos_integer(). 

は、方法は、少なくとも正しい型を返すことを確認する必要があり行を追加しますが、これはそうではないようです。 。

の場合:

fib(N) when N < 3 -> 
    ok; 
fib(N) -> 
    not_ok. 

コードはまだコンパイルされ、うまく実行されます。

私は何を誤解していますか?

+1

ところで、あなたの型指定は '-spec fib_cps(pos_integer()) - > pos_integer()。'(空白のカッコに注意してください)のようになります。そうしないとDialyzerはあなたが 'pos_integer' – legoscia

答えて

11

コンパイラはこれらのコメントをスキップします。しかし、透析装置を使って静的コード解析を行うことができます。このツールは仕様違反について警告します。

+0

これは、 '安定した'コードを保証するために、コンパイラのダイアライザツールontopを実行する必要があることを意味しますか?これは、型検査全体の問題を回避する方法ですか? –

+0

@MartinKristiansenはい、安定した生産コードが必要な場合は、透析装置を稼働させる必要があります。たぶんすべてのビルドではなく、定期的に。たとえば、毎日のビルドシステムを使用する場合は、それを1日のビルドシステムと統合することができます。 – werewindle

1

werewindleは、another answerで、-specは、署名の一部ではなく、解析にのみ使用されます。入力タイプを確認する場合は、ガード内のタイプのチェックを含めることができます。だから、あなたの例では、あなたが行うことができます:

fib(N) when is_integer(N), N > 0, N < 3 -> 
    1; 
fib(N) when is_integer(N), N >= 3 -> 
    fib(N-1) + fib(N-2). 

あるいは、より慣用的に、2つだけの正当なベースケースがあるので:

fib(1) -> 1; 
fib(2) -> 1; 
fib(N) when is_integer(N), N >= 3 -> 
    fib(N-1) + fib(N-2). 

これはfib(bogus)fib(0.5)ような何かをやってからあなたを妨げるのかさらにfib(-1)。試してみると、実行時にbadmatchで失敗します。

注:guardで使用できる唯一の機能は、ランタイムによって許可されている組み込み関数です。それらのほとんどはerlangモジュールにあります。

+0

私は見ていますが、本当に好きなのは、MLのような静的な型チェックです。私がタイプを指定したいという意味。 A:= C | D. 次に、メソッドがforinstance(_ - > A)型を持つように定義します。 そのようなことができる並行性の高いメカニズムを備えた言語について知っていますか? –

+2

@MartinKristiansen:透析装置は標準的なツールです。 erlangに同梱されており、erlangプロジェクトで使用する必要があります。はい、静的解析はコンパイラの一部ではありませんが、とにかくいつでもこれを行うことができます。 Cプリプロセッサがコンパイラとは別のツールであるとしたら、想像してみてください。それはどういうわけか不快ですが、大丈夫です。 – werewindle

関連する問題