user918069
user918069

Reputation: 109

trouble with variables in a method

In a previous question ( Is a method in ruby similar to a subroutine?) I asked about methods in Ruby. Now, writing my first ever method, I've clearly run into trouble with the scope of variables. The program below interprets and runs fine when I don't call the method learn. That is, if I remove the call learn(2) in line 33, everything works fine and it doesn't seem to matter that I use various variables (e.g. stimulus[]) both in the main program and in the method. But when I insert the call (and use it by pushing the u key), I get the message below, apparently indicating it's not alright to use stimulus in the method.

brain.rb:26:in `block in learn': undefined local variable or method `stimulus' for main:Object (NameError)
    from brain.rb:25:in `each'
    from brain.rb:25:in `learn'
    from brain.rb:33:in `ucr'
    from brain.rb:69:in `<main>'

But I NEED to use it (and brain) there, and with their present values as determined by the main program. All the answers to questions about scope that I've come across seem to go the other way, i.e, problems using variables in a method elsewhere. I thought of making stimulus and brain global, but apparently that is a no-no. How do I tell the method to use variables from the program?

Ps. Once this method works, I will be calling it from six other places in the program.

require 'matrix'
class Matrix
  def []=(i, j, x)
    @rows[i][j] = x
  end
end #code to allow putting individual elements in matrix at i,j
def read1maybe
  return $stdin.read_nonblock 1
rescue Errno::EAGAIN
  return ''
end # part of code to get keypress
brain=  Matrix[ [0,0,0,0,99,0,0,0,0,1,0],
                [0,0,0,0,0,99,0,0,0,1,0],
                [0,0,0,0,0,0,99,0,0,1,0],
                [25,0,0,0,0,0,0,1,-1,1,-99],
                [0,23,0,0,0,0,0,1,-1,1,1],
                [0,0,24,0,0,0,0,1,-1,1,1],
                [0,0,0,22,0,0,0,1,-1,1,1] ]
stimulus=Matrix.column_vector([0,0,0,0,0,0,0,0,0,0,0])
behavior=Matrix.column_vector([0,0,0,0,0,0,0])
t=500 # t=threshold
energy=50
# begin defining behavioral methods
def learn(ix)
    for j in (7..10)
    if stimulus[j]>0 && brain[ix,j] != 0 && brain[ix,j] < 99 then
        brain[ix,j]+=int(0.1 * stimulus[j]) * (99-brain[ix,j])
    end # if stim
    end # for j
end # learn
def ucr
    puts "Show UCR"
    learn(2)
end
def positive_fixer
    puts "Positive fixer"
end
def negative_fixer
    puts "Negative fixer"
end
# end defining behavioral methods

# begin main program
while(energy>0) do
(0..10).each {|n| if stimulus[n,0]>2 then stimulus[n,0]+= -2 else stimulus[n,0]==0 end}
input=false
system 'stty cbreak'
look=0
while look < 40000
  q = read1maybe
  break if q.length > 0
  look +=1
end # while look
case q
when "f" then stimulus[4,0]=9 and puts "Good!"
when "p" then stimulus[5,0]=9 and puts "Bad!"
when "u" then stimulus[6,0]=9
when "l" then stimulus[7,0]=9 and stimulus[8,0]=9 and puts "ight on"
when "c" then stimulus[9,0]=9 and puts "   BUZZZ"
input=true
end # case q
system 'stty cooked'

if input==false then (0..3).each { |n| stimulus[n,0]=rand(25)} end

behavior=brain*stimulus
if behavior[0,0] > t then positive_fixer end
if behavior[1,0] > t then negative_fixer end
if behavior[2,0] > t then ucr end
if behavior [3,0] > t then puts "show operant 1" end # and stimulus[10,0]=9
if behavior[4,0] > t then puts "show operant 2" end
if behavior[5,0] > t then puts "show operant 3" end
if behavior[6,0] > t then puts "show operant 4" end
energy += -1
# temp to test development of memory
puts brain[2,9]
end # while energy > 0
puts
puts "It's dead Jim."
# end main program

Upvotes: 1

Views: 73

Answers (1)

Todd
Todd

Reputation: 3508

stimulus and brain are declared outside of the method. You need to pass them in as parameters like so:

def learn(ix, brain, stimulus)
    for j in (7..10)
    if stimulus[j]>0 && brain[ix,j] != 0 && brain[ix,j] < 99 then
        brain[ix,j]+=int(0.1 * stimulus[j]) * (99-brain[ix,j])
    end # if stim
end # for j end # l

And edit ucr like so:

def ucr(brain, stimulus)
    puts "Show UCR"
    learn(2, brain, stimulus)
end

And invoke ucr like ucr(brain, stimulus). See the pattern? You need to add the parameters to the method definitions that use them and then pass them in when invoking the method.

Upvotes: 1

Related Questions