2

I have two methods in my ruby class and I am trying to modify a local variable string on another method,

def modify_test
    value = 'initial stringg'
    remove_last_char(value)
    puts value
end

def remove_last_char(value)
    value = value[0...-1]
    puts value
end

The remove_last_char method prints initial string but modify_test method prints initial stringg even after invoking the remove_last_char. I don't think that value = value[0...-1] is getting referenced to the parameterized value.

  1. Can I point to the same value after the modification of value on the remove_last_char method?
  2. Are there any alternatives to achieve such a case?

I have gone through this question as well and that has a similar case but not the duplicate one :)

1 Answer 1

4

Ruby's methods use the "call by reference value" evaluation strategy, also called "call by object sharing" or "call by pointer". This means that the parameter in a function call is evaluated, and that value is passed (as an object reference); not the variable itself. The value is then assigned to a local variable in the method. This new variable is distinct from a variable that may have been used to pass the parameter in the first place, so assignment to the local variable does not affect the value of the original variable. But the value itself can be mutated (its contents modified) if the object permits such modification.

Thus, there are two things you can do.

  • You can return the new value, and trust the caller to then assign the return value to a variable in the calling context:

    def modify_test
        value = 'initial stringg'
        value = remove_last_char(value)
        puts value
    end
    
    def remove_last_char(value)
        value[0...-1]
    end
    
  • If the string is mutable (i.e. it is not frozen), you can change the contents of the string without having to change the assignment of the variable:

    def modify_test
        value = 'initial stringg'
        remove_last_char(value)
        puts value
    end
    
    def remove_last_char(value)
        value[-1..] = ''
    end
    
Sign up to request clarification or add additional context in comments.

6 Comments

I was looking for something like second strategy as it does not require to return and re-assign the value. You can remove the first strategy - if you give some more explanation on the second option would much be appreciated!
The "second strategy" only works on some objects though. For example, you can't use it with numbers, booleans... Also, what kind of "some more explanation" do you need? It's like telling a cook "this soup needs something more". More salt? More meat? More water? :)
Alternatively value.slice!(0...-1). It's similar to value[0...-1] (aka values.slice(0...-1)) but mutates the receiver. String#[]= is a bit odd but that's just my opinion.
Sorry to mislead the question. I know its already delicious soup - I just wanted to know the recipe ... as I am a newbie on ruby and value[-1..] = '' seems a bit vague to me..
The -1.. range is superfluous because it only spans one character. You can just give the character's index instead, i.e. value[-1] = ''. Or alternatively value.slice!(-1) which avoids the creation of an empty string.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.