2012-06-24 13 views
7

は、私は、Web上でこのコードaccrossに来た:私は自分のガードをErlangで作ることができますか?

is_char(Ch) ->   
    if Ch < 0 -> false; 
     Ch > 255 -> false; 
     true -> true  
    end. 

is_string(Str) ->    
    case is_list(Str) of   
    false -> false;   
    true -> lists:all(is_char, Str) 
    end. 

ITSは、それが入力文字列をあるかどうかを確認することで、私は、オフ夢見alwaisガードです - どのように今まで、私はそれを使用することはできませんよエルランでは、なぜこれは?そして、回避策はありますか?

私のようなものを書くことができるようにしたいと思います:

Fun(Str) when is_string(Str) -> Str; 
Fun(Int) when is_integer(Int) -> io:format("~w", [Int]). 

またはより良いメッセージにそれを使用しています。

+4

文字列をテストするより良い方法は、 'io_lib:printable_list/1'と' io_lib:printable_unicode_list/1'を組み合わせて使う方法です。 –

+0

[this](http://stackoverflow.com/questions/10861347/why-comparing-function-results-is-an-illegal-guard-exception-in-erlang)[this](http:// [this](http://stackoverflow.com/questions/6927632/checking-for-membership)、[this](http://stackoverflow.com/questions/6927632/checking-for-membership) -in-an-erlang-guard)、[this](http:// stackoverflow。com/questions/2241340/function-call-in-function-guard)と[this](http://stackoverflow.com/questions/7474894/use-of-function-in-guard-not -allowed-suggestions-for-alternate-implementation-w)の質問です。 – legoscia

答えて

9

ガード内でユーザー定義関数を使用することはできません。これは、ガード内の機能が副作用から解放されている必要があるためです(関数内でio:formatを使用するなど)。形式試験(is_atomis_constantis_floatis_integeris_listis_numberis_pidis_portis_referenceis_tupleis_binaryis_functionis_record)、に使用

  • たBIF:警備員で、あなたは次のように制限されています
  • ブール演算子(notandorandalsoorelse,;)、
  • 関係演算子(>>=<=<=:====/=/=)、
  • 算術演算子(+-*divrem)、
  • ビット単位演算子(bandborbxor,bnot,bsl,bsr)、
  • 他のBIFs tha tは、副作用のない(abs/1element/2hd/1length/1node/1,2round/1size/1tl/1trunc/1self/0
+4

ええと、それは副作用のチェックが非常に簡単な静的解析のトリックになるようです... –

+5

@MartinKristiansen実行中にモジュール内のコードを変更または置き換えることはできません。 –

+0

@alexeyRomanov:あなたは絶対に正しいですが、現在のモジュールの中でBIFと唯一の機能を使用する制限をしているかもしれません:-) –

5

ガードにユーザ定義関数を許可しないための別の理由は、エラーがで異なる方法で処理されることです"通常の"機能よりも警備員の方が安全です。ガードエラーでではなくが例外を生成すると、ガード自体が失敗するだけです。

ガードは実際には表現ではなく、のテストです。

関連する問題