배열의 값을 바꿀 때마다 값 중 하나를 참조 변수에 저장했는지 확인합니다. 하지만 Ruby가 두 값을 반환하고 자동으로 두 값을 바꿀 수 있다는 것을 알았습니다. 예를 들면
array = [1, 3, 5 , 6 ,7]
array[0], array[1] = array[1] , array[0] #=> [3, 1]
루비가 어떻게하는지 궁금합니다.
답변:
다른 언어와 달리 Ruby의 모든 메소드 호출의 반환 값은 항상 객체입니다. Ruby의 모든 것과 마찬가지로 nil
자체가 객체 이기 때문에 가능 합니다.
당신이 보게 될 세 가지 기본 패턴이 있습니다. 특정 값을 반환하지 않음 :
def nothing
end
nothing
# => nil
특이 값 반환 :
def single
1
end
x = single
# => 1
이것은 다른 프로그래밍 언어에서 기대하는 것과 일치합니다.
여러 반환 값을 처리 할 때 상황이 약간 다릅니다. 다음과 같이 명시 적으로 지정해야합니다.
def multiple
return 1, 2
end
x = multiple
# => [ 1, 2 ]
x
# => [ 1, 2 ]
여러 값을 반환하는 호출을 만들 때 값을 독립 변수로 나눌 수 있습니다.
x, y = multiple
# => [ 1, 2 ]
x
# => 1
y
# => 2
이 전략은 다음과 같은 대체 유형에도 적용됩니다.
a, b = 1, 2
# => [1, 2]
a, b = b, a
# => [2, 1]
a
# => 2
b
# => 1
[1, 2]
위의 예제와 동일하게 작동합니다.
1,2
그 자체로 유효하지 않지만 return 1,2
또는 [1,2]
작동 중이 라는 것을 분명히해야 했다 .
아니요, Ruby는 실제로 두 개체 반환을 지원하지 않습니다. (BTW : 변수가 아닌 개체를 반환합니다.보다 정확하게는 개체에 대한 포인터를 반환합니다.)
그러나 병렬 할당을 지원합니다. 할당의 오른쪽에 둘 이상의 객체가있는 경우 객체는 다음으로 수집됩니다 Array
.
foo = 1, 2, 3
# is the same as
foo = [1, 2, 3]
할당의 왼쪽에 "대상"(변수 또는 setter 메서드)이 두 개 이상있는 경우 변수 Array
는 오른쪽의 요소에 바인딩됩니다 .
a, b, c = ary
# is the same as
a = ary[0]
b = ary[1]
c = ary[2]
오른쪽이 하지Array
, 상기 한 사용으로 변환한다 to_ary
방법
a, b, c = not_an_ary
# is the same as
ary = not_an_ary.to_ary
a = ary[0]
b = ary[1]
c = ary[2]
두 가지를 합치면
a, b, c = d, e, f
# is the same as
ary = [d, e, f]
a = ary[0]
b = ary[1]
c = ary[2]
이와 관련된 것은 할당의 왼쪽에있는 표시 연산자입니다. 그것은 "takeArray
오른쪽에있는 의 모든 남은 요소를 가져옵니다 "를 의미합니다.
a, b, *c = ary
# is the same as
a = ary[0]
b = ary[1]
c = ary.drop(2) # i.e. the rest of the Array
마지막으로 괄호를 사용하여 병렬 할당을 중첩 할 수 있습니다.
a, (b, c), d = ary
# is the same as
a = ary[0]
b, c = ary[1]
d = ary[2]
# which is the same as
a = ary[0]
b = ary[1][0]
c = ary[1][1]
d = ary[2]
때를 return
하는 방법이나next
또는 break
블록에서, 루비 때문에, 할당의 오른쪽과 같은이-의 종류를 취급합니다
return 1, 2
next 1, 2
break 1, 2
# is the same as
return [1, 2]
next [1, 2]
break [1, 2]
그건 그렇고, 이것은 메서드와 블록의 매개 변수 목록에서도 작동합니다 (메소드가 더 엄격하고 블록이 덜 엄격함).
def foo(a, (b, c), d) p a, b, c, d end
bar {|a, (b, c), d| p a, b, c, d }
예를 들어 "덜 엄격"한 블록은 Hash#each
작동합니다. 그것은 실제로 yield
SA 단일 두 요소Array
블록에 키와 값의,하지만 우리는 일반적으로 쓰기
some_hash.each {|k, v| }
대신에
some_hash.each {|(k, v)| }
tadman과 Jörg W Mittag는 나보다 Ruby를 더 잘 알고 있으며, 그들의 대답은 틀리지 않지만 OP가 알고 싶어하는 것에 대답하고 있다고 생각하지 않습니다. 그래도 질문이 명확하지 않다고 생각합니다. 내 이해에서 OP가 요청하려는 것은 여러 값을 반환하는 것과 관련이 없습니다.
진짜 질문은 두 변수의 값 a
과 b
(또는 원래 질문에서와 같이 배열의 두 위치) 전환하려는 경우 왜 시간 변수를 사용할 필요가 없다는 것입니다.temp
다음과 같은 것입니다.
a, b = :foo, :bar
temp = a
a = b
b = temp
그러나 다음과 같이 직접 수행 할 수 있습니다.
a, b = :foo, :bar
a, b = b, a
대답은 다중 할당에서 전체 왼쪽을 할당하기 전에 전체 오른쪽이 평가되고 하나씩 수행되지 않는다는 것입니다. 그래서a, b = b, a
는 a = b; b = a
.
양측 =
의 용어 수가 서로 다른 경우 조정에서 뒤 따르는 할당 전에 전체 오른쪽을 먼저 평가하는 것이 필요 하며 Jörg W Mittag의 설명이 간접적으로 관련 될 수 있지만 이것이 주요 문제는 아닙니다.