为什么我无法使用String
或其他模块进行保护?
代码:
def foo(s1, s2) when String.length(s1) == String.length(s2) do
# something
end
当我希望使用模块功能时,如何优雅地重新格式化这种情况?
答案 0 :(得分:24)
来自erlang docs:
有效保护表达式集(有时称为保护测试)是有效Erlang表达式集的子集。限制有效表达式集的原因是必须保证对保护表达式的评估没有副作用。
Elixir也是如此。
好消息是,对于您的特定用例,有一个可以工作的警卫:
def foo(s1, s2) when byte_size(s1) == byte_size(s2) do
通常,当您想要做的事情无法在警卫中使用时,您需要检查该功能,例如:
def foo(s1, s2) do
cond do
String.length(s1) == String.length(s2) -> # Do something
true -> # Do something else
end
end
以下答案解释了用宏Create new guard clause定义自己的守卫(守卫必须使用http://elixir-lang.org/getting-started/case-cond-and-if.html#expressions-in-guard-clauses中记录的有效守卫功能)
答案 1 :(得分:1)
byte_size(s1) == byte_size(s2)
与
的含义不同String.length(s1) == String.length(s2)
仅对由单个字节组成的字符执行此操作。
iex(1)> String.length("hello") == String.length("helló")
true
iex(2)> byte_size("hello") == byte_size("helló")
false
要获得正确的行为,您必须手动调度:
def foo_same(s1, s2) do
# something
end
def foo_different(s1, s2)do
# something
end
def foo(s1, s2) do
if String.length(s1) == String.length(s2) do
foo_same(s1, s2)
else
foo_different(s1, s2)
end
end