Question

I created a simple "banking program" as practice and it seemed to work well until I deliberately tried breaking it to see what happens. I have a bit of code used to make sure that the pin is entered correctly.

I wanted to make one message appear if the entry did not include numbers, and I wanted to make another message pop up to determine whether or not the pin they entered was the pin associated to their account. To do this I used an unless/else conditional followed by an if/else conditional (the first part of the code are some regexps referenced in the method and the hash where it's all stored):

@accounts = {
    "bob" => { :pin => 1234, :balance => -100 },
    "mark" => { :pin => 2345, :balance => 1000000000 }
}

# Makes sure the user only types exactly 4 digits
def valid_pin_entry(pin)
    /^\d{4}$/ === pin
end
# Makes sure the user only types digits
def valid_number_entry(number)
    /^\d+$/ === number
end

def enter_pin_number(username)
    puts "Please type your pin number."
    response = gets.chomp 

    unless valid_pin_entry(response)
        puts "Your response must be 4 numbers in length.\n\n"
        enter_pin_number(username)
    else
        pin = response.to_i
        puts "Validating pin number..."
    end
    if validate_pin(@username, pin)
        puts "Your pin was successfully entered!\n\n"
    else
        puts "The pin number you entered was incorrect.\n\n"
        enter_pin_number(@username)
    end
end

What seems to happen is that when the number is entered incorrectly, I call on the method to start over. But it doesn't actually start over the way I thought it would. The response I'm looking for would be something like:

"Your response must be 4 numbers in length."

"Please type your pin number."

(Entered correctly this time.)

"Validating pin number..."

"Your pin was successfully entered!"

But instead I wind up with this:

Please type your pin number.
 a
Your response must be 4 numbers in length.

Please type your pin number.
 2345
Validating pin number...
Your pin was successfully entered!

The pin number you entered was incorrect.

Please type your pin number.
 2345
Validating pin number...
Your pin was successfully entered!

I'm honestly having trouble understanding why this is happening in the first place and am thinking this has to deal with carrying the parameter back through the same method. I managed to fix it using while to loop through responses, but that hasn't helped me understand my mistake. My original program was riddled with these apparently, so I've posted it in a codecademy lab.

My bank_account.rb code

Was it helpful?

Solution

In the following line, the code is calling the same function (another function call).

enter_pin_number(username)

Once that function call complete, the caller resume. To prevent resuming, you need to explicitly return.

unless valid_pin_entry(response)
    puts "Your response must be 4 numbers in length.\n\n"
    enter_pin_number(username)
    return # <------
else
    pin = response.to_i
    puts "Validating pin number..."
end

OTHER TIPS

When you decide to use recursion for your problem, make sure that no more code get executed after the return of a recursion call. In functional programming, it's called tail-recursion and can be optimized to a loop.

def enter_pin_number(username)
  puts "Please type your pin number."
  response = gets.chomp 

  unless valid_pin_entry(response)
    puts "Your response must be 4 numbers in length.\n\n"
    enter_pin_number(username)
  else
    pin = response.to_i
    puts "Validating pin number..."

    if validate_pin(@username, pin)
      puts "Your pin was successfully entered!\n\n"
    else
      puts "The pin number you entered was incorrect.\n\n"
      enter_pin_number(@username)
    end
  end
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top