2016-08-31 2 views
2

Is ruby pass by reference or value?을 읽은 후에 나는 많은 것을 배웠지 만, 내가 읽는 것보다 더 많은 질문이 남아있다.이 Ruby 예제에서 값 대 전달에 대한 이해

는 다음과 같은 예를 생각해 출력 여기 Ruby is pass-by-value

이 어떻게 작동하는지 해부 내 시도이다

def foo(bar) 
    bar = 'reference' 
end 
baz = 'value' 
foo(baz) 
puts "Ruby is pass-by-#{baz}" 

:

첫째, 전역 baz에이 값을 가진다 value.

이제 foo은 매개 변수를 전달하며, 사용자가 전달한 매개 변수는 local 수준입니다. 우리가 baz 전달할 때

그러므로 reference 같다 ANOTHER baz가 있지만 그것이 value 인쇄하는 글로벌 레벨에두고 때, 결과적으로 지방 수준에있다. 내가 여기 .replace 방법은 글로벌 baz을 변경 않는 사실 위에서 말한 경우

지금 또 다른 예

def foo(bar) 
    bar.replace 'reference' 
end 
baz = 'value' 
foo(baz) 
puts "Ruby is pass-by-#{baz}" 

출력

Ruby is pass-by-reference

을 고려? 나는 이것을 정확하게 해석하고 있는가? 내 시도에서 어떤 실수를 지적 자유롭게, 나는 단서가 오른쪽 트랙에 메신저 있다면.

감사합니다.

편집

더 매직

def my_foo(a_hash) 
    a_hash["test"]="reference" 
end; 

hash = {"test"=>"value"} 
my_foo(hash) 
puts "Ruby is pass-by-#{hash["test"]}" 

답변

1

루비는 값으로 전달되지만 값은 객체에 대한 참조입니다.

첫 번째 실험에서 baz"value" 문자열에 대한 참조입니다. barfoo으로 전화 할 때 baz 사본 (즉, 참조 사본)으로 초기화됩니다.문자 "reference"을 참조하여 bar을 덮어 씁니다. bar은 사본이므로 덮어 쓰면 변경되지 않습니다. baz. 두 번째 실험에서

다시, baz 당신이 foo를 호출 할 때 "value"barbaz의 사본으로 초기화되는 문자열에 대한 참조입니다. 이번에는 bar을 덮어 쓰지 않고 그 위에 메소드를 호출하십시오. barbaz의 복사본이지만 동일한 개체 (문자열 "value")를 참조합니다. 메서드를 호출하면 해당 객체의 상태가 변경됩니다. 그런 다음 to_sbaz (간접적으로 "Ruby is pass-by-#{baz}"으로 대체 함)으로 호출하면 to_s이 새 상태를 반환합니다.

세 번째 실험은 두 번째 실험과 많이 비슷합니다. 이 메서드에서 참조 복사본이 참조하는 개체의 상태를 변경 한 다음 메서드 외부에서 원본 참조를 통해 새 상태를 다시 읽습니다.

+0

그런데 또 다른 마법 예를 추가 .. 내 뇌 이데트 get -__- – bill

+0

또 다른 마법의 예를 추가했습니다 – bill

+0

'foo'를 호출했을 때'bar'가'baz'의 복사본에 초기화되지 않았습니다. 이 첫 번째 순간에 같은 대상을 나타냅니다. –

0

그것은 실제로 메소드에 매개 변수 전달과는 아무 상관이 없습니다. 예제에서 중요한 부분을 추출했습니다.

baz = 'value' 
bar = baz 
bar = 'reference' 
puts baz 
bar = baz 
bar.replace 'reference' 
puts baz 

변수를 포인터로 생각할 수 있습니다. =을 사용하면 변수 점을 다른 점으로 만들고 원래 값은 변경되지 않고 그대로 유지되며 점을 가리키는 다른 변수를 통해 액세스 할 수 있습니다. 그러나 replace을 사용하면 변수가 가리키는 문자열의 내용이 변경됩니다.

+0

좋아 거 이것과 다른 답변을 살펴, 나는 당신이 완전히 두 번째 실험 부분에 저를 분실 – bill

0

첫 번째 경우 새 개체를 만드는 bar = 'reference'을 사용합니다. 두 번째 경우 .replace은 적용 대상을 변경합니다. 당신은 .object_id 방법으로 이것을 보장 할 수 있습니다. 예 :

def foo_eql(bar) 
    bar = 'reference' 
    puts bar.object_id 
    bar 
end 

def foo_replace(bar) 
    bar.replace 'reference' 
    puts bar.object_id 
    bar 
end 

baz = 'value' 
puts baz.object_id #Here you will get original baz object_id 
res1 = foo_eql(baz) #Here you will get printed new object_id 
res2 = foo_replace(baz) #Here you will get printed original baz object_id 
puts "foo_eql: Ruby is pass-by-#{res1}" 
=> foo_eql: Ruby is pass-by-reference 
puts "foo_replace: Ruby is pass-by-#{res2}" 
=> foo_replace: Ruby is pass-by-reference 

따라서 마법은 전혀 없습니다. 귀하의 해시를 사용하여 예제에서 새 해시 개체를 만들지 않고 기존 해시 개체를 수정합니다. 그러나이 같은 방법으로 새를 만들 수 있습니다

def my_foo(a_hash) 
    a_hash = a_hash.merge({"test" => "reference"}) 
end 
my_foo(hash) 
puts "Ruby is pass-by-#{hash["test"]}" 

은 기본적으로 당신은 " "방법의 개체에 대한 참조를 전달합니다. 더 나은 이해를 위해 this post과 그에 대한 의견을 확인하십시오.

1

매우 흥미로운 것. object_id들과

재생, 당신은 루비는 장면 노호 무엇을하고 있는지 볼 수 있습니다 : 로컬 할당 bar = 'reference'

def foo(bar) 
    puts bar.object_id 
    bar = 'reference' 
    puts bar.object_id 
end 

baz = 'value' 
puts baz.object_id 
foo(baz) 

출력

> baz = 'value' 
=> "value" 

> puts baz.object_id 
70241392845040 

> foo(baz) 
70241392845040 
70241392866940 

, 로컬 변수 bar 참조합니다 다른 객체이므로 원래 객체를 변경하지 않습니다.

어떤 경우에는 객체의 dup이되는 것 같습니다.

+0

그것이 보입니다 .'replace' doesent *'object_id'를 바꿉니다. 왜 그런가요? 또한 당신이 그걸 보길 원한다면 또 다른 예를 들어 보겠습니다. – bill

1

어쩌면이 그것을 이해하는 데 도움이 될 것입니다 :

x = 'ab' 
x.object_id 
=> 70287848748000 # a place in memory 

x = 'cd' 
x.object_id 
=> 70287848695760 # other place in memory (other object) 

x.replace('xy') 
x.object_id 
=> 70287848695760 # the same place in memory (the same object) 
관련 문제