-1

I am following chapter 2 of Understanding Computation to build a simple Ruby interpreter:

At some point after Class Assign, Variable and Number are defined (which I think is actually irrelevant), I do this in irb

irb(main):001:0> statement = Assign.new(:x, Add.new(Variable.new(:x), Number.new(1)))

=> <<x = x + 1>>

irb(main):002:0> environment = { x: Number.new(2) }

=> {:x=><<2>>}

irb(main):003:0> statement, environment = statement.reduce(environment)

=> [<<x = 2 + 1>>, {:x=><<2>>}]

and everything goes perfectly.

But when I declare statement and environment in .rb file:

def statement
    Assign.new(:x, Add.new(Variable.new(:x), Number.new(1)))
end

def environment
    { x: Number.new(2) }
end

something goes wrong when I type statement, environment = statement.reduce(environment) in irb:

irb(main):001:0> statement, environment = statement.reduce(environment)

NoMethodError: undefined method reduce for nil:NilClass from (irb):1 from /usr/bin/irb:12:in <main>

I don't know if the bug is on the way I declare statement or environment?

How could I declare the variable in .rb file?

I check this question and @variable_name doesn't seems to work with a non-string variable.

Community
  • 1
  • 1
Rahn
  • 4,787
  • 4
  • 31
  • 57
  • Looking at the code that you've shown it looks to me like you might have a scoping problem. Are you doing anything with the return from Assign.new that will allow `environment` to see it or do you simply allow it to go out f scope? – David Hoelzer Dec 26 '15 at 11:47

1 Answers1

1

The two pieces of code are completely different. The first uses variables, the second uses methods.

Variables are defined like this:

name_of_var = initialization_expression

Methods are defined like this:

def name_of_method(parameter_one, parameter_two)
  body_expression
end

I don't know if the bug is on the way I declare statement or environment

Yes.

This is what happens:

def statement
  Assign.new(:x, Add.new(Variable.new(:x), Number.new(1)))
end

def environment
  { x: Number.new(2) }
end

Here you define two methods, statement and environment. What they do is actually irrelevant because you never call them.

statement, environment = statement.reduce(environment)

Here, you declare two variables, statement and environment. You initialize them by calling reduce on the contents of the variable statement (which is nil, because statement hasn't been initialized yet (we are just in the process of initializing it, after all) and un-iintialized variables evaluate to nil in Ruby) passing as an argument the contents of the variable environment (which is also nil for the same reason).

You never call the methods you defined, because they are being shadowed by the two variables you created with the same names.

how could I solve it?

You already did: the first piece of code works.

Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653