Bartek Gładys Bartek Gładys - 2 months ago 15
Ruby Question

Overwrite a variable without repeating the name

Is there a method to overwrite variable without copying its name? For example, when I want to change

my_var = '3'
to an integer, I must do something like this:

my_var = my_var.to_i


Is there way to do this without copying variable's name? I want to do something like this:

my_var = something_const.to_i


For numbers there exists
+=
,
-=
etc, but is there universal way to do this for all methods ?

Answer

There is no way to covert a string to an integer like that, without repeating the variable name. Methods such as String#upcase! and Array#flatten! work by mutating the object; however, it is not possible to define such a method like String#to_i! because we are converting the object to an instance of a different class.

For example, here is a (failed) attempt to define such a method:

# What I want to be able to do:
# my_var = "123"
# my_var.to_i! # => my_var == 123

class String
  def to_i!
    replace(Integer(self))
  end
end

my_var = "123"
my_var.to_i! # TypeError: no implicit conversion of Fixnum into String

...And even if this code were valid, it would still offer no performance gain since a new object is still being created.

As for your examples of += and -=, these are in fact simply shorthand for:

x += 1
# Is equivalent to:
x = x + 1

So again, there is no performance gain here either; just slightly nicer syntax. A good question to ask is, why doesn't ruby support a ++ operator? If such an operator existed then it would offer performance gain... But I'll let you research for yourself why this is missing from the language.

So to summarise,

is there universal way to do this for all methods?

No. The special operators like +=, -=, |= and &= are all predefined; there is no "generalised" version such as method_name=.

You can also define methods that mutate the object, but only when appropriate. Such methods are usually named with a !, are called "bang-methods", and have a "non-bang" counterpart. On String objects, for example, there is String#capitalize! (and String#capitalize), String#delete! (and String#delete), String#encode! (and String#encode), .... but no String#to_i! for the reasons discussed above.

Comments