Question

Ruby 2.1 will have a frozen string so that the object is not re-created every time that the interpreter runs across it, i.e.

my_hash["abcd"f] = 123

Why can't the interpreter automatically detect that this string is not going to change and just automatically freeze it?

Or, pre-ruby 2.1 How could any code change such a string once the interpreter has started running? If we say that "abcd" needs to be frozen, then there must be some way of changing it.

-- UPDATE: The question above was updated, so the below comments are a bit awkward, but addressed a previous code example that was not as good.

-- UPDATE: http://globaldev.co.uk/2014/05/ruby-2-1-in-detail/ Ruby keys are automatically frozen.

Était-ce utile?

La solution 2

Ruby is a dynamic language. There is no static compilation and it's very hard for the interpreter to know in advance who will eventually access and modify a variable.

Let's look at the following example. You have a string

str = "foo"

and then later in your code you have

str.upcase!
# => "FOO"

This example is pretty trivial even for a simple parser to understand that the string is mutated. But let's add some more complexity

str = "foo"
method = ["up", "case"]
str.send((method << "!").join)
# => "FOO"

This is producing exactly the same result of before, but the method is not statically coded in the script. Instead, it's the result of a computation then dynamically performed on the string at runtime.

But wait, let's make it even more complicated.

str = "foo"
method = [ARGV.first, "case"]
str.send((method << "!").join) if ARGC.to_i > 0
# => "FOO"

In this case, assuming I pass an argument from the command line, the transformation method will be computed and then applied to the string.

As you can guess, the only way in both cases to know that str is going to be changed is by actually executing the code.

These examples should also answer your second part of the question

How could any code change such a string once the interpreter has started running? If we say that "abcd" needs to be frozen, then there must be some way of changing it.

As a side note, I'd like to point out that the "frozen string literals" feature has evolved recently and it's now sufficient to flag a variable as frozen.

In Ruby 2.1, "str".freeze is optimized by the compiler to return a single shared frozen strings on every invocation. An alternative "str"f syntax was implemented initially, but later reverted.

Autres conseils

  • Regarding your first question:

    Because the interpreter cannot foresee whether that string instance would be later modified by any destructive method.

  • Regarding your second question (after "Or"):

    By any of the destructive methods on String, such as reverse!, prepend, concat, etc.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top