Ruby에서 문자열을 고정하는 다른 방법

18441 단어 programmingrailsruby
Ruby에서 문자열을 고정하려면 최소한 두 가지 방법이 있습니다.

1) 파일 시작 부분에 매직 코멘트 추가

# frozen_string_literal: true


2) 고정하려는 문자열에서 호출.freeze
a = "this is a frozen string".freeze
puts a.frozen? # will return true 

b = "this is a frozen string".freeze
puts b.frozen? # will return true 

puts a.equal?(b) # will return true
puts a.object_id == b.object_id # true


아시다시피 ab는 동일한 개체 인스턴스인 것 같습니다.
새 개체가 인스턴스화되지 않습니다.

기호에 대해서도 마찬가지입니다.

s = :a_new_symbol_open
puts s.frozen? # will, of course return true

m = :a_new_symbol_open
puts m.frozen? # will, of course return true

puts s.object_id == m.object_id # will return true


문자열을 고정하는 다른 방법



문자열에 적용할 수 있는 일종의 이상한 메서드 입력: -
다음과 같은 코드를 볼 수 있습니다.

status = -"global.pending"


String#-@ 및 String#+@ 메소드



이러한 방법이 어떻게 작동하는지 살펴보겠습니다.

문자열 리터럴을 사용하면 할당이 발생할 때마다 새 String 객체가 생성됩니다. 다음 예제에서 object_id가 str1str2 사이에서 다르다는 점에 유의하십시오.

str1 = "Normal string"
puts "#{str1.object_id}, #{str1.frozen?}" # 60, false

str2 = "Normal string"
puts "#{str2.object_id}, #{str2.frozen?}" # 80, false

puts str1.object_id == str2.object_id # false


문자열에서 -를 사용하는 것은 무엇을 합니까?



먼저, hereString#-의 정의이다.

Returns a frozen, possibly pre-existing copy of the string

The returned String will be deduplicated if it has no instance variables.



다음 예제에서 문자열이 동결되고 동일한 object_id를 반환한다는 점에 유의하십시오.

str3 = -"Normal string"
puts "#{str3.object_id}, #{str3.frozen?}" # 100, true

# Here for example, it will return the same object id
str4 = -"Normal string"
puts "#{str4.object_id}, #{str4.frozen?}" # 100, true

puts str3.object_id == str4.object_id # true


따라서 우리는 문자열을 수정에 가깝게 만들 뿐만 아니라 동일한 객체를 재사용하고 있습니다.

그러한 문자열을 고정 해제하는 방법은 무엇입니까?



문자열에 대응하는 방법이 있습니다: +
does 다음과 같습니다.

Returns a frozen, possibly pre-existing copy of the string.

The returned String will be deduplicated as long as it does not have any instance variables set on it.



frozen_string = -"This is a frozen string"
begin
  frozen_string << "and it cannot be modified"
rescue FrozenError => e
  puts e # can't modify frozen String: "This is a frozen string"
end 

puts "#{frozen_string.object_id}, #{frozen_string.frozen?}" # 120, true

str5 = +frozen_string 
puts "#{str5.object_id}, #{str5.frozen?}"  # 140, false

str5 << " and it can be modified" # This is a frozen string and it can be modified
puts str5


흥미로운 사례 탐색



Ruby에서 문자열 키가 있는 해시는 키를 동결합니다. 그러나 키는 동일한 개체입니까? 가치는 어떻습니까?

hash1 = { "Key" => "Value" }
key1 = hash1.keys[0]
value1 = hash1.values[0]
puts "H1: #{key1.object_id}, #{value1.object_id}" # 160, 180
puts "H1: #{key1.frozen?}, #{value1.frozen?}" # true, false


hash2 = { -"Key" => "Value" }
key2 = hash2.keys[0]
value2 = hash2.values[0]
puts "H2: #{key2.object_id}, #{value2.object_id}" # 160, 200
puts "H2: #{key2.frozen?}, #{value2.frozen?}" # true, false

puts key1.equal?(key2) # true
puts key1.object_id == key2.object_id # true


알 수 있듯이 키의 object_id는 동일합니다. 따라서 동일한 개체 인스턴스입니다. 그러나 값은 서로 다른 object_id를 가지므로 동일한 객체가 아닙니다.

puts value1.equal?(value2) # false
puts value1.object_id == value2.object_id # false


따라서 동일한 문자열 리터럴이므로 값도 동일한 개체로 만들고 싶다면 다음을 수행하십시오.

hash3 = { "Key" => -"Value" }
key3 = hash2.keys[0]
value3 = hash2.values[0]
puts "H3: #{key3.object_id}, #{value3.object_id}" # 160, 200
puts "H3: #{key3.frozen?}, #{value3.frozen?}" # true, true

hash4 = { "Key" => -"Value" }
key4 = hash2.keys[0]
value4 = hash2.values[0]
puts "H4: #{key4.object_id}, #{value4.object_id}" # 160, 200
puts "H4: #{key4.frozen?}, #{value4.frozen?}" # true, true

puts value3.equal?(value4) # true
puts value3.object_id == value4.object_id # true


-on 문자열을 사용하는 몇 가지 예



먼저 가능하면 문자열 대신 기호를 사용하십시오.

물론 기호에는 작성하는 데 좀 더 제한적인 규칙이 있으므로 명확성 또는 기타 이유로 기호를 사용할 수 없거나 사용하고 싶지 않을 수 있습니다.

따라서 변형이 없을 가능성이 있는 문자열에 -를 사용하십시오.

예:

1) 다른 곳에서 재사용될 수 있는 커스텀 SQL을 작성할 때

SolarSystem.planets.order(-"orbit = 'circular' ASC, name ASC")


2) 기본 URL 또는 경로를 정의하는 외부 API를 호출하는 경우:

base = -"http://example.com"
url = URI.join(base, -"/foo")


3) 예를 들어 헤더를 추가할 때:

header = { "Content-Type" => -"application/x-www-form-urlencoded" }


4) 구조화된 짧은 정보를 기록하고 싶을 때:

Rails.logger(-"job.start.highpriority")



이러한 유형의 콘텐츠가 마음에 드신다면 제가 주로 Ruby 및 Rails 콘텐츠를 공유/리트윗하는 Twitter에서 저를 팔로우하세요.

또한 newsletter.shortruby.com에 Ruby 및 Rails의 최신 콘텐츠가 포함된 뉴스레터를 게시합니다.

좋은 웹페이지 즐겨찾기