From: Daniel Finnie Date: 2006-12-17T07:59:53+09:00 Subject: Re: Just some Ruby language ideas, comments wanted. I did something like that for the current Ruby Quiz, but it doesn't do the []=, which I think is cool. The code is a bit shorter though: class ArrayValue instance_methods.each do |m| undef_method(m) unless m =~ /^_*(method_missing|send|id)_*$/ end def initialize(origArray, origIndex) @origArray, @origIndex = origArray, origIndex end def set(newObj) @origArray[@origIndex] = newObj end def get @origArray[@origIndex] end def method_missing(method, *args) get.send(method, *args) rescue super end end class Array def to_av() ret = [] each_index {|x| ret << ArrayValue.new(self, x) } ret end end Sample usage: daniel@daniel-desktop:~$ irb -r 'arrayvalue.rb' irb(main):001:0> ary = [1, 2, 3, 4, "SomeString", :ASymbol] => [1, 2, 3, 4, "SomeString", :ASymbol] # Set the first String to 42. irb(main):002:0> ary.to_av.find{|x| x.kind_of?(String)}.set(42) => 42 # Changes are reflected in the original array. irb(main):003:0> ary => [1, 2, 3, 4, 42, :ASymbol] # Set the 3rd Numeric value to 43 irb(main):004:0> ary.to_av.select{|x| x.kind_of?(Numeric)}[2].set(43) => 43 # Changes are reflected in the original array. irb(main):005:0> ary => [1, 2, 43, 4, 42, :ASymbol] Logan Capaldo wrote: > On Sun, Dec 17, 2006 at 04:00:49AM +0900, Devin Mullins wrote: >> Daniel Finnie wrote: >>> How this would work: >>> Currently, the following would default to "i" if the element doesn't exist. >>> [4, 6, 9].fetch(4, "i") >>> This would do the same thing: >>> [4, 6, 9][4].default("i") or [4, 6, 9].fetch(4).default("i") >> I get along fine with: >> [4, 6, 9].fetch(4)||'i' >> >> Sure, it has false misses on instances of FalseClass, but I live with >> the pain. Besides, what if the above array contained nil? >> >>> This would allow things like: >>> ary = [4, nil, 6, nil] >>> ary.select{|x| x.nil?}[1].set(2) >>> ary # => [4, nil, 6, 2] >> May I suggest: >> ary.select{|x| x.nil?}[1] = 2 >> as a better interface. >> >> = isn't overridable, but []= is. >> >> I see more potential in your second thing... Build it as a stand-alone >> Ruby library first. >> >> Devin > Here, I'll evenget you started: > > % cat view.rb > class ArrayView > class ArrayIndexRef > def initialize( array, index ) > @array = array > @index = index > end > > def value > @array[@index] > end > > def value=(new_value) > @array[@index] = new_value > end > end > > def initialize( array ) > @array = array > @references = [] > end > > def [](*args) > if args.length == 1 and args.kind_of? Range or args.length > 1 > @references[*args].map { |x| x.value } > else > @references[*args].value > end > end > > def []=(index, value) > @references[index].value = value > end > > def each > @references.each do |x| > yield x.value > end > end > > > def add_ref( index ) > @references << ArrayIndexRef.new( @array, index ) > end > end > > > class Array > def select_view > r = ArrayView.new( self ) > each_with_index do |item, index| > r.add_ref( index ) if yield( item ) > end > r > end > end > > a = (1..10).to_a > > p a > b = a.select_view { |x| (x % 2).zero? } > b[0] = 42 > p a > > % ruby view.rb > [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] > [1, 42, 3, 4, 5, 6, 7, 8, 9, 10] > >