[Note: parts of this message were removed to make it a legal post.]
elegant references
Acutally, there *is* an implementation already:
irb(main):002:0> s=SimpleDelegator.new nil
=> nil
irb(main):003:0> s.__getobj__
=> nil
irb(main):004:0> s.__setobj__ "foo"
=> "foo"
irb(main):005:0> s
=> "foo"
irb(main):006:0> s.__getobj__
=> "foo"
irb(main):007:0> s.__setobj__ "bar"
=> "bar"
irb(main):008:0> s.__getobj__
=> "bar"
irb(main):009:0> s.length
=> 3
irb(main):010:0> s.gsub /./, 'X'
=> "XXX"
But, this doesn't give you an lvalue reference, just an anonymous reference
(which could be used for a case b implementation). A one element Array
would work just as well:
s = ["foo"]
p s[0] # => "foo"
s[0] = "bar"
p s[0] # => "bar"
I usually make a little class with [] and []= methods that take no args in
the [], so I don't need the "0" and the [] suffix is equivalent to the *
prefix in C/C++.
Here would be an fairly efficient instance variable lvalue reference class:
class InstanceVariable
def initialize(obj, var); @obj=obj; @var=var; end
def []; @obj.instance_variable_get(@var); end
def []=(val); @obj.instance_variable_set(@var, val); end
end
node = Object.new
node.instance_variable_set
@next, nil)
node2 = Object.new
link = InstanceVariable.new(node,
next)
p link[] # => nil
link[] = node2
p link[].equal?(node2) # => true
p node.instance_variable_get
@next).equal?(node2) # => true
Here would be a more general class for referencing any lvalue:
class LValue
def initialize(&lvalue); @lvalue = lvalue; end
def []; eval(@lvalue[].to_s, @lvalue.binding); end
def []=(val); eval("proc {|v| #{@lvalue[].to_s} = v}",
@lvalue.binding)[val]; end
end
def swap(a, b); b[], a[] = a[], b[]; end
x = 1
y = 2
swap(LValue.new { :x }, LValue.new { :y })
p x # => 2
p y # => 1
Correct. For Array this could easily be build as an external class
(attached is an experimental version).
For Array, there isn't a whole lot of value for an external iterator,
because we already have something that works as a poor man's replacement -
index (an integer). The index can't do its own dereferencing (to read and
write an element), but Array can using an index. In C++ STL, an external
iterator can't do all operations either. To do an erase or insert for
example, you call a method on the container with an iterator.
I think external iterators are more useful for other data structures where
you don't have random access - linked lists, trees, etc. I guess you could
provide an index-like API (but the index might not be an integer) instead of
a normal external iterator.
BTW, another external iterator we already have is IO, which operates at a
specific point in a file.
Eric