Question

Say I'm writing a division algorithm script:

def current_trace
  puts "Counter: #{counter}; r: #{r}; q: #{q}"
end

r = a
q = 0
counter = 0

while r >= d
  current_trace
  r = r - d
  q = q + 1
  counter += 1
end
current_trace

I expected that calling current_trace would output the value of counter, r and q. But instead I get:

in current_trace': undefined local variable or methodcounter' for main:Object (NameError)

  1. What's the problem here?
  2. How should I write a method that will output the values of some variables named counter, r, and q, at any given point (preferably without passing arguments to the method)?
Was it helpful?

Solution 2

The correct thing is to write your method so it accepts parameters:

def current_trace(c, r, q)
  puts "Counter: #{ c }; r: #{ r }; q: #{ q }"
end

Then call it like:

d = 1          
r = 5          
q = 0          
counter = 0    

while r >= d                      
  current_trace(counter, r, q)    
  r = r - d                       
  q = q + 1                       
  counter += 1                    
end                               

current_trace(counter, r, q) 

Which results in:

Counter: 0; r: 5; q: 0
Counter: 1; r: 4; q: 1
Counter: 2; r: 3; q: 2
Counter: 3; r: 2; q: 3
Counter: 4; r: 1; q: 4
Counter: 5; r: 0; q: 5

(I tweaked your variable names because your code won't work because you don't show where a and d come from, but that's beside the point.)

You can use @instance, $global or CONSTANTs but those are playing games with variable scoping, which can cause problems when you accidentally change them in some method, often because you mistype them or leave off the sigil (@, $) and inadvertently create a local variable that doesn't change the one you want. Having to use @var, or $var at the main level, just to get your code to work, is a pretty good sign you're doing something wrong actually.

OTHER TIPS

In this case, your current_trace method is so simple that it does not worth making it a method. But looking at your code, the reason you did so is probably because it appears more than once. That is the bad part of your code that should be improved. By reconsidering the timing of the conditional and puts, you can avoid calling puts in two different locations.

counter, q, r = 0, 0, a
loop do
  puts "Counter: #{counter}; q: #{q}; r: #{r}"
  break if r < d
  counter += 1
  q += 1
  r -= d
end

I think I figured it out. counter, r and q were (apparently) only local to main's scope. I changed them to the globals $counter, $r and $q, and now I have access to them in my method.

(Realized this here: https://stackoverflow.com/a/9389532/1468130)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top