1

I have written a small ruby function that alters a string variable according to its length. The printout shows that in the function, the variable is altered -- however it is always reset to its default when it is called later in the program.

#ruby variable test
def mrn_value(mrn_length, mrn)
if mrn_length < 7 
 case mrn_length
 when 6
 mrn = '0' << mrn
 return mrn
 when 5
 mrn = '00' + mrn
 return mrn 
 when 4
 mrn = '000' + mrn
 return mrn 
 when 3
 puts mrn
 mrn = '0000' + mrn
 puts mrn
 return mrn 
 when 2
 mrn = mrn.to_s
 puts 'mrn of 2 length' #prints 'mrn of 2 length'
 mrn = '00000' + mrn
 puts 'mrn altered in case statement: ' + mrn #prints 'mrn altered in case statement 0000012'
 when 1
 mrn = '000000' + mrn
 return mrn 
 end
 end 
 end
mrn = 12
mrn = mrn.to_s
mrn_length = mrn.length
mrn_value(mrn_length, mrn)
puts 'Returned MRN: ' + mrn #prints '12'

What I need is for the returned MRN to be the altered MRN. thoughts?

asked Oct 7, 2014 at 21:41

5 Answers 5

2

I recommend you read more about why Ruby is 'pass-by-value'. In mrn = 12, mrn is a variable, a pointer that points to an object which is 12 in this case.

When you're passing mrn to mrn_value, you're passing a COPY of that pointer. Now you have 2 pointers pointing to the same object. The moment you do mrn = '00000' + mrn you're telling the second pointer to no longer point to 2 but to whatever else is on the right side. Your original mrn pointer outside of the mrn_value method still points to 2, as you can see.

You can read more on Posts on StackOverflow on why Ruby is 'pass by value'. To give you a simplified version to demonstrate:

a = 1
def will_a_be_changed(a)
 a = 2
 puts a #=> 2
end
will_a_be_changed(a)
puts a #=> 1
answered Oct 7, 2014 at 22:00
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the explanation & the example. I thought that the "return" command would cause the altered variable to be available outside of the function, am I mistaken?
Ruby is pass-by-value, not pass-by-reference. You cannot pass variables, variables aren't objects. You can only pass objects.
@Elisa - that will work if you follow rohit89's example below. You'll have to reassign it to mrn.
@Phil Oh, I see. I'm used to doing this in PHP, where I would 'return' a value for use and have it be assigned already.
2

What's wrong with reassigning the value?

mrn = mrn_value(mrn_length, mrn)

answered Oct 7, 2014 at 21:47

Comments

2

In all lines like:

mrn = '0' << mrn

You are not doing what you thing you're doing. You are creating a new string here and you assign it to a local variable. This local variable was pointing to some string object which has been passed to this method, after this assignment it is pointing to some other object, which is lost after method is executed.

Instead, you need to replace the object this variable is pointing:

mrn.replace('0' + mrn)

or

mrn.prepend('0')

Note this is only possible because strings are mutable, this will not work for Fixnums or Symbols.

Now when this is explained, why not simply use existing string methods like for example rjust?

mrn = '12'
mrn = mrn.rjust(7, '0')
answered Oct 7, 2014 at 21:47

1 Comment

thanks for the suggestion -- i tried using mrn.rjust, but for some reason in that format it does not write to the .csv that I am having store results. it does save them in the other format. shrugs
1

You could do something like this, if I understand your requirements correctly:

#ruby variable test
def mrn_value(mrn_length, mrn)
 value = ""
 if mrn_length < 7 
 case mrn_length
 when 6
 value = '0' << mrn
 when 5
 value = '00' + mrn
 when 4
 value = '000' + mrn
 when 3
 puts mrn
 value = '0000' + mrn
 puts mrn
 when 2
 value = mrn.to_s
 puts 'mrn of 2 length' #prints 'mrn of 2 length'
 value = '00000' + mrn
 puts 'mrn altered in case statement: ' + mrn #prints 'mrn altered in case statement 0000012'
 when 1
 value = '000000' + mrn
 end
 end
 value
end
mrn = 12
mrn = mrn.to_s
mrn_length = mrn.length
mrn = mrn_value(mrn_length, mrn)
puts 'Returned MRN: ' + mrn 
answered Oct 7, 2014 at 21:50

Comments

0

The problem is caused by ruby passing method parameters by value rather than by reference (ish).

If you change mrn to @mrn it'll work. The @ makes it an instance variable which I'm guessing in this case makes it available throughout the module.

answered Oct 7, 2014 at 21:55

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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