2

I know a bit about ruby way to handle objects and references. The replace stuff, ect ...

I know it d'ont work on fixnum, cause the var is the fixnum. But i wish to change the value of a fixnum inside a function, and that the value changed in the ouside var.

How can i do this ?

I guess i can use a string like this "1" but that's quite dirty.

Perello
  • 633
  • 1
  • 7
  • 22
  • 6
    Please provide code for what you are trying to do. Your question is confusing. – Gazler Feb 06 '12 at 21:18
  • possible duplicate of [Generic way to replace an object in it's own method](http://stackoverflow.com/questions/9130994/generic-way-to-replace-an-object-in-its-own-method) – Marc-André Lafortune Feb 07 '12 at 01:17

3 Answers3

5

Ruby will always pass-by-reference (because everything is an object) but Fixnum lacks any methods that allow you to mutate the value. See "void foo(int &x) -> Ruby? Passing integers by reference?" for more details.

You can either return a value that you then assign to your variable, like so:

a = 5
def do_something(value)
    return 1 #this could be more complicated and depend on the value passed in
end
a = do_something(a)

or you could wrap your value in an object such as a Hash and have it updated that way.

a = {:value => 5}
def do_something(dict)
  dict[:value] = 1
end
do_something(a) #now a[:value] is 1 outside the function

Hope this helps.

Community
  • 1
  • 1
tjarratt
  • 1,692
  • 9
  • 17
  • 5
    Not quite. Everything is an object and it is always pass by value but the value is always a reference. The problem is that there are no mutating methods for Fixnum so you can't change the value of a Fixnum. You can change a String that is passed to a method though: `def pancakes(str) str << ' pancakes' end` and then `s = 'have some';pancakes(s); puts s` for example. The solutions make sense though. – mu is too short Feb 06 '12 at 21:39
  • AH, right, thanks. It's too easy to treat immutable objects as though they are just simple values. – tjarratt Feb 06 '12 at 22:53
  • 1
    @tjarratt: That's because when they are immutable it is impossible to distinguish whether the value was passed directly or a reference to the value was passed. You can only observe the difference when the object is mutated outside of the method, but immutable objects can't be mutated. – Jörg W Mittag Feb 07 '12 at 01:16
  • Thanks for the idea. I will use an array. – Perello Feb 08 '12 at 09:24
  • i really wish this answer said pass reference by value, to avoid confusion – user3125280 Aug 24 '14 at 14:24
4

You could pass an array with a single number, like [1], or a hash like {value: 1}. Less ugly than a string, as your number itself remains a number, but less overhead than a new class...

glenn mcdonald
  • 15,290
  • 3
  • 35
  • 40
  • But Arrays are objects, how can there be less overhead for creating an Array than just a bare object? Is there some crazy optimization for Arrays in ruby implementations? – tjarratt Feb 09 '12 at 22:21
  • I meant implementation overhead, not execution overhead. And I was comparing these with creating a new class, like in Semyon's answer. Also, in Ruby we call {}s hashes, not objects... – glenn mcdonald Feb 10 '12 at 03:21
2

When I was building a game I had the same problem you have. There was a numeric score that represented how many zombies you've killed and I needed to manually keep it in sync between Player (that incremented the score), ScoreBar and ScoreScreen (that displayed the score). The solution I've found was creating a separate class for the score that will wrap the value and mutate it:

class Score
  def initialize(value = 0)
    @value = value
  end

  def increment
    @value += 1
  end

  def to_i
    @value
  end

  def to_s
    @value.to_s
  end
end
Simon Perepelitsa
  • 20,350
  • 8
  • 55
  • 74
  • It probably would be a good idea to use `SimpleDelegator`. See my answer to this similar question: http://stackoverflow.com/questions/9130994/generic-way-to-replace-an-object-in-its-own-method – Marc-André Lafortune Feb 07 '12 at 04:52
  • In this simple case I'd prefer explicitly exposing the methods I need. But using Simple Delegator might be a good choice if you need an object to have all numeric methods. – Simon Perepelitsa Feb 07 '12 at 18:28