Having issues understanding recursion

I would like to puts a question and until I get a certain answer to call recursively the method.
Is that possible?
Here is how I see this but of course it doesn’t work

def myF 
  puts "Please select a position 0 to 9"
  ans=gets.chomp
  while ans.to_i<10 
    myF
  end 
  puts "you chose #{ans}"
end 

Any suggestions would be greatly appreciated
Thanks

This code works just fine. You have your inequality the wrong way around. It should be while ans.to_i >= 10 or better yet, because Ruby is awesome, until ans.to_i < 10.

In this simple case, there is however no need for recursion. You can just do:

def myF
  puts "Please select a position 0 to 9"
  ans = 11 # We set the ans value too large, so that the `until` will trigger
  ans = gets.chomp.to_i until ans < 10 # We keep getting `ans` values until it is smaller than `10`
  puts "You choose #{ans}"
end

Sorry for typos and not so optimal explanations ahead… I’m typing this on my mobile…

Recursion means to call the function itself over and over again. Usually we define a success case to break the recursion and not get an infinite loop.

Your wording implies that your success case is when the user entered a number from 0 to 9, but your code says, it shall recurse on any number given smaller than 10.

In the current iteration the given number won’t change after a deeper level of recursion has resolved successfull. This is why you encounter an infinite loop with your code.

Therefore let me start with giving away some hints.

  • Do not recurse from a loop which condition is based on an external value (in general you rarely want to do a loop in a recursive function, as recursion is just another way to write loops)
  • Use if to check for the success condition
  • Report back whether those hints were helpful and if you were able to get something working. I’m eager to get deeper into this with you.

@Ohm Thank you for the answer. Your code does exactly what I need except that in case of a wrong number (outside the range of 0 to 9) it doesn’t display the message again which was the reason I wanted to use recursion. Any ideas how to keep posting the message until a valid choice is made?

Hello @NoobZ
Thank you for the explanation. Only after I submitted the problem I realized that my wording was not consistent with the code. I also understand the reason for using "if checks " instead of a recursion but for me it was more of a technical curiosity (since I never got to use recursion before) whether it is possible to use recursion in a problem like this.
Again I want the my program to ask for an input and then to “sit” and not continue until the user makes a “valid” choice.
For example: Please type your fruit of preference: apples or oranges? And if the user types “bananas” I want to repeat the question until there is a valid input.
Is that possible with recursion?

Thanks

I tried to be smart in my solution. Maybe too smart. :wink:

You can do

def myF
  ans = 11 # We set the ans value too large, so that the `until` will trigger
  until ans < 10 # We keep getting `ans` values until it is smaller than `10
    puts "Please select a position 0 to 9"
    ans = gets.chomp.to_i 
  end
  puts "You choose #{ans}"
end

This will puts the message once every time it fails - and once at the beginning.

2 Likes

That’s it! Awesome! Thanks!

So you did not understand. if is not a replacement for recursion, if is a tool for recursion. while is a replacement.

Lets say we want to count from an arbitrary x backwards to 0, then we do this:

def backwards(x)
  return if x < 0
  puts x
  backwards(x - 1)
end

Understanding recursion is important, as it will make it a lot easier to deal with recursive data later on that is not flat (trees and graphs come to my mind).

Also it is important that you understand why your original code stuck in infinitely calling myF once you enter a value out of the valid range. I explained already above. Without understanding the issue, I might assume that there will be scoping issue you stumble over later on.

I don’t quite get how you are using – return — in your example.
What exactly is return referring to?

To its surrounding function. It’s just a common return…