Psychicplatypus
Psychicplatypus

Reputation: 25

How do "variables" work with recursion in Elixir?

I am an absolute beginner in Elixir and I tried toying around with recursion by making a function like this:

  def player_choice() do
    choice = IO.gets("Choose rock, paper or scissors: ") |> String.trim()

    unless String.downcase(choice) in ["rock", "paper", "scissors"] do
      IO.puts("\nPlease insert a valid move")
      choice = player_choice()
    end

    choice
  end

So if someone inputs a value thats not expected the function should continue asking for an input. But if the first input is something unexpected like "no", and the next input is "rock" the function will return "no". Why does this happen, shouldn't "choice" be the reassigned value?

Upvotes: 1

Views: 174

Answers (2)

Hedde van der Heide
Hedde van der Heide

Reputation: 22449

Pattern matching seems an idiomatic way to approach this

defmodule Playground do
  def player_choice(choice) when choice in ["rock", "paper", "scissors"], do: choice
  def player_choice(_) do
    IO.puts("\nPlease insert a valid move")
    prompt()
  end
  
  def prompt() do
    IO.gets("Choose rock, paper or scissors: ") 
    |> String.trim
    |> String.downcase 
    |> Playground.player_choice
  end
end

Upvotes: 2

bortzmeyer
bortzmeyer

Reputation: 35459

The problem is that you redefine a new variable choice in your internal unless, masking the outer one (in Elixir, you don't "reassign"). The compiler warns you:

variable "choice" is unused (there is a variable with the same name in the context

A better solution would be something like:

def player_choice() do
  choice = IO.gets("Choose rock, paper or scissors: ") |> String.trim() |> String.downcase
  if choice in ["rock", "paper", "scissors"] do
     choice
  else
     IO.puts("\nPlease insert a valid move")
     player_choice()
  end
end

Upvotes: 2

Related Questions