Warning issues of unsafe often happen and how to solve the following case:
def dine(phil, table) do
send table, {:sit_down, self(), phil}
receive do
{:eat, forks} ->
phil = eat(phil, forks, table)
phil = think(phil, table)
# dine(phil, table)
end
dine(phil, table) #=> "variable phil is unsafe"
end
warning: the variable “phil” is unsafe
version: Elixir 1.5.0
When dine() moves to comment #dine, it is OK. But I want to keep the above code steps.
Could you help me how to write code to solve this?
def dine(phil, table) do
send table, {:sit_down, self(), phil}
new_phil =
receive do
{:eat, forks} ->
phil
|> eat(forks, table)
|> think(table)
end
dine(new_phil, table)
end
Remember: expressions, not statements.
I suspect that the warning was issued because you were referencing a name (phil) that was being rebound inside one of the receive pattern blocks (of which there can be many, not all of them necessarily providing a value for phil - even when in your particular case there doesn’t seem to be a problem).
By making new phil the (return) value of the receive expression any potential ambiguity is resolved.
def eat_with_forks (phil, table) do
receive do
{:eat, forks} ->
phil
|> eat(forks, table)
|> think(table)
end
end
def dine(phil, table) do
send table, {:sit_down, self(), phil}
phil
|> eat_with_forks(table)
|> dine(table)
end
In other case of if statement, I am annoyed.
There is no equivalent to C’s: if '(' expr ')' stmt [ else stmt ]
The if in Elixir is like the ternary or conditional operator:
so there always has to be an else - if you leave out the else it assumes:
logical-OR-expression?expression: nil
which may not be what you want.
Furthermore between the if and the else and the else and the endisn’t a block of statements - it’s a sequence of expressions; the value of that sequence is the value of the last expression in the sequence - the values of the preceding expressions are ignored which means they are executed for their side-effect (which often is binding the value to a name).
Finally = isn’t an assignment - it’s a match - the name(s) on the left hand side is(are) bound to a value(values) that will make it(them) match to the right hand side (if that is possible - see the pin operator).
I appreciate your kind explanation and I am impressed at your code of eat_with_forks regards receive do.
I am learning Elixir with reading project examples and refactoring on my own way. Most of codes I got from github have warnings and old functions such as Dict.map, though it must be good practice to correct them.
Regards if statement, I don’t reach the level of that I completely understand. But I know what result I can get by experiments.
I am learning and need your help, anyway.
Thanks a lot.