programing

루비에서 문자열을 만들 때 삽 연산자(<)가 플러스 기호(+=)보다 선호되는 이유는 무엇입니까?

megabox 2023. 6. 3. 08:22
반응형

루비에서 문자열을 만들 때 삽 연산자(<)가 플러스 기호(+=)보다 선호되는 이유는 무엇입니까?

저는 루비코안스를 통해 일하고 있습니다.

test_the_shovel_operator_modifies_the_original_stringabout_strings.rb의 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'의 'Strings in Ruby'를 겪으며 똑같은 질문을 했습니다.저는 다음과 같은 비유를 사용하여 그에게 설명했습니다.

당신은 반쯤 채워진 물 한 잔을 가지고 있고 당신은 당신의 잔을 다시 채워야 합니다.

첫 번째 방법은 새 잔을 들고, 수도꼭지에서 물을 반쯤 채운 다음, 두 번째 반 잔을 사용하여 마시는 잔을 다시 채우는 것입니다.당신은 잔을 다시 채워야 할 때마다 이렇게 합니다.

두 번째 방법은 반 컵을 들고 수도꼭지에서 바로 물을 다시 채우는 것입니다.

결국, 만약 여러분이 잔을 다시 채울 필요가 있을 때마다 새로운 잔을 선택한다면, 여러분은 더 많은 잔을 청소해야 할 것입니다.

삽 조작자와 플러스 이퀄 조작자에게도 동일하게 적용됩니다.또한 동등한 작업자는 새 '유리'를 선택하고 삽 작업자는 동일한 유리를 사용하여 다시 채워야 합니다.마지막으로 Plus 등호 연산자를 위한 더 많은 '유리' 컬렉션을 제공합니다.

이것은 오래된 질문이지만, 저는 방금 우연히 발견했고 저는 기존의 답변에 완전히 만족하지 않습니다.삽 << 연결 +=보다 빠르다는 장점이 많지만 의미론적인 고려도 있습니다.

@prefl에서 받아들여진 답은 <<이 제자리에 있는 기존 객체를 수정하는 반면 +=는 새로운 객체를 생성한다는 것을 보여줍니다.따라서 문자열에 대한 모든 참조에 새 값을 반영할 것인지 아니면 기존 참조를 그대로 두고 로컬에서 사용할 새 문자열 값을 만들 것인지 고려해야 합니다.업데이트된 값을 반영하기 위해 모든 참조가 필요한 경우 <<을 사용해야 합니다.다른 참조를 그대로 두려면 +=를 사용해야 합니다.

문자열에 대한 참조가 하나뿐인 경우가 매우 일반적입니다.이 경우 의미적 차이는 중요하지 않으며 속도 때문에 <<을 선호하는 것은 당연합니다.

더 빠르기 때문에 / 가비지 수집기를 실행할 필요가 없는 문자열 <->의 복사본을 만들지 않습니다.

대부분의 대답은 다음과 같습니다.+=복사본을 명심하는 것이 중요합니다.+=그리고.<< 호환되지 않습니다!각 항목을 다른 경우에 사용하려고 합니다.

용사를 합니다.<<는 또한 " 또가변변경됩다니수도는키리한▁that"를 가리키는 변수도 합니다.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"

이 구별을 이해하는 것은 여러분이 루프를 다룰 때 많은 두통을 줄일 수 있습니다!

당신의 질문에 대한 직접적인 대답은 아니지만, 왜 완전히 뒤집힌 빈은 항상 제가 좋아하는 루비 기사 중 하나였을까요?또한 가비지 수집과 관련된 문자열에 대한 몇 가지 정보도 포함되어 있습니다.

언급URL : https://stackoverflow.com/questions/4684446/why-is-the-shovel-operator-preferred-over-plus-equals-when-building-a

반응형