[ruby] “frozen_string_literal : true”라는 주석은 무엇을합니까?

이것은 rspec내 프로젝트 디렉토리 의 쓰레기통입니다.

#!/usr/bin/env ruby
begin
  load File.expand_path("../spring", __FILE__)
rescue LoadError
end
# frozen_string_literal: true
#
# This file was generated by Bundler.
#
# The application 'rspec' is installed as part of a gem, and
# this file is here to facilitate running it.
#

require "pathname"
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
  Pathname.new(__FILE__).realpath)

require "rubygems"
require "bundler/setup"

load Gem.bin_path("rspec-core", "rspec")

이것은 무엇을하기위한 것입니까?

# frozen_string_literal: true



답변

# frozen_string_literal: trueRuby 2.3에서 처음으로 지원되는 마법의 주석으로, 파일에있는 모든 문자열 리터럴이 #freeze각각에 대해 호출 된 것처럼 암시 적으로 고정되었음을 Ruby에 알려줍니다 . 문자열 리터럴이 댓글을 가진 파일에 정의되어있는 경우 즉, 그리고 당신이하는 등의 수정을, 해당 문자열에 대한 메소드를 호출 <<, 당신은 얻을 것이다 RuntimeError: can't modify frozen String.

주석은 파일의 첫 번째 줄에 있어야합니다.

Ruby 2.3에서는이 마법 설명 사용 하여 고정 된 문자열 리터럴을 Ruby 3의 기본값으로 준비 할 수 있습니다 .

Ruby 2.3에서는 --enable=frozen-string-literal플래그를 사용하여 실행하고 Ruby 3에서는 모든 파일에서 문자열 리터럴이 고정됩니다. 로 전역 설정을 무시할 수 있습니다 # frozen_string_literal: false.

전역 또는 파일 별 설정에 관계없이 문자열 리터럴을 변경할 수있게하려면 단항 +연산자 앞에 접두사를 붙이 거나 (연산자 우선 순위에주의하여) 호출 .dup할 수 있습니다.

# frozen_string_literal: true
"".frozen?
=> true
(+"").frozen?
=> false
"".dup.frozen?
=> false

unary로 변경 가능 (동결 해제) 문자열을 고정 할 수도 있습니다 -.


답변

동일한 문자열에 새 공간을 할당하지 않아 응용 프로그램 성능이 향상되어 가비지 수집 작업 시간이 절약됩니다. 어떻게? 문자열 리터럴 (문자열 객체)을 고정하면 프로그램에서 문자열 리터럴 (객체)을 수정하지 않도록 Ruby에 지시합니다.

명심해야 할 몇 가지 명백한 관찰.

1. 문자열 리터럴을 고정하면 새로운 메모리 공간이 할당되지 않습니다.

예:

마술 주석이 없으면 동일한 문자열에 새 공간을 할당합니다 (인쇄 된 다른 객체 ID를 준수하십시오)

def hello_id
  a = 'hello'
  a.object_id
end

puts hello_id   #=> 70244568358640
puts hello_id   #=> 70244568358500

매직 코멘트 로 루비는 한 번만 공간을 할당합니다.

# frozen_string_literal: true

def hello_id
  a = 'hello'
  a.object_id
end

puts hello_id   #=> 70244568358640
puts hello_id   #=> 70244568358640

2. 문자열 리터럴을 고정하면 문자열 리터럴을 수정하려고 할 때 프로그램에서 예외가 발생합니다.

예:

magic comment가 없으면 문자열 리터럴을 수정할 수 있습니다.

name = 'Johny'
name << ' Cash'

puts name     #=> Johny Cash

magic comment를 사용하면 문자열 리터럴을 수정할 때 예외가 발생합니다.

# frozen_string_literal: true

name = 'john'
name << ' cash'  #=> `<main>': can't modify frozen String (FrozenError)

puts name      

항상 배우고 융통성이 있어야합니다.


답변

루비 3.0. Matz (Ruby의 제작자)는 기본적으로 모든 문자열 리터럴을 고정하기로 결정했습니다.

Ruby 2.x에서 사용할 수 있습니다. 파일의 첫 줄에이 주석을 추가하십시오.

# frozen_string_literal: true

파일 맨 위의 주석은 파일에서 정적 문자열 리터럴의 의미를 변경합니다. 정적 문자열 리터럴은 고정되며 항상 동일한 객체를 반환합니다. (동적 문자열 리터럴의 의미는 변경되지 않습니다.)

이 방법은 다음과 같은 이점이 있습니다.

추악한 f- 접미사가 없습니다. 이전 Ruby에서는 구문 오류가 없습니다. 각 파일마다 한 줄만 있으면됩니다.

자세한 내용은이 주제를 읽으십시오.

https://bugs.ruby-lang.org/issues/8976


답변