2014-10-07 28 views
1

我寫了一個小的ruby函數,它根據字符串的長度改變字符串變量。打印結果顯示,在該函數中,該變量被更改 - 但是在稍後在程序中調用它時,它總是被重置爲默認值。如何從Ruby函數中返回值以用於程序的其餘部分

#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' 

我需要的是返回的MRN是改變的MRN。想法?

回答

3

我建議你閱讀更多關於爲什麼Ruby是'傳遞值'。在mrn = 12中,mrn是一個變量,指向一個在這種情況下爲12的對象的指針。

當你通過mrnmrn_value時,你傳遞了該指針的COPY。現在你有兩個指針指向同一個對象。當你做mrn = '00000' + mrn時,你告訴第二個指針不再指向2,而是指向右側的任何其他指針。正如你所看到的,你原來的mrn指針在mrn_value方法之外仍然指向2。

你可以在Posts on StackOverflow on why Ruby is 'pass by value'瞭解更多。給你一個簡化的版本來演示:

a = 1 

def will_a_be_changed(a) 
    a = 2 
    puts a #=> 2 
end 

will_a_be_changed(a) 
puts a #=> 1 
+0

感謝您的解釋和例子。我認爲「返回」命令會導致修改後的變量在函數外部可用,我誤解了嗎? – Elisa 2014-10-08 02:29:17

+0

Ruby是通過值傳遞的,而不是通過引用傳遞。你不能傳遞變量,變量不是對象。你只能傳遞對象。 – 2014-10-08 08:16:34

+1

@Elisa - 如果你按照下面的rohit89的例子,這將工作。你必須重新分配給mrn。 – Phil 2014-10-08 10:23:04

3

重新分配值有什麼問題?

mrn = mrn_value(mrn_length, mrn)

3

在所有的線路,如:

mrn = '0' << mrn 

你沒有做你正在做什麼,你的事。您正在此處創建一個新字符串,並將其分配給本地變量。這個局部變量指向一個已經傳遞給該方法的字符串對象,在這個賦值之後它指向另一個對象,這個對象在方法執行後會丟失。

相反,你需要更換對象這個變量指向:

mrn.replace('0' + mrn) 

mrn.prepend('0') 

注意這僅僅是可能的,因爲字符串是可變的,這不會對Fixnums或符號工作。

現在,當解釋這個時,爲什麼不簡單地使用現有的字符串方法,例如rjust

mrn = '12' 
mrn = mrn.rjust(7, '0') 
+0

感謝您的建議 - 我試過使用mrn。rjust,但由於某種原因,該格式不會寫入存儲結果的.csv文件。它會以其他格式保存它們。 *聳聳肩* – Elisa 2014-10-08 14:27:41

1

你可以做這樣的事情,如果我正確地理解你的要求:

#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 
0

問題是由紅寶石按值傳遞方法參數而不是引用(ish)引起的。

如果您將mrn更改爲@mrn它將起作用。 @使它成爲一個實例變量,我猜在這種情況下它可以在整個模塊中使用它。

相關問題