Project

General

Profile

Feature #15504

Freeze all Range object

Added by ko1 (Koichi Sasada) 9 months ago. Updated 4 months ago.

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

Description

Abstrcat

Range is now non-frozen. How about to freeze all of Range objects?

Background

We freeze some type of objects, Numerics (r47523) and Symbols [Feature #8906].
I believe making objects immutable solves some kind of programming difficulties.

Range is mutable, at least it is written in Range literal. So we can write the following weird program.

2.times{
  r = (1..3)
  p r.instance_variable_get(:@foo)
  #=> 1st time: nil
  #=> 2nd time: :bar
  r.instance_variable_set(:@foo, :bar)
}

in range.c, there is a comment (thanks znz-san):

static void
range_modify(VALUE range)
{
    rb_check_frozen(range);
    /* Ranges are immutable, so that they should be initialized only once. */
    if (RANGE_EXCL(range) != Qnil) {
    rb_name_err_raise("`initialize' called twice", range, ID2SYM(idInitialize));
    }
}

Patch

Index: range.c
===================================================================
--- range.c (リビジョン 66699)
+++ range.c (作業コピー)
@@ -45,6 +45,8 @@
     RANGE_SET_EXCL(range, exclude_end);
     RANGE_SET_BEG(range, beg);
     RANGE_SET_END(range, end);
+
+    rb_obj_freeze(range);
 }

 VALUE

Discussion

There are several usage of mutable Range in tests.

  • (1) taint-flag
  • (2) add singleton methods.
  • (3) subclass with mutable states

Maybe (2) and (3) are points.

Thanks,
Koichi

History

Updated by marcandre (Marc-Andre Lafortune) 9 months ago

I think that (2) and (3) are indeed capital points. Freezing range litterals (only) might be a better idea? with an approach like frozen string literals?

Not that even frozen ranges aren't completely immutable:

r = ('a'..'z').freeze
r.end.upcase!
r # => "a".."Z" 

Updated by Eregon (Benoit Daloze) 4 months ago

I think it would make sense to freeze Range literals.

Adding methods to Range might be reasonable, but singleton methods, I would think much less so.

Updated by mame (Yusuke Endoh) 4 months ago

I guess Eregon (Benoit Daloze) came from #15950. Will ary[-3..] be as efficient as ary[-3, 3] by freezing and deduping a literal (-3..)? Looks good if we can confirm it by an experiment.

Some thoughts:

  • Even if a range is frozen, ("a".."z") should not be deduped because of the reason marcandre (Marc-Andre Lafortune) said.
  • I'm for freezing all Ranges, not only Range literals. I hate the idea of freezing only literals because casually mixing frozen and unfrozen objects leads to hard-to-debug bugs that depend upon data flow.
  • It would be the most elegant if the combination of MJIT and escape analysis solves this kind of performance problems.

Also available in: Atom PDF