recursive function problem

M

Maurizio De santis

Hi all!

I have a problem with this function, which should return a formatted
string of an hash given as an argument:

def show_params(params, tabs_num)
params_str = String.new if tabs_num == -1
tabs_num++
params.each do |key, value|
tabs_num.times { params_str += "\t" }
if params.class != value.class
params_str += "#{key} => " + value.to_s + "\n"
else
params_str += "#{key} => \n"
show_params(value, tabs_num)
end
end
return params_str
end

I call the function with this:
show_params(params, -1)

obtaining thish error (in Rails):

undefined method `+@' for {"action"=>"edit", "id"=>"51",
"controller"=>"items"}:HashWithIndifferentAccess

I cannot guess the reason! Any idea?

Thanks!
 
J

Josh Cheek

[Note: parts of this message were removed to make it a legal post.]

On Tue, Oct 20, 2009 at 4:32 AM, Maurizio De santis <
Hi all!

I have a problem with this function, which should return a formatted
string of an hash given as an argument:

def show_params(params, tabs_num)
params_str = String.new if tabs_num == -1
tabs_num++
params.each do |key, value|
tabs_num.times { params_str += "\t" }
if params.class != value.class
params_str += "#{key} => " + value.to_s + "\n"
else
params_str += "#{key} => \n"
show_params(value, tabs_num)
end
end
return params_str
end

I call the function with this:
show_params(params, -1)

obtaining thish error (in Rails):

undefined method `+@' for {"action"=>"edit", "id"=>"51",
"controller"=>"items"}:HashWithIndifferentAccess

I cannot guess the reason! Any idea?

Thanks!
In Ruby ++ isn't defined
tabs_num++
should instead use += like this
tabs_num+=1

-----

Also, you can specify default values for parameters, so
def show_params(params, tabs_num)
could be rewritten:
def show_params(params, tabs_num = -1)

Which would allow you to take the current call of
show_params(params, -1)
and instead call it like this
show_params(params)

This allows you to keep internal knowledge inside, people calling the
function shouldn't have to know that they need to initialize some internal
variable to -1

-----

You still have an issue in that you only initialize the variable params_str
on the first call to the function, so in the future calls, this variable is
not defined, and you cannot then concatenate additional string to it. To
resolve this, remove the if on it, so that it is initialized for each
recursive call. Then you actually get some output. Now, what to do with this
variable? Well, we want to take the results of the recursive calls, and add
them into the current string. Notice right now you are saying

params_str += "#{key} => \n"
show_params(value, tabs_num)

But this second line does nothing, it calculates the substring, then returns
it but nothing receives it or does anything with it. So instead, try

params_str += "#{key} => \n"
params_str += show_params(value, tabs_num)

-----

Anyway, here is what I have, and it does what I think you are wanting it to
do:

def show_params( params , tabs_num = -1 )
tabs_num += 1
params_str = String.new
params.each do |key, value|
params_str << "\t" * tabs_num
if value.is_a? Hash
params_str << "#{key.inspect} =>\n#{show_params value , tabs_num}"
else
params_str << "#{key.inspect} => #{value.inspect}\n"
end
end
params_str
end

params = { :abc => 'def' , 3 => {1=>true,2=>{'xyz'=>/xyz/}} , 5 => 5 }
puts show_params(params)

-----

I don't really know how to read the docs, but this seems like the kind of
thing that I would expect the pp library to do for us. I tried about 15
different ways to get it to do this, and only ever got the same as the
default p function. If pp does address this issue, can someone explain how
to get it to work?
 
A

Aurora S.r.l.

I don't really know how to read the docs, but this seems like the kind
of
thing that I would expect the pp library to do for us. I tried about 15
different ways to get it to do this, and only ever got the same as the
default p function. If pp does address this issue, can someone explain
how
to get it to work?

Bravo!!!

I come from PHP and my first need was a function similar to print_r() (I
develop with Rails 2 now), so I just started (very lazily :) ) to write
it... and you are giving me the code, written with a ruby philosophy!
Many thanks!!!!! Anyway, it's less bizarre that a such modern language
doesn't implement in native libraries these prehistorical functions, I
think...
 
J

Josh Cheek

[Note: parts of this message were removed to make it a legal post.]

Bravo!!!

I come from PHP and my first need was a function similar to print_r() (I
develop with Rails 2 now), so I just started (very lazily :) ) to write
it... and you are giving me the code, written with a ruby philosophy!
Many thanks!!!!! Anyway, it's less bizarre that a such modern language
doesn't implement in native libraries these prehistorical functions, I
think...
Well, if you just need to look at it, inspect usually works. It's just when
you get long lists or lots of nesting, using inspect sometimes still isn't
enough. I really think that pp should do it, but can't figure out how.

If I were doing it, myself, I would monkey patch it into the hash class,
something like this:

class Hash
def readable( tabs_num = -1 )
tabs_num += 1
self.inject(String.new)do | str , ( key , value ) |
rhs = value.is_a?(Hash) ? "\n#{value.readable tabs_num}" :
"#{value.inspect}\n"
str << "#{"\t" * tabs_num}#{key.inspect} => #{rhs}"
end
end
end

params = { :abc => 'def' , 3 => {1=>true,2=>{'xyz'=>/xyz/}} , 5 => 5 }
puts params.readable

But some people here hate monkey patching, so I didn't post that earlier.

Also, I found that YAML gives something very similar to what we are doing
here, with

require 'yaml'
puts params.to_yaml
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,050
Latest member
AngelS122

Latest Threads

Top