Project

General

Profile

Feature #14680

Adding +@ and -@ to hash and array

Added by kddeisz (Kevin Deisz) 3 months ago. Updated 14 days ago.

Status:
Open
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:86513]

Description

Since we have -@ and +@ for strings and it's very useful (and reads better than .freeze) I'd like to propose adding the same API to hash and array. Especially with constants, linters are always telling me to freeze them, and I'd like to be able to accomplish that with -@. I've attached the necessary code to make that happen.

freeze.patch (3.86 KB) freeze.patch kddeisz (Kevin Deisz), 04/11/2018 02:49 PM

History

#1 [ruby-core:86515] Updated by shevegen (Robert A. Heiler) 2 months ago

I like .dup and .freeze, more than + and - on class String.

https://ruby-doc.org/core-2.5.0/String.html#method-i-2B-40

The only good thing is that I don't have to use any of these
methods so ultimately I don't have to care either way. :)

As for linters, I assume you refer to rubocop since that is
by far the most common use case I could see, with people
putting things such as:

FOO = 'foo'.freeze
BAR = 'bar'.freeze

into files. I wonder if matz thinks that this is a good way;
to me, I always wondered when people do so. Probably
lint-based development ... should that not be superfluous
with frozen strings now? One comment on top of the file
and avoid all the explicit .freeze calls?

#2 [ruby-core:86516] Updated by kddeisz (Kevin Deisz) 2 months ago

I don't think it's as common these days to see .freeze all over the place, since the linters explicitly tell you to use the frozen string literal comment. But that's explicitly for literals. There are plenty of cases where you'd want to freeze strings without them being a literal in the code. In this case there's also plenty of occurrences where you'd want to freeze hashes and arrays without them beings literals. Maybe I should have rephrased the ticket, it's definitely not just for the benefit of lint-based development.

#3 Updated by nobu (Nobuyoshi Nakada) 2 months ago

  • Description updated (diff)
  • Subject changed from Adding @+ and @- to hash and array to Adding +@ and -@ to hash and array

#4 [ruby-core:87150] Updated by rab (Rob Biedenharn) about 1 month ago

If -@ is supposed to return a frozen copy, is that patch really doing that? The tests don't seem to ensure that. Do rb_hash_freeze and rb_ary_freeze make copies first or .freeze the given object?

#5 [ruby-core:87468] Updated by kddeisz (Kevin Deisz) 15 days ago

This patch is adding -@ and +@ to array and hash, mirroring the logic of string's version of those methods. So for -@ if the array or hash is already frozen, it just returns the object, otherwise it returns a frozen copy of it. The opposite for +@.

#6 [ruby-core:87472] Updated by rab (Rob Biedenharn) 14 days ago

My question is whether this would pass:

  def test_uminus
    a = { a: 1, b: 2, c: 3 }

    refute a.frozen?
    assert (-a).frozen?

    a = { a: 1, b: 2, c: 3 }.freeze
    assert_equal a, -a

    # * If the hash is frozen, then return the hash itself.
    fa = { a: 1, b: 2, c: 3 }.freeze
    assert_equal fa, -fa
    assert_equal fa.object_id, (-fa).object_id

    # * If the hash is not frozen, return a frozen copy of it.
    ua = { a: 1, b: 2, c: 3 }
    assert_equal ua, -ua
    refute_equal ua.object_id, (-ua).object_id
  end

as the code simply return rb_hash_freeze(hsh); when not OBJ_FROZEN(hsh).

#7 [ruby-core:87473] Updated by Hanmac (Hans Mackowiak) 14 days ago

we need to specify it, that -@ and +@ are not doing deep freeze (they don't freeze the values of hash or elements of array)

people might do this:


VAL = -["abc"]

and suspect the string inside the array to be frozen too

or are we asume now that frozen-string-literal is true for this?

#8 [ruby-core:87474] Updated by kddeisz (Kevin Deisz) 14 days ago

Happy to specify it in the docs, but it would be odd to assume that it did since .freeze itself doesn't.

Also available in: Atom PDF