tommy
If expression in a cond - SyntaxError: unexpected token: ). The “do” at line 77 is missing terminator “end”
I created a small scripts that takes a lottery number of length x and loops until it finds a match. I created it just for learning purposes and out of curiosity of how many loops are needed to find a match.
At the moment it prints the number of loops to the terminal but I would prefer if it only printed every 5000 or so tries.
I put an if expression that checks the see if loop_num / 5000 ends in 0, in the cond for each non match but I get the following error:
"elixir elixirPlay.exs
** (SyntaxError) elixirPlay.exs:83: unexpected token: ). The “do” at line 77 is missing terminator “end”
HINT: it looks like the "do" on line 1 does not have a matching "end"
(elixir) lib/code.ex:813: Code.require_file/2
"
If I comment out the if it works again. Are if expressions allowed in conds? What’s the solution?
Any other other critiques on the code?
defmodule Play do
def random_numbered_balls num do
(for _x <- 1..num, do: Enum.random 1..49) |> List.to_tuple
end
def loto(true), do: IO.puts "We have a match!"
def loto(num_of_balls), do: loto(random_numbered_balls(num_of_balls), num_of_balls, 0)
def loto(static_balls_list, num_of_balls, loop_num) do
static_balls = static_balls_list
changing_balls = random_numbered_balls(num_of_balls)
cond do
(static_balls == changing_balls) ->
IO.inspect static_balls
IO.inspect changing_balls
loto(true)
(static_balls != changing_balls) ->
#if (String.ends_with?(to_string(loop_num / 5000)), "0")), do: IO.puts "#{loop_num} tries"
IO.puts "#{loop_num} tries" #(temp) would prefer to print only ever 5000 tries but can't get the above to work
loop_num = (loop_num + 1)
loto(static_balls, num_of_balls, loop_num)
end
end
end #module end
Play.loto(x)
Most Liked
al2o3cr
if (String.ends_with?(to_string(loop_num / 5000)), "0"))
This has too many ).
It should also be spelled if (loop_num % 5000 == 0), partly because that’s much more efficient than converting to string and checking the last character but mostly because / in Elixir does not mean integer division:
4214 / 5000
# evaluates to
0.8428
Other general notes:
static_balls = static_balls_list
What’s the intent of this line?
(static_balls != changing_balls) ->
Parentheses are not required here.
loop_num = (loop_num + 1)
And they’re DEFINITELY not required here
I highly recommend learning about and using mix format - it helps remember all the “where do the parens go” rules.
Matsa59
Hello,
def lotto(static_balls_list, num_of_balls, loop_num) do
cond do
(static_balls_list == changing_balls) ->
(static_balls_list != changing_balls) ->
# if your code goes the condition before is always true
end
end
you can simply do
def lotto(static_balls_list, num_of_balls, loop_num) do
if static_balls_list == changing_balls do
else
end
end
also you return loto(true you can direclty return the result {:match_found}
You have 3 functions signatures for loto
def lotto(true), do: {:match_found}
def lotto(num_of_balls), do: lotto(random_numbered_balls(num_of_balls), num_of_balls, 0)
def lotto(static_balls_list, num_of_balls, loop_num) do
that describres 3 differents behaviour.
I rewrite your code as I probably code it (just sharing way of think not judging)
defmodule Loto do
def shuffle(num) do
# Use a List is better than custom Tuple length
for _x <- 1..num, do: :rand.uniform(49)
end
# start loto
def start(num_of_balls) do
win?(
shuffle(num_of_balls),
shuffle(num_of_balls)
)
end
# This line just set the default value for the 3th parameter
# and is know as a function signature that do nothing more ;)
def win?(list_of_balls, other_list_of_balls, loop_num \\ 1)
# if we provide 1st et 2nd is the same value basically you win
def win?(balls_list, balls_list, loop_num) do
IO.puts("We have a match. It took #{loop_num} tries in total.")
:match_found
end
# otherwise try again
def win?(_, balls_list, loop_num) do
if rem(loop_num, 100_000) == 0, do: IO.puts("#{loop_num} tries")
balls_list
|> Enum.count()
|> shuffle()
|> win?(balls_list, loop_num + 1)
end
end
Loto.start(1)
I think
win?/3could be improve not my best piece of code.
Also start / win? will always return :match_found so not a usefull return.
Hope it help ![]()
Matsa59
With time you’ll start thinking different (some one already say that
)
In general term, you use tuple for a structured data that you know the size in compile time. In your case we can’t.
But why knowing the size is so important? It allows you to play easily with the data.
For example pattern matching become an elegant way to accomplish things. With list, you can use [tail | head] for matching data.
E.g:
[h|t] = [1,2,3]
# h -> 1
# y -> [2,3]
Doing this with tuple is little bit harder. The first way is : you now the size you can match data so you can do something like the code bellow
{a,b,c} = {1,2,3}
However, imagine you put 50 elements in the tuple and it become a nightmare.
Or you can use elem/2 But it’s not a pattern matching and it will not be useful in our case.
elem({1,2,3}, 1)
2
I explain you that because the main thing about functional programming is thinking of the future. When you write a function your main goal is to provide a piece of code that could be use again and again without any modification. That’s why I had 3 little functions instead of one bigger. Each one does exactly one thing.
So here, I use a list because needs could evolve to : if there is rights numbers but in different order print « you were close » in the console. Doing this with list a pretty easy and the code will be elegant (It could be an great exercice btw).
And for charlists, you can take a look at Elixir lists interpreted as char lists - Stack Overflow
When I was young I was diagnosed with dyslexia. With time, code help me a lot. Keep in mind dyslexia is an advantage. Your brain work differently and it will give you the opportunity to think how to accomplish things differently.
Have a great day ![]()
kokolegorille
You can always switch to LFE 
tommy
Thank you, very interesting. I’ll reread your message tomorrow, run it and reply :).







