0

I'm new to programming, especially in Ruby so I've been making some basic projects. I have this code and as far as I know, it should work, but it gives results that I don't expect

The program takes a and B and returns a^b. I did this as a programming exercise, hence why I didn't just go a**b.

class Exponate
  attr_accessor :args

  def initialize args = {}
    @args = args
    @ans = nil
  end

  def index
    @args[:b].times {
      @ans = @args[:a] * @args[:a]
    }
    puts @ans
  end
end

e = Exponate.new(:a => 32, :b => 6)
e.index

e.args[:a] = 5
e.index

Returns

1024     # Should be 1_073_741_824
25       # Should be 15_625

But they are definitely not that

2 Answers2

1

You can write like this:

class Exponate
  attr_accessor :args, :ans

  def initialize args = {}
    @args = args
  end

  def index
    @ans = 1 # multiplication will start from 1
    @args[:b].times {
      @ans *=  @args[:a] #same as @ans = @ans * @args[:a]
    }
    puts @ans
  end
end
Ilya
  • 13,337
  • 5
  • 37
  • 53
  • Thanks! The only thing I changed after this was moving @ans = 1 out of initialization and into index because otherwise it doesn't reset. – Soviet Ketchup Feb 13 '16 at 11:07
1

@ans = @args[:a] * @args[:a] will return the same value, no matter how many times called, you need to reference the accumulator variable in some way to make use of the cycle.

Using an instance variable for a local does not seem right - their lifetime is longer, so after method exits they cannot not be collected if the whole object is still referenced somewhere. Also the @s are more error-prone - if you make a typo (for example - @asn instead of @ans), you'll get nil instead of NameError, it may be harder to debug, so better to write this way:

def index
  ans = 1
  args[:b].times {
    ans *= args[:a]
  }
  puts ans
end

For loops with an accumulator in ruby it's better to use Enumerable#inject:

@ans = @args[:b].times.inject(1){|acc,v| acc * @args[:a]}

this way it's less likely to forget initialisation.

Vasfed
  • 18,013
  • 10
  • 47
  • 53