Take the 2-minute tour ×

Just wondering why

def move
  world_switch(@pos_X += 1, @pos_X -= 1, @pos_Y += 1, @pos_Y -= 1)

  def world_switch(do_on_north, do_on_south, do_on_east, do_on_west)
    case @facing # => 'NORTH'
    when 'NORTH'
      puts do_on_north # => 1
    when 'SOUTH'
    when 'EAST'
    when 'WEST'

Calling world_switch:

robot = Robot.new(0, 0, 'NORTH')
puts robot.instance_variable_get("@pos_X") #=> 0

results in changing nothing, I would like to increase or decrease instance variable @pos_X or @pos_Y

This is my initialize method

def initialize(pos_X, pos_Y, facing)

and that's how I create an instance of the class robot = Robot.new(0, 0, 'NORTH')

All help will be appreciated

share|improve this question
How do you call world_switch? The one above cannot run. And world_switch should not defined like that. Since it accepts only instance variables as parameters, we can omit them all. The self can provide access to them. –  halfelf Sep 27 '12 at 9:31
1. It is better to use symbols rather than strings for switches. 2. You code will thrown an error because world_switch is called before it is defined. –  sawa Sep 27 '12 at 9:34
updated a question, could you please review –  Jackie Chan Sep 27 '12 at 9:39
ok, so what do you want to print? Now I get the output as 1 0, seems normal. –  halfelf Sep 27 '12 at 9:45
add comment

3 Answers

up vote 2 down vote accepted

The explanation for the current behaviour is as Chowlett described, but did you intend for your @pos_X += 1, @pos_X -= 1 etc in move to be blocks of code and then for exactly one of these to be called from world_switch depending on which way the robot is facing?

If so, move needs to be declared like this

def move

and then in world_switch you can do something like

case @facing # => 'NORTH'
    when 'NORTH'
    when 'SOUTH'
share|improve this answer
That would indeed make the current code work. I'm not sure it's the best way of doing it, though; do you really need world_switch to be so general that you can pass in what "step NORTH" means? –  Chowlett Sep 27 '12 at 10:27
@Chowlett Agreed. It does seem overly complicated. Something along the lines of Matt's answer would be a nice, simple solution. It depends on whether the exercise is intended to be an example of a more general point, and also whether the OP is a bit unclear on at what point evaluation takes place when parameter passing. –  mikej Sep 27 '12 at 10:45
Thanks Mikej, Procs... –  Jackie Chan Sep 28 '12 at 0:17
add comment

It does nothing because of the way you call world_switch. Ruby will evaluate each of the expressions you're passing as parameters before the call.

So, you call move with (say), @pos_X and @pos_Y both equal to 0. The Ruby does:

@pos_X += 1 # => @pos_X = 1; param 1 will be 1
@pos_X -= 1 # => @pos_X = 0; param 2 will be 0
@pos_Y += 1 # => @pos_Y = 1; param 3 will be 1
@pos_Y -= 1 # => @pos_Y = 0; param 4 will be 0

world_switch(1, 0, 1, 0)

Then world_switch switches based on @facing, and simply returns the value of the appropriate parameter. It doesn't change the instance variables at all.

I'm not sure I explained that all that clearly. Let me know if you need clarification.

share|improve this answer
Explanation is good, thanks –  Jackie Chan Sep 28 '12 at 0:13
add comment

Adding to Chowlett's and mikej's answers (which nicely explain why your code isn't working). You could try something like this:

class Player
  def initialize(position)
    @position = position

  def move(direction)
    case direction
    when :north
      @position[:x] += 1
    when :south
      @position[:x] -= 1
    when :east
      @position[:y] -= 1
    when :west
      @position[:y] += 1

player = Player.new({:x => 0, :y => 0})
puts player.inspect
# => "#<Player:0x16c7ef8 @position={:x=>1, :y=>0}>"
share|improve this answer
add comment

Your Answer


