“Frozen_string_literal: true” yorumu ne işe yarıyor?


226

Bu rspecbenim proje dizinimdeki binstub.

#!/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")

Bunun amacı ne?

# frozen_string_literal: true

Yanıtlar:


314

# frozen_string_literal: trueRuby 2.3'te ilk kez desteklenen sihirli bir yorum, Ruby'ye dosyadaki tüm dize değişmezlerinin #freezeher biri çağrılmış gibi örtük olarak dondurulduğunu söyler. Bir dize bu yorum ile bir dosyada tanımlanır Yani, eğer, ve hangi gibi değiştirir bunu o tellerden bir yöntemini çağırmak <<, elde edersiniz RuntimeError: can't modify frozen String.

Yorum dosyanın ilk satırında olmalıdır.

Ruby 2.3'te, bu sihirli yorumu Ruby 3'teki varsayılan donmuş dize değişmezlerine hazırlamak için kullanabilirsiniz .

Ruby 2.3'te --enable=frozen-string-literalbayrakla çalışır ve Ruby 3'te dize değişmezleri tüm dosyalarda dondurulur. İle global ayarı geçersiz kılabilirsiniz # frozen_string_literal: false.

Bir dizgi hazır bilgisinin genel veya dosya başına ayarından bağımsız olarak değiştirilebilir olmasını isterseniz, bunu tekli işleçle önek olarak ekleyebilirsiniz +(işleç önceliğine dikkat ederek) veya çağırabilirsiniz .dup:

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

Ayrıca mutable (donmamış) bir dizgiyi tekli ile dondurabilirsiniz -.


25
Dizeleri dondurma konusunda dikkat edilmesi gereken önemli bir nokta, uygulamanın performansını artırmasıdır . Ayrıca bkz burada
Andres Ehrenpreis

2
@ dave-schweisguth -"foo"Aynı olmasını beklememiz gerekmez "foo".freezemi? Kontrol (-"foo").__id__ettiğimde her seferinde farklı bir değer alıyorum ama "foo".freeze.__id__her seferinde aynı. Herhangi bir fikir?
lilole

Bu işlevin sorun olup olmadığını merak ediyorum, sadece tekli eksi ile çağrılıyor gibi görünüyor. github.com/ruby/ruby/blob/trunk/string.c#L2572
lilole

2
-dondurulmuş bir String döndürmenin yanı sıra, bellek tasarrufu sağlamak için Dize tekilleştirme içindir.
eregon

9
Hala sihirli yorumu kullanabilmenize rağmen, Matz resmen tüm string değişmezlerini Ruby 3'te varsayılan olarak değişmez hale getirmemeye karar verdi: bugs.ruby-lang.org/issues/11473#note-53
Konstantin Tikhonov

44

Aynı dize için yeni alan ayırmayarak uygulama performansını iyileştirir, böylece çöp toplama işleri için zaman kazandırır. Nasıl? bir dize değişmezini (dize nesnesi) dondurduğunuzda, Ruby'ye programlarınızın hiçbirinin dize değişmez değerini (nesne) değiştirmesine izin vermemesini söylersiniz.

Akılda tutulması gereken bazı açık gözlemler.

1. Dize değişmezlerini dondurduğunuzda, bunun için yeni bellek alanı ayırmazsınız.

Misal:

Sihirli yorum olmadan aynı dize için yeni alan ayırır (Yazdırılan farklı nesne kimliklerini gözlemleyin)

def hello_id
  a = 'hello'
  a.object_id
end

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

Sihirli bir yorumla , ruby ​​sadece bir kez yer ayırır

# frozen_string_literal: true

def hello_id
  a = 'hello'
  a.object_id
end

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

2. Dize değişmezlerini dondurduğunuzda, dizgi değişmez değerlerini değiştirmeye çalışırken programınız bir istisna oluşturur.

Misal:

Sihirli yorum olmadan , dize değişmezlerini değiştirebilirsiniz.

name = 'Johny'
name << ' Cash'

puts name     #=> Johny Cash

Sihirli yorumda , dize değişmezlerini değiştirdiğinizde bir istisna ortaya çıkar

# frozen_string_literal: true

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

puts name      

Öğrenmek ve esnek olmak için her zaman daha fazlası vardır:


Bu daha sezgisel bir cevap.
Jin Lim

20

Ruby 3.0'da. Matz (Ruby'nin yaratıcısı) tüm String değişmezlerini varsayılan olarak dondurmaya karar verdi.

Ruby 2.x'te kullanabilirsiniz. Bu yorumu dosyalarınızın ilk satırına eklemeniz yeterlidir.

# frozen_string_literal: true

Bir dosyanın üstündeki yukarıdaki yorum, dosyadaki statik dize değişmezlerinin anlambilimini değiştirir. Statik dize değişmezleri dondurulur ve her zaman aynı nesneyi döndürür. (Dinamik dize değişmezlerinin semantiği değişmez.)

Bu yol aşağıdaki avantajlara sahiptir:

Çirkin f eki yok. Eski Ruby'de sözdizimi hatası yok. Her dosya için sadece bir satıra ihtiyacımız var.

Plese, daha fazla bilgi için bu konuyu okuyun.

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


Ne yazık ki bu yorum dizilerdeki dizeler için çalışmıyor, bu yüzden hala açıkça dondurulmaları gerekiyor
ToTenMilan

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.