Ruby Koans를 통해 작업하고 있습니다.
about_strings.rb 의 test_the_shovel_operator_modifies_the_original_string
Koan 에는 다음 주석이 포함되어 있습니다.
루비 프로그래머는 문자열을 만들 때 더하기 같음 연산자 (+ =)보다 삽 연산자 (<<)를 선호하는 경향이 있습니다. 왜?
내 생각 엔 속도와 관련이 있지만 삽 운영자가 더 빨라지게 만드는 후드 아래의 행동을 이해하지 못합니다.
누군가가이 기본 설정의 세부 사항을 설명해 주시겠습니까?
답변
증명:
a = 'foo'
a.object_id #=> 2154889340
a << 'bar'
a.object_id #=> 2154889340
a += 'quux'
a.object_id #=> 2154742560
따라서 <<
새 문자열을 만드는 대신 원래 문자열을 변경합니다. 그 이유는 루비 에서 할당 인 ( 다른 연산자 에도 동일하게 적용되는 a += b
) 구문상의 속기 이기 때문입니다 . 반면에 수신자를 제자리에서 변경 하는 별칭입니다 .a = a + b
<op>=
<<
concat()
답변
성능 증명 :
#!/usr/bin/env ruby
require 'benchmark'
Benchmark.bmbm do |x|
x.report('+= :') do
s = ""
10000.times { s += "something " }
end
x.report('<< :') do
s = ""
10000.times { s << "something " }
end
end
# Rehearsal ----------------------------------------
# += : 0.450000 0.010000 0.460000 ( 0.465936)
# << : 0.010000 0.000000 0.010000 ( 0.009451)
# ------------------------------- total: 0.470000sec
#
# user system total real
# += : 0.270000 0.010000 0.280000 ( 0.277945)
# << : 0.000000 0.000000 0.000000 ( 0.003043)
답변
Ruby를 첫 프로그래밍 언어로 배우고있는 한 친구가 Ruby Koans 시리즈의 Strings in Ruby를 살펴보면서 동일한 질문을했습니다. 나는 다음 비유를 사용하여 그에게 설명했다.
반쯤 가득 찬 물 한 잔이 있고 잔을 다시 채워야합니다.
첫 번째 방법은 새 잔을 가져다가 수도꼭지에서 물로 반쯤 채운 다음이 반쯤 가득 찬 잔으로 음료수 잔을 다시 채우는 것입니다. 잔을 리필해야 할 때마다이 작업을 수행합니다.
두 번째 방법은 반쯤 가득 찬 유리 잔을 가져다가 수도꼭지에서 바로 물로 채우는 것입니다.
하루가 끝나면 잔을 다시 채울 때마다 새 잔을 선택하면 청소할 잔이 더 많아집니다.
삽 연산자와 더하기 같음 연산자에도 동일하게 적용됩니다. 게다가 동등한 작업자는 유리를 다시 채울 필요가있을 때마다 새로운 ‘유리’를 선택하는 반면 삽 작업자는 동일한 유리를 가져다가 다시 채 웁니다. 하루가 끝나면 Plus equal 연산자를위한 더 많은 ‘유리’컬렉션.
답변
이것은 오래된 질문이지만 방금 만났고 기존 답변에 완전히 만족하지 않습니다. 삽 <<이 연결 + =보다 빠르다는 점에 대해 많은 좋은 점이 있지만 의미 론적 고려도 있습니다.
@noodl의 대답은 <<가 기존 개체를 수정하는 반면 + =는 새 개체를 만듭니다. 따라서 문자열에 대한 모든 참조가 새 값을 반영하도록 할 것인지 아니면 기존 참조를 그대로두고 로컬에서 사용할 새 문자열 값을 만들 것인지 고려해야합니다. 업데이트 된 값을 반영하기 위해 모든 참조가 필요한 경우 <<를 사용해야합니다. 다른 참조를 그대로 두려면 + =를 사용해야합니다.
매우 일반적인 경우는 문자열에 대한 참조가 하나뿐입니다. 이 경우 의미 적 차이는 중요하지 않으며 속도 때문에 <<를 선호하는 것이 당연합니다.
답변
더 빠르기 때문에 / 문자열의 복사본을 만들지 않기 때문에 <-> 가비지 수집기를 실행할 필요가 없습니다.
답변
답변 커버의 대부분 동안 +=
이 새 복사본을 만들기 때문에 느린, 그 마음을 유지하는 것이 중요 +=
하고 <<
없는 상호 교환! 서로 다른 경우에 각각을 사용하려고합니다.
를 사용 <<
하면을 가리키는 모든 변수도 변경됩니다 b
. 여기서 우리는 a
원하지 않을 때도 돌연변이를 일으 킵니다 .
2.3.1 :001 > a = "hello"
=> "hello"
2.3.1 :002 > b = a
=> "hello"
2.3.1 :003 > b << " world"
=> "hello world"
2.3.1 :004 > a
=> "hello world"
때문에 +=
새 복사본을 만들어, 그것은 또한 변경이 가리키는 된 모든 변수를 떠난다.
2.3.1 :001 > a = "hello"
=> "hello"
2.3.1 :002 > b = a
=> "hello"
2.3.1 :003 > b += " world"
=> "hello world"
2.3.1 :004 > a
=> "hello"
이 구별을 이해하면 루프를 다룰 때 많은 두통을 줄일 수 있습니다!
답변
귀하의 질문에 대한 직접적인 대답은 아니지만 The Fully Upturned Bin은 항상 제가 좋아하는 Ruby 기사 중 하나였습니다. 또한 가비지 수집과 관련된 문자열에 대한 정보도 포함합니다.