【问题标题】:Can I make my own Guards in Erlang?我可以在 Erlang 中制作自己的 Guards 吗?
【发布时间】:2012-06-25 23:41:04
【问题描述】:

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

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]).

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

【问题讨论】:

  • 无意冒犯,但更好的字符串测试方法是:io_lib:printable_list/1io_lib:printable_unicode_list/1 组合使用。
  • 另请参阅thisthisthisthisthis 问题。

标签: erlang guard


【解决方案1】:

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

  • 用于型式测试的 BIF(is_atomis_constantis_floatis_integeris_listis_numberis_pidis_portis_reference@31 987654332@, is_function, is_record),
  • 布尔运算符(notandorandalsoorelse,;),
  • 关系运算符(&gt;&gt;=&lt;=&lt;=:====/=/=),
  • 算术运算符(+-*divrem),
  • 位运算符(bandborbxorbnotbslbsr),
  • 其他无副作用的BIF(abs/1element/2hd/1length/1node/1,2round/1size/1tl/1self/0trunc/1trunc/1 @)

【讨论】:

  • 嗯,检查副作用似乎是一个非常简单的静态分析技巧......
  • @MartinKristiansen 并非如此,因为模块中的任何代码都可以在运行时更改或替换。
  • @alexeyRomanov:你是绝对正确的——但也许会限制使用 BIF,并且只能在当前模块中使用函数 :-)
  • @MartinKristiansen 那必须是“只有 BIF 和当前模块中的那些函数,它们只调用当前模块中的 BIF 和函数并且不递归(以确保它们终止)”。这意味着你不能使用is_string 作为后卫,毕竟:)
  • @MartinKristiansen ...或使用特殊构造的函数,例如 receive,总是会产生副作用。
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-30
    • 1970-01-01
    • 2014-01-27
    • 1970-01-01
    • 1970-01-01
    • 2011-04-20
    • 2014-01-19
    相关资源
    最近更新 更多