Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why forbidden to use a remote function inside a guard

Tags:

elixir

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?

like image 305
jimmbraddock Avatar asked Jan 18 '16 08:01

jimmbraddock


2 Answers

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)

like image 109
Gazler Avatar answered Oct 25 '22 08:10

Gazler


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
like image 43
Richard Avatar answered Oct 25 '22 08:10

Richard