0

I'm new to Ruby and Rails, coming from C. I'd like to know how update a value in a method, like a pointer in C when I send the address as parameter.

def upd_value(str)
    str = "salut"
end

str = "bonjour"
upd_value(str)
puts str

I can use replace to change it, which worked. It was a mistake though because I used a string as the example, and I want to update a Array. Any idea?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
albttx
  • 3,444
  • 4
  • 23
  • 42
  • What do you want to do to the array? There are lots of ways to alter arrays. – Joseph Jun 15 '15 at 17:36
  • 1
    Since you have several responses handling strings, you should open a new question asking about arrays. Future visitors are going to be confused, because now you're asking two different things. – Kristján Jun 15 '15 at 17:41
  • This won't work for the exact same reason that it doesn't work in C, either: both languages are strictly pass-by-value. – Jörg W Mittag Jun 15 '15 at 19:36

5 Answers5

1

You can use String#replace.

def change_str(str)
  str.replace 'goodbye'
end

str = 'hello'
change_str(str)
puts str
#=> goodbye
Kristján
  • 18,165
  • 5
  • 50
  • 62
1

In Ruby, (almost) every variable is in fact a reference/pointer to an object, e.g.

a = [0, 1, 23]
b = a
a << 42
p b

will give [0, 1, 23, 42] because a and b are pointing to the same object.

So in fact, you are using pointers all the time.

If you want to do pointer arithmetic as in C, this is not possible with Ruby.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Zain Zafar
  • 1,607
  • 4
  • 14
  • 23
0

The str within upd_value is in its own scope and won't affect the one outside it. You need to explicitly reassign it:

str = upd_value(str)

Joseph
  • 760
  • 1
  • 4
  • 9
0

This should work

def upd_value(str = nil)
    str = str || "test"
end

str = "bonjour"
puts upd_value(str)
aashish
  • 2,453
  • 1
  • 21
  • 19
0

See "Is Ruby pass by reference or by value?" on how Ruby handles arguments.

Generally speaking, you can pass an object to a method, modify the object attributes within that method and the modifications will still be there after the method returns.

What happens in your example though is shadowing of the parameter str by the local variable str. Since you make an assignment to the local variable and not to the passed argument, the modification is lost as soon as the method returns and its local scope is destroyed.

Your options are either return a value from the method and use it outside like this:

def my_method(str)
  str + 'salut' # a new instance of string is created and returned
end

str = 'hey, '
str = my_method(str)

puts str # outputs 'hey, salut'

or use a mutator method such as #replace

def my_method(str)
  str.replace('salut') # same string instance is reused
end

str = 'whatever'
my_method(str)

puts str # outputs 'salut'

You can handle easily handle passed arrays inside a method by changing values using index like so:

def my_method(array)
  array[15] = 10
end

Or add items via <<:

def my_method(array)
  array << 10
end

Or call its methods like this:

def my_method(array)
  array.delete(0)
end

All these modifications will be kept since the outer scope holds the reference to the same array instance you're operating on within the method.

Community
  • 1
  • 1
Nic Nilov
  • 5,056
  • 2
  • 22
  • 37