ความคิดเห็น“ Frozen_string_literal: true” ทำอะไรได้บ้าง


226

นี่คือrspecbinstub ในไดเรกทอรีโครงการของฉัน

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

คำตอบ:


314

# frozen_string_literal: trueเป็นความคิดเห็นเวทมนต์ซึ่งได้รับการสนับสนุนเป็นครั้งแรกใน Ruby 2.3 ที่บอก Ruby ว่าตัวอักษรสตริงทั้งหมดในไฟล์นั้นถูกแช่แข็งโดยปริยายราวกับว่า#freezeมีการเรียกใช้ในแต่ละรายการ นั่นคือถ้าตัวอักษรสตริงที่กำหนดไว้ในไฟล์ที่มีความคิดเห็นนี้และคุณเรียกวิธีการในสตริงที่ปรับเปลี่ยนเช่นคุณจะได้รับ<<RuntimeError: can't modify frozen String

ความคิดเห็นจะต้องอยู่ในบรรทัดแรกของไฟล์

ในทับทิม 2.3 คุณสามารถใช้ความคิดเห็นมหัศจรรย์นี้เพื่อเตรียมความพร้อมสำหรับตัวอักษรของสตริงแช่แข็งเป็นค่าเริ่มต้นในทับทิม 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

นอกจากนี้คุณยังสามารถตรึงผันแปร (unfrozen) -สตริงกับเอก


24
สิ่งสำคัญที่ควรสังเกตเกี่ยวกับการแช่แข็งสตริงคือการปรับปรุงประสิทธิภาพของแอพ ดูเพิ่มเติมได้ที่นี่
Andres Ehrenpreis

2
@ dave-schweisguth เราไม่ควรคาดหวังว่า-"foo"จะเป็นเช่นเดียวกับ"foo".freeze? เมื่อฉันตรวจสอบ(-"foo").__id__ฉันได้รับค่าที่แตกต่างกันในแต่ละครั้ง แต่"foo".freeze.__id__จะเหมือนกันในแต่ละครั้ง ความคิดใด ๆ
lilole

ฉันสงสัยว่าฟังก์ชั่นนี้เป็นปัญหาหรือไม่ดูเหมือนว่าจะถูกเรียกด้วยการลบเอกภาพเท่านั้น github.com/ruby/ruby/blob/trunk/string.c#L2572
lilole

2
-ใช้สำหรับการทำซ้ำสตริงเพื่อบันทึกหน่วยความจำนอกเหนือจากการคืนค่าสตริงที่ตรึง
eregon

9
ในขณะที่คุณยังสามารถใช้ความคิดเห็นเวทมนตร์ Matz ตัดสินใจอย่างเป็นทางการว่าจะไม่ทำให้ตัวอักษรสตริงทั้งหมดไม่เปลี่ยนรูปตามค่าเริ่มต้นใน Ruby 3: bugs.ruby-lang.org/issues/11473#note-53
Konstantin Tikhonov

43

ปรับปรุงประสิทธิภาพของแอปพลิเคชันโดยไม่จัดสรรพื้นที่ใหม่สำหรับสายอักขระเดียวกันดังนั้นจึงประหยัดเวลาสำหรับการเก็บขยะ อย่างไร? เมื่อคุณตรึงสตริงตัวอักษร (วัตถุสตริง) คุณกำลังบอกให้รูบี้ไม่ให้โปรแกรมใด ๆ ของคุณแก้ไขสตริงตัวอักษร (วัตถุ)

ข้อสังเกตที่ชัดเจนบางอย่างที่ต้องจำไว้

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. ด้วยการตรึงสตริงตัวอักษรโปรแกรมของคุณจะยกข้อยกเว้นเมื่อพยายามแก้ไขสตริงตัวอักษร

ตัวอย่าง:

หากไม่มีความคิดเห็นเวทมนต์คุณสามารถแก้ไขตัวอักษรสตริงได้

name = 'Johny'
name << ' Cash'

puts name     #=> Johny Cash

ด้วยความคิดเห็นมายากลข้อยกเว้นจะถูกยกขึ้นเมื่อคุณแก้ไขตัวอักษรสตริง

# frozen_string_literal: true

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

puts name      

มีอะไรให้เรียนรู้และมีความยืดหยุ่นอยู่เสมอ:


นี่เป็นคำตอบที่ง่ายกว่า
Jin Lim

20

ใน Ruby 3.0 Matz (ผู้สร้าง Ruby) ตัดสินใจที่จะทำให้ตัวอักษร String ทั้งหมดถูกตรึงไว้โดยค่าเริ่มต้น

คุณสามารถใช้ใน Ruby 2.x เพียงเพิ่มความคิดเห็นนี้ในบรรทัดแรกของไฟล์ของคุณ

# frozen_string_literal: true

ความคิดเห็นด้านบนที่ด้านบนของไฟล์จะเปลี่ยนซีแมนทิกส์ของตัวอักษรสตริงแบบคงที่ในไฟล์ ตัวอักษรสตริงแบบคงที่จะถูกแช่แข็งและส่งกลับวัตถุเดียวกันเสมอ (ความหมายของตัวอักษรสตริงแบบไดนามิกจะไม่เปลี่ยนแปลง)

วิธีนี้มีประโยชน์ดังต่อไปนี้:

ไม่มีคำต่อท้ายน่าเกลียด ไม่มีข้อผิดพลาดทางไวยากรณ์เกี่ยวกับ Ruby ที่เก่ากว่า เราต้องการเพียงบรรทัดสำหรับแต่ละไฟล์

โปรดอ่านหัวข้อนี้สำหรับข้อมูลเพิ่มเติม

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


น่าเสียดายที่ความคิดเห็นนี้ใช้ไม่ได้กับสตริงในอาร์เรย์ดังนั้นพวกเขาจึงจำเป็นต้อง
แช่แข็ง

3
น่าเสียดายที่นี่จะไม่อยู่ใน ruby ​​3 bugs.ruby-lang.org/issues/11473#note-53
zhisme
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.