Forum: Ruby recursion and variable scope level

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Adam A. (Guest)
on 2008-11-03 12:07
Hi i want to reverse a string and at the same time check if there are
any spaces using recursion. I can get the string to reverse fine but
cant detect when theres a space

heres my code

def reverse_string a_string, an_index, spaces
  spaces = true if a_string[an_index - 1].chr == ' '
  if an_index == 1
    return a_string[an_index - 1].chr
  else
    return a_string[an_index - 1].chr + reverse_string(a_string,
an_index - 1, spaces)
  end

end

and i call it like this

spaces = false
str = "hello people"
puts reverse_string str, str.length, spaces
puts "Spaces present? #{spaces}"

spaces in the end is set as false though it should be set to true. Is
this soemthing to do with variable and parameter scope?
Adam A. (Guest)
on 2008-11-03 12:15
oh and im doing this as a way to practice recursion. Using
string.reverse would of course be the simpler way of doing this.
Brian C. (Guest)
on 2008-11-03 15:36
Adam A. wrote:
> spaces in the end is set as false though it should be set to true. Is
> this soemthing to do with variable and parameter scope?

Yes. The 'spaces' inside the method definition is a completely separate
variable to the 'spaces' you use outside, since 'def' starts a fresh
scope.

One solution is to return both str and spaces from your function:

def reverse_string a_string, an_index, spaces
  spaces = true if a_string[an_index - 1].chr == ' '
  if an_index == 1
    return a_string[an_index - 1].chr, spaces
  else
    r1, r2 = reverse_string(a_string, an_index - 1, spaces)
    spaces ||= r2
    return a_string[an_index - 1].chr + r1, spaces
  end

end

#and i call it like this

str = "hello people"
rev, spaces = reverse_string str, str.length, spaces
puts rev
puts "Spaces present? #{spaces}"

Another option is to pass a lambda, which is a function which is called
whenever a space is detected.

def reverse_string a_string, an_index, spaces
  spaces.call if a_string[an_index - 1].chr == ' '
  if an_index == 1
    return a_string[an_index - 1].chr
  else
    return a_string[an_index - 1].chr + reverse_string(a_string,
an_index - 1, spaces)
  end

end

#and i call it like this

spaces = false
str = "hello people"
puts reverse_string str, str.length, lambda { spaces=true }
puts "Spaces present? #{spaces}"
Adam A. (Guest)
on 2008-11-03 16:04
I dont believe i only just found out that functions can return more than
one variable in ruby!

How I missed that i dont know.

Thank you very much for your help on that.
Brian C. (Guest)
on 2008-11-03 16:11
Adam A. wrote:
> I dont believe i only just found out that functions can return more than
> one variable in ruby!
>
> How I missed that i dont know.
>
> Thank you very much for your help on that.

No problem.

Really they are just returning an array, and that array may (or may not)
be split at the receiver.

irb(main):001:0> def foo; return 1,2; end
=> nil
irb(main):002:0> x = foo
=> [1, 2]
irb(main):003:0> x, y = foo
=> [1, 2]
irb(main):004:0> x
=> 1
irb(main):005:0> y
=> 2
irb(main):006:0> def bar; return [1,2]; end
=> nil
irb(main):007:0> x = bar
=> [1, 2]
irb(main):008:0> x, y = bar
=> [1, 2]
irb(main):009:0> x
=> 1
irb(main):010:0> y
=> 2

I believe there's no difference whether you build an array to return, or
give multiple values to return.
This topic is locked and can not be replied to.