ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
From: "tenderlovemaking (Aaron Patterson)" <noreply@ruby-lang.org>
To: ruby-core@ruby-lang.org
Subject: [ruby-core:105381] [Ruby master Feature#18035] Introduce general model/semantic for immutable by default.
Date: Wed, 22 Sep 2021 21:25:48 +0000 (UTC)	[thread overview]
Message-ID: <redmine.journal-93795.20210922212548.3344@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-18035.20210709081055.3344@ruby-lang.org

Issue #18035 has been updated by tenderlovemaking (Aaron Patterson).


jeremyevans0 (Jeremy Evans) wrote in #note-11:
> @maciej.mensfeld alluded to this already, but one thing to consider is that no object in Ruby is truly immutable unless all entries in `object.singleton_class.ancestors` are also frozen/immutable.

Are they not?  It seems like for Arrays they are (I haven't checked other types), so maybe there's some precedent:

```ruby
x = [1, 2, 3].freeze

Mod = Module.new { def foo; end }

begin
  x.extend(Mod)
rescue FrozenError
  puts "can't extend"
end

begin
  def x.foo; end
rescue FrozenError
  puts "can't def"
end

begin
  y = x.singleton_class
  def y.foo; end
rescue FrozenError
  puts "can't def singleton"
end
```

----------------------------------------
Feature #18035: Introduce general model/semantic for immutable by default.
https://bugs.ruby-lang.org/issues/18035#change-93795

* Author: ioquatix (Samuel Williams)
* Status: Open
* Priority: Normal
----------------------------------------
It would be good to establish some rules around mutability, immutability, frozen, and deep frozen in Ruby.

I see time and time again, incorrect assumptions about how this works in production code. Constants that aren't really constant, people using `#freeze` incorrectly, etc.

I don't have any particular preference but:

- We should establish consistent patterns where possible, e.g.
  - Objects created by `new` are mutable.
  - Objects created by literal are immutable.

We have problems with how `freeze` works on composite data types, e.g. `Hash#freeze` does not impact children keys/values, same for Array. Do we need to introduce `freeze(true)` or `#deep_freeze` or some other method?

Because of this, frozen does not necessarily correspond to immutable. This is an issue which causes real world problems.

I also propose to codify this where possible, in terms of "this class of object is immutable" should be enforced by the language/runtime, e.g.


```ruby
module Immutable
  def new(...)
    super.freeze
  end
end

class MyImmutableObject
  extend Immutable

  def initialize(x)
    @x = x
  end
  
  def freeze
    return self if frozen?
    
    @x.freeze
    
    super
  end
end

o = MyImmutableObject.new([1, 2, 3])
puts o.frozen?
```

Finally, this area has an impact to thread and fiber safe programming, so it is becoming more relevant and I believe that the current approach which is rather adhoc is insufficient.

I know that it's non-trivial to retrofit existing code, but maybe it can be done via magic comment, etc, which we already did for frozen string literals.



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

  parent reply	other threads:[~2021-09-22 21:26 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-09  8:10 [ruby-core:104560] [Ruby master Bug#18035] Introduce general module for immutable by default samuel
2021-07-09  8:11 ` [ruby-core:104561] [Ruby master Bug#18035] Introduce general model/semantic " samuel
2021-07-09  8:48 ` [ruby-core:104563] " duerst
2021-07-09  9:51 ` [ruby-core:104566] " samuel
2021-08-10 19:11 ` [ruby-core:104868] [Ruby master Feature#18035] " eregontp
2021-09-22  7:51 ` [ruby-core:105370] " ioquatix (Samuel Williams)
2021-09-22 10:05 ` [ruby-core:105372] " Eregon (Benoit Daloze)
2021-09-22 12:39 ` [ruby-core:105373] " Dan0042 (Daniel DeLorme)
2021-09-22 20:19 ` [ruby-core:105378] " maciej.mensfeld (Maciej Mensfeld)
2021-09-22 20:57 ` [ruby-core:105379] " jeremyevans0 (Jeremy Evans)
2021-09-22 21:25 ` tenderlovemaking (Aaron Patterson) [this message]
2021-09-22 21:55 ` [ruby-core:105383] " jeremyevans0 (Jeremy Evans)
2021-09-22 22:07 ` [ruby-core:105384] " tenderlovemaking (Aaron Patterson)
2021-09-22 22:10 ` [ruby-core:105385] " ioquatix (Samuel Williams)
2021-09-22 22:32 ` [ruby-core:105386] " jeremyevans0 (Jeremy Evans)
2021-09-22 23:39 ` [ruby-core:105389] " ioquatix (Samuel Williams)
2021-09-23  2:04 ` [ruby-core:105390] " jeremyevans0 (Jeremy Evans)
2021-09-26 23:08 ` [ruby-core:105430] " ioquatix (Samuel Williams)
2021-09-26 23:10 ` [ruby-core:105431] " ioquatix (Samuel Williams)
2021-10-03 12:21 ` [ruby-core:105532] " Eregon (Benoit Daloze)
2021-10-03 12:25 ` [ruby-core:105533] " Eregon (Benoit Daloze)
2021-10-19  4:20 ` [ruby-core:105666] " ko1 (Koichi Sasada)
2021-10-20 14:33 ` [ruby-core:105697] " Eregon (Benoit Daloze)
2021-10-21  3:21 ` [ruby-core:105709] " ioquatix (Samuel Williams)
2021-10-21  9:12 ` [ruby-core:105722] " Eregon (Benoit Daloze)
2021-10-21  9:20 ` [ruby-core:105723] " Eregon (Benoit Daloze)
2021-10-21  9:43 ` [ruby-core:105726] " Eregon (Benoit Daloze)
2021-10-25  1:28 ` [ruby-core:105764] " ioquatix (Samuel Williams)
2021-10-25  1:39 ` [ruby-core:105765] " nobu (Nobuyoshi Nakada)
2021-10-25  2:19 ` [ruby-core:105767] " ioquatix (Samuel Williams)
2021-10-25 14:48 ` [ruby-core:105789] " Dan0042 (Daniel DeLorme)
2021-11-09 16:33 ` [ruby-core:105991] " Dan0042 (Daniel DeLorme)
2021-11-09 16:42 ` [ruby-core:105992] " Eregon (Benoit Daloze)
2021-11-09 16:47 ` [ruby-core:105993] " Eregon (Benoit Daloze)
2023-12-28  8:52 ` [ruby-core:115953] [Ruby master Feature#18035] Introduce general model/semantic for immutability ioquatix (Samuel Williams) via ruby-core
2024-01-04 16:27 ` [ruby-core:116011] " matheusrich (Matheus Richard) via ruby-core
2024-01-05 16:06 ` [ruby-core:116034] " Dan0042 (Daniel DeLorme) via ruby-core
2024-01-14  3:12 ` [ruby-core:116196] " ioquatix (Samuel Williams) via ruby-core
2024-01-14  4:31 ` [ruby-core:116199] " ioquatix (Samuel Williams) via ruby-core
2024-03-06  3:46 ` [ruby-core:117063] " ioquatix (Samuel Williams) via ruby-core

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.ruby-lang.org/en/community/mailing-lists/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=redmine.journal-93795.20210922212548.3344@ruby-lang.org \
    --to=ruby-core@ruby-lang.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).