0

I apologize for the excessive length, I just wanted to make sure I actually understand what's going on here. This is a follow up on my previous two questions Does 'upcase!' not mutate a variable in Ruby? and Destructive and non destructive methods in Ruby.

def changeMe(string) 
  string + "?"
end

phrase = "how are you"
puts changeMe(phrase) #how are you?
puts phrase #how are you

When changeMe is invoked with the phrase passed in as an argument, the parameter string points to the same object as phrase. When we change the line to string + "?" we are creating a new object different from the one the string parameter points to, the same if we assigned the newly created object to a variable.

def changeMe(string) 
  string += "?"
end
phrase = "how are you"
puts changeMe(phrase) #how are you?
puts phrase #how are you

If I do this -

def changeMe(string) 
  string + "?"
  string.capitalize!
end
phrase = "how are you"
puts changeMe(phrase) #How are you
puts phrase #How are you

When changeMe is invoked with phrase passed in as an argument, the string + "?" creates a new object different from the one #capitalize! is called on in the next line. #capitalize! is called on the object that the variable phrase is referencing, the same object the string parameter points to but not the same object returned by string + ?. If we reassign it to a variable,

def changeMe(string) 
  string += "?"
  string.capitalize!
end
phrase = "how are you"
puts changeMe(phrase) #How are you?
puts phrase #how are you

string += "?" will create a new object that is assigned to a variable called string. That new object has #capitalize! called on it. The method is invoked with phrase passed in as an argument and returns a new object different from the one the variable phrase references so the original value for the variable phrase is unchanged.

Are there flaws or misconceptions in my logic. Am I accurately explaining/understanding things?

  • 1
    Note: Ruby is a case-sensitive language and capital letters have specific meaning in terms of syntax. Variables and method names should be lower-case letters. Capitals indicate constants of the form `ClassName` or `CONSTANT_NAME`. – tadman Jul 03 '20 at 20:25
  • Said a different way, In Ruby, variables and method names are snake_case, not camelCase. ItIsA readability_thing. – the Tin Man Jul 03 '20 at 22:10
  • Your understanding is perfect now. That's all you need to know! – Rajagopalan Jul 04 '20 at 00:56

1 Answers1

4

That's largely correct, but perhaps a more complicated path to understanding than necessary. In Ruby one thing that helps a lot is calling object_id on a given object to see which object it is. Every object has a unique object_id.

For example:

"test" == ("te" + "st")
# => true
"test".object_id == ("te" + "st").object_id
# => false

Or more specifically for a method that creates a new copy:

x = 'test'
y = x + '?'

x.object_id == y.object_id
# => false

You can see how in-place modifications work:

x = 'test'
y = x << '?'

x.object_id == y.object_id
# => true

Where this allows you to differentiate between in-place modifications and methods that produce new objects or copies.

Remember that every Ruby expression returns an object. If this object is not captured into a variable or used as an argument will often can be discarded if not already used.

In other words there's a huge difference between this:

def add
  1 + 2   # Computed and discarded
  :three  # The actual return value
end

And this:

def add
  1 + 2   # Computed and returned
end

Though this depends on that return value being captured, as calling the function computes the value and throws out the results again unless it's captured or used.

tadman
  • 208,517
  • 23
  • 234
  • 262