Why I can't to use String
or other module in guard?
Code:
def foo(s1, s2) when String.length(s1) == String.length(s2) do
# something
end
And how I can elegantly reformat such case, when I wish to use module functions?
From the erlang docs:
The set of valid guard expressions (sometimes called guard tests) is a subset of the set of valid Erlang expressions. The reason for restricting the set of valid expressions is that evaluation of a guard expression must be guaranteed to be free of side effects.
The same is also true for Elixir.
The good news is, for your particular use case, there is a guard that will work:
def foo(s1, s2) when byte_size(s1) == byte_size(s2) do
Typically when what you want to do can't be used in a guard, you need to check inside the function, for example:
def foo(s1, s2) do
cond do
String.length(s1) == String.length(s2) -> # Do something
true -> # Do something else
end
end
The following answer explains defining your own guard with macros Create new guard clause (the guard must use the valid guard functions documented in http://elixir-lang.org/getting-started/case-cond-and-if.html#expressions-in-guard-clauses)
byte_size(s1) == byte_size(s2)
does not have the same meaning of
String.length(s1) == String.length(s2)
It only does so for characters composed of a single byte.
iex(1)> String.length("hello") == String.length("helló")
true
iex(2)> byte_size("hello") == byte_size("helló")
false
For the correct behavior, you have to manually dispatch:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With