10

我在网上看到了这段代码:

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.

它是我一直梦寐以求的 Guard,它检查输入是否为字符串——但是,我不允许在 erlang 中使用它,这是为什么呢?有解决办法吗?

我希望能够写出类似的东西:

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

甚至更好地在消息上使用它。

4

2 回答 2

12

不允许在警卫中使用用户定义的函数。这是因为守卫中的函数必须没有副作用(例如io:format在你的函数中使用)。在守卫中,您仅限于以下内容:

  • 用于型式测试的 BIF ( is_atom, is_constant, is_float, is_integer, is_list, is_number, is_pid, is_port, is_reference, is_tuple, is_binary, is_function, is_record),
  • 布尔运算符 ( not, and, or, andalso, orelse, ,, ;),
  • 关系运算符 ( >, >=, <, =<, =:=, ==, =/=, /=),
  • 算术运算符 ( +, -, *, div, rem),
  • 位运算符 ( band, bor, bxor, bnot, bsl, bsr),
  • 其他无副作用的 BIF ( abs/1, element/2, hd/1, length/1, node/1,2, round/1, size/1, tl/1, trunc/1, self/0)
于 2012-06-24T11:54:13.737 回答
5

不允许在守卫中使用用户定义函数的另一个原因是守卫中的错误处理方式与“正常”函数中的处理方式不同。在守卫中,错误不会产生异常,它只会导致守卫本身失败。

守卫不是真正的表达式,而是测试

于 2012-06-27T01:22:09.140 回答