On 01/06/05, Robert Klemme <bob.news / gmx.net> wrote:
> Gavin Kistner wrote:
> > On Jun 1, 2005, at 7:49 AM, Brian Schröäer wrote:
> >> On 01/06/05, Gavin Kistner <gavin / refinery.com> wrote:
> >>> class ReadOnlyArray < Array
> >>>      alias_method :'__ro_<<', :'<<' #:nodoc:
> >>>      alias_method :__ro_insert, :insert #:nodoc:
> >>>      alias_method :__ro_delete_at, :delete_at #:nodoc:
> >>>      affectors = %w| << []= clear concat delete delete_at delete_if
> >>> fill flatten! insert map! pack pop push reject! replace reverse!
> >>> shift slice! sort! uniq! unshift |
> >>>      affectors.each{ |name| undef_method name }
> >>> end
> >> Why not create a proxy class that contains an array and only forwards
> >> the reading methods. It seems to me, that this would achieve exactly
> >> what you want.
> >
> > That's an interesting idea. What advantage do you think that would
> > offer compared to my implementation above? How would you modify the
> > internal representation when necessary? (Perhaps the constructor for
> > the proxy class receives the array that it is supposed to wrap?)
> >
> > One advantage of mine versus the proxy approach would be that by
> > actually inheriting from Array, my class supports additional methods
> > defined by the user for Array or Enumerable. (If the user has added a
> > special Array#my_collect method, my array is extended as well.)
> >
> > (I think that it's correct that it would not be possible for a custom
> > user method to modify the array, if I'm undef'ing all core methods
> > for modifying it, yes?)
> 
> require 'delegate'
> 
> class ImmutableArray < DelegateClass(Array)
>   def []=(*a) raise "Immutable!" end
>   def <<(*a) raise "Immutable!" end
>   def push(*a) raise "Immutable!" end
>   def unshift(*a) raise "Immutable!" end
> end
> 
> ?> a = [1,2,3]
> => [1, 2, 3]
> >> ia = ImmutableArray.new a
> => [1, 2, 3]
> >> ia << "bust"
> RuntimeError: Immutable!
>         from (irb):5:in `<<'
>         from (irb):13
> 
> :-))
> 
> Kind regards
> 
>     robert
> 
> 

Though this means that you have to override all methods that can
change the array. I'd shurely forget something in this case. You
forgot e.g. #clear. Therefore I'd propose to explicitly delegate the
needed methods for the application because this is easier to control.

best regards,

Brian

-- 
http://ruby.brian-schroeder.de/

Stringed instrument chords: http://chordlist.brian-schroeder.de/