Feature #2509
Recursive freezing?
| Status: | Assigned | Start date: | 12/21/2009 | |
|---|---|---|---|---|
| Priority: | Normal | Due date: | ||
| Assignee: | % Done: | 0% |
||
| Category: | core | |||
| Target version: | 2.0.0 |
Description
I like freezing my constants, config files I read, etc... I believe it is the typical use case for #freeze.
In all theses cases, what I really want to do is freeze everything. There is often no easy way to do this (e.g. for config files), or else one must explicitly call freeze a bunch of times, like:
DEFAULT_SEND_FILE_OPTIONS = {
:type => 'application/octet-stream'.freeze,
:disposition => 'attachment'.freeze,
}.freeze
It would be very nice if there was an easy way to freeze recursively arrays, hashes, etc...
A solution would be for #freeze to accept a level argument (similar to flatten, but the default being 1), or alternatively a boolean one (recursive = false).
Should I write a patch for this feature request?
Thanks,
Marc-André
History
Updated by shyouhei (Shyouhei Urabe) over 2 years ago
> It would be very nice if there was an easy way to freeze recursively arrays, hashes, etc...
The difficult part is those "etc". Imagine how can you freeze a lambda and its "everything"?
irb(main):001:0> a = 0
=> 0
irb(main):002:0> p = lambda { p a }.freeze
=> #<Proc:0x00007fc681b2e310@(irb):2>
irb(main):003:0> p.frozen?
=> true
irb(main):004:0> a = 1
=> 1
irb(main):005:0> p.call
1
=> nil
irb(main):006:0>
Updated by RickDeNatale (Rick DeNatale) over 2 years ago
On Sun, Dec 20, 2009 at 11:02 PM, Shyouhei Urabe <redmine@ruby-lang.org> wrote:
> Issue #2509 has been updated by Shyouhei Urabe.
>
>
>> It would be very nice if there was an easy way to freeze recursively arrays, hashes, etc...
>
> The difficult part is those "etc". Imagine how can you freeze a lambda and its "everything"?
>
> irb(main):001:0> a = 0
> => 0
> irb(main):002:0> p = lambda { p a }.freeze
> => #<Proc:0x00007fc681b2e310@(irb):2>
> irb(main):003:0> p.frozen?
> => true
> irb(main):004:0> a = 1
> => 1
> irb(main):005:0> p.call
> 1
> => nil
> irb(main):006:0>
>
The other danger to consider is where does 'everything' end. This
made me think of Ice Nine from Kurt Vonnegut's Cat's Cradle
http://en.wikipedia.org/wiki/Ice-nine
--
Rick DeNatale
Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale
Updated by marcandre (Marc-Andre Lafortune) over 2 years ago
I'm sorry for not having been more precise. My proposal would affect directly Array, Hash, Range & Struct. Traversal would be guarded against infinite recursion, like #inspect and al. Enumerator simply forwards the recursive call to the arguments used when contructing them, as if these were stored as instance variables. In std libraries: OpenStruct: nothing special to do (since sub objects are stored as instance variables) Delegate: To be more intuitive, they probably should not decrement the level to freeze, so that freezing a given object by 2 levels would have a similar effect than freezing its delegate by 2 levels. Set: Uses a hash, so should also forward the call without decrementing the level. Freezing a set would thus have similar effect to freezing an array. StringIO: Forwards the call to the underlying string. I feel the the lambda example is not an issue. The local variable "a" doesn't belong to the lambda, and lambdas have no mutating methods anyways, so any_lambda.freeze, any_lambda.freeze(-1) have the same (trivial) effect (unless they somehow get instance variables, in which case these get frozen like any other object).
Updated by znz (Kazuhiro NISHIYAMA) about 2 years ago
- Target version changed from 1.9.2 to 2.0.0
Updated by shyouhei (Shyouhei Urabe) over 1 year ago
- Status changed from Open to Assigned