From: Brian Candler Date: 2007-09-06T16:50:28+09:00 Subject: Symbols and frozen strings I just had a thought. One of the problems with using strings as hash keys is that every time you refer to them, you create a throw-away garbage string: params["id"] ^ +-- temporary string, needs to be garbage collected In Rails you have HashWithIndifferentAccess, but this actually isn't any better. Although you write params[:id], when executed the symbol is converted to a string anyway. In a Rails-like scenario, using symbols as the real keys within the hash doesn't work: the keys come from externally parsed data, which means (a) they were strings originally, and (b) if you converted them to symbols you'd risk a symbol exhaustion attack. So I thought, wouldn't it be nice to have a half-way house: being able to converting a symbol to a string, in such a way that you always got the same (frozen) string object? This turned out to be extremely easy: class Symbol def fring @fring ||= to_s.freeze end end irb(main):006:0> :foo.fring => "foo" irb(main):007:0> :foo.fring.object_id => -605512686 irb(main):008:0> :foo.fring.object_id => -605512686 irb(main):009:0> :bar.fring => "bar" irb(main):010:0> :bar.fring.object_id => -605543036 irb(main):011:0> :bar.fring.object_id => -605543036 irb(main):012:0> :bar.fring << "x" TypeError: can't modify frozen string from (irb):12:in `<<' from (irb):12 from :0 Is this a well-known approach, and/or it does it exist in any extension library? I suppose that an instance variable lookup isn't necessarily faster than always creating a temporary string with to_s and then garbage collecting it at some point later in time, but it feels like it ought to be :-) However, since I've seen discussion about string modifiers like "..."u, perhaps there's scope for adding in-language support, e.g. "..."f - frozen string, same object ID each time it's executed In that case, it might be more convenient the other way round: "..." - frozen string literal, same object "..."m - mutable (unfrozen) string literal, new objects String.new("...") - another way of making a mutable string "...".dup - and another That would break a lot of existing code, but it could be pragma-enabled. Sorry if this ground has been covered before - it's hard to keep up with ruby-talk :-) Regards, Brian.