While I understand the (very valid) reasons that my RCR [see: 
http://rcrchive.net/rcr/RCR/RCR201] got shot down, an underlying problem 
still remains for me.

I want to provide access to a full collection of elements (returned as 
an array, or iterated through an arbitrary .each{} block), but not let 
the objects be modified.

Is this possible?

For example, assume that a House has Furniture and ArtObjects inside it. 
I need to be able to modify those collections independently; at any time 
give external objects access to read the full collection; and (the hard 
part) prevent the objects in the collections from being changed.


class House
	attr_reader(:furniture,:jewelry,:furnitureValue,:jewelryValue)
	def initialize
		@furniture,@jewelry=[],[]
		@furnitureValue,@jewelryValue=0,0
	end
	def addFurniture (*newPieces)
		@furniture.push(*newPieces)
		newPieces.each{ |p| @furnitureValue+=p.value }
	end
	def addJewelry (*newPieces)
		@jewelry.push(*newPieces)
		newPieces.each{ |p| @jewelryValue+=p.value }
	end
end
class Obj
	attr_accessor(:name,:value)
	def initialize(name,value)
		@name,@value=name,value
	end
end

myHouse = House.new
myHouse.addFurniture( Obj.new('Chair',100), Obj.new('Table',200) )
myHouse.furniture.each{ |p| puts p.name } #fine
myHouse.furniture.each{ |p| p.value*=2 }
#uh-oh! myHouse.furnitureValue is now out of sync



The problem cannot be solved by freezing @furniture, since I want to be 
able to modify it at any time. The problem could be sort of solved by...

def furniture
	return @furniture.dup
end

....except that (a) this provides 'silent' protection (the code can 
modify the values, it just doesn't do what was expected) and (b) the 
returned array is no longer synced with the original:

foo = myHouse.furniture
myHouse.addFurniture( Obj.new('Credenza',1000) )
# foo has two items, the house really has three.



So...how do I solve this? The problem is that a 'read-only' copy of an 
array doesn't prevent code from getting a read-only reference to an 
element in that array, and then modifying it directly.


[And as an aside...I realize that the particular problem could be solved 
  if I either disallowed .value= or recalculated the furnitureValue by 
iterating the array each time it was asked for. Or I could have the 
furniture pieces know what house they are in, and any time they are 
changed have them tell the house that they were modified and any 
dependent information needs to be recalculated. While all are solutions 
to the above, I can sense that I'm going to be repeatedly bumping up 
against this problem...the desire to keep a collection of elements who 
should be able to be read, but not directly modified.]