Ruby: What does the comment “frozen_string_literal: true” do?

后端 未结 3 1764
南笙
南笙 2020-11-30 17:47

This is the rspec binstub in my project directory.

#!/usr/bin/env ruby
begin
  load File.expand_path(\"../spring\", __FILE__)
rescue LoadError
e         


        
相关标签:
3条回答
  • 2020-11-30 18:09

    In Ruby 3.0. Matz (Ruby’s creator) decided to make all String literals frozen by default.

    EDIT 2019: he decided to abandon the idea of making frozen-string-literals default for Ruby 3.0 (source: https://bugs.ruby-lang.org/issues/11473#note-53)


    You can use in Ruby 2.x. Just add this comment in the first line of your files.

    # frozen_string_literal: true
    

    The above comment at top of a file changes semantics of static string literals in the file. The static string literals will be frozen and always returns same object. (The semantics of dynamic string literals is not changed.)

    This way has following benefits:

    No ugly f-suffix. No syntax error on older Ruby. We need only a line for each file.

    Plese, read this topic for more information.

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

    0 讨论(0)
  • 2020-11-30 18:10

    It improves application performance by not allocating new space for the same string, thereby also saving time for garbage collection chores. How? when you freeze a string literal(string object), you're telling Ruby to not let any of your programs modify the string literal (object).

    Some obvious observations to keep in mind.

    1. By freezing string literals, you're not allocating new memory space for it.

    Example:

    Without magic comment allocates new space for the same string (Observe the different object IDs printed)

    def hello_id
      a = 'hello'
      a.object_id
    end
    
    puts hello_id   #=> 70244568358640
    puts hello_id   #=> 70244568358500
    

    With magic comment, ruby allocates space only once

    # frozen_string_literal: true
    
    def hello_id
      a = 'hello'
      a.object_id
    end
    
    puts hello_id   #=> 70244568358640
    puts hello_id   #=> 70244568358640
    

    2. By freezing string literals, your program will raise an exception when trying to modify the string literal.

    Example:

    Without magic comment, you can modify the string literals.

    name = 'Johny'
    name << ' Cash'
    
    puts name     #=> Johny Cash
    

    With magic comment, an exception will be raised when you modify string literals

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

    There's always more to learn and be flexible:

    • https://bugs.ruby-lang.org/issues/8976
    • https://www.mikeperham.com/2018/02/28/ruby-optimization-with-one-magic-comment/
    0 讨论(0)
  • 2020-11-30 18:12

    # frozen_string_literal: true is a magic comment, supported for the first time in Ruby 2.3, that tells Ruby that all string literals in the file are implicitly frozen, as if #freeze had been called on each of them. That is, if a string literal is defined in a file with this comment, and you call a method on that string which modifies it, such as <<, you'll get RuntimeError: can't modify frozen String.

    The comment must be on the first line of the file.

    In Ruby 2.3, you can use this magic comment to prepare for frozen string literals being the default in Ruby 3.

    In Ruby 2.3 run with the --enable=frozen-string-literal flag, and in Ruby 3, string literals are frozen in all files. You can override the global setting with # frozen_string_literal: false.

    If you want a string literal to be mutable regardless of the global or per-file setting, you can prefix it with the unary + operator (being careful with operator precedence) or call .dup on it:

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

    You can also freeze a mutable (unfrozen) string with unary -.

    0 讨论(0)
提交回复
热议问题