[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Array#modified

Juozas Gaigalas

1/15/2007 1:53:00 PM

I'm looking for a simple and short solution/library that does this:

a = []

def a.modified
puts "Array a changed"
end

a << 'x'
puts a
a[0] = 'y'
puts a

----OUTPUT----
Array a changed
x
Array a changed
y

--
Posted via http://www.ruby-....

8 Answers

Tim Hunter

1/15/2007 2:04:00 PM

0

Juozas Gaigalas wrote:
> I'm looking for a simple and short solution/library that does this:
(snip)
> ----OUTPUT----
> Array a changed
> x
> Array a changed
> y

Check out the Observable class in the standard library.

--
Posted via http://www.ruby-....

Gregory Seidman

1/15/2007 2:20:00 PM

0

On Mon, Jan 15, 2007 at 10:52:37PM +0900, Juozas Gaigalas wrote:
> I'm looking for a simple and short solution/library that does this:
>
> a = []
>
> def a.modified
> puts "Array a changed"
> end
>
> a << 'x'
> puts a
> a[0] = 'y'
> puts a
>
> ----OUTPUT----
> Array a changed
> x
> Array a changed
> y

You can sort of do this, but an object does not know what variable(s) it is
assigned to, so you will never be able to get the "Array a changed" message
from it directly. Try the following, however:

module ArrayWatch
def is_modified?
@modified
end

def reset_modified
@modified = false
end

def []=(k, v)
@modified = true
super(k, v)
end

def <<(v)
@modified = true
super(v)
end

def concat(v)
@modified = true
super(v)
end

def push(*v)
@modified = true
super(*v)
end

def unshift(*v)
@modified = true
super(*v)
end

def replace(v)
@modified = true
super(v)
end

def slice!(*v)
@modified = true
super(*v)
end

def compact!
@modified = true
super
end

def sort!(&block)
@modified = true
super &block
end

def uniq!
@modified = true
super
end

def reverse!
@modified = true
super
end

def flatten!
@modified = true
super
end

def collect!(&block)
@modified = true
super &block
end

def map!(&block)
@modified = true
super &block
end

def delete_at(i)
@modified = true
super(i)
end

def delete(v, &block)
@modified = true
super(v, &block)
end

def delete_if(&block)
@modified = true
super &block
end

def reject!(&block)
@modified = true
super &block
end

def shift
@modified = true
super
end

def pop
@modified = true
super
end

end

a = []
a.extend ArrayWatch

def a.to_s
"a #{ is_modified? ? 'is' : 'is not' } modified"
end

puts a
a << 'x'
puts a
a.reset_modified
puts a
a[0] = 'y'
puts a

--Greg


Juozas Gaigalas

1/15/2007 2:21:00 PM

0

Tim Hunter wrote:
> Juozas Gaigalas wrote:
>> I'm looking for a simple and short solution/library that does this:
> (snip)
>> ----OUTPUT----
>> Array a changed
>> x
>> Array a changed
>> y
>
> Check out the Observable class in the standard library.

Thanks for your prompt reply. Unfortunately Observable is not what I'm
looking for. It requires manually setting "changed" state to true on
every operation that modifies the array. I'm looking for something that
overrides all of the methods that can modify an array (<<, pop, shift,
push, []=, filter, etc.) then calls the old method and finally invokes
the "modified" callback.

I'm assuming something like this exists (specifically for the Array
class). I could write it myself, but I'd prefer to reuse existing code.




--
Posted via http://www.ruby-....

Robert Klemme

1/15/2007 2:49:00 PM

0

On 15.01.2007 15:20, Gregory Seidman wrote:
> On Mon, Jan 15, 2007 at 10:52:37PM +0900, Juozas Gaigalas wrote:
>> I'm looking for a simple and short solution/library that does this:
>>
>> a = []
>>
>> def a.modified
>> puts "Array a changed"
>> end
>>
>> a << 'x'
>> puts a
>> a[0] = 'y'
>> puts a
>>
>> ----OUTPUT----
>> Array a changed
>> x
>> Array a changed
>> y
>
> You can sort of do this, but an object does not know what variable(s) it is
> assigned to, so you will never be able to get the "Array a changed" message
> from it directly. Try the following, however:
>
> module ArrayWatch
> def is_modified?
> @modified
> end
....

Alternative approach would be to use Delegator to wrap an Array instance.

OP, what are you trying to achieve? What is the problem you are trying
to solve?

Kind regards

robert

Marc Heiler

1/15/2007 3:32:00 PM

0

"I'm assuming something like this exists (specifically for the Array
class). I could write it myself, but I'd prefer to reuse existing code."

Ok, I dont know myself, but there seems to exist a very
small "event" based .. uhm thing, made possible in an easy
manner already, like so

def StdLiving.inherited(sub)

Sure, its not what you need though. :)

I'd love to get event states from classes like Array in this case,
would remind me a bit of the basic GUI state-events, like
button_pressed ... or value_changed ;)

PS: I think there exists a bigger event framework for Ruby too
though... havent checked it yet so cant tell anything

--
Posted via http://www.ruby-....

Florian Frank

1/15/2007 4:11:00 PM

0

Juozas Gaigalas wrote:
> I'm looking for a simple and short solution/library that does this:
>
> a = []
>
> def a.modified
> puts "Array a changed"
> end
>
> a << 'x'
> puts a
> a[0] = 'y'
> puts a
>
> ----OUTPUT----
> Array a changed
> x
> Array a changed
> y
>
>
class Changed
def initialize(obj, &changed)
@obj = obj
@changed = changed
end

def method_missing(id, *a, &b)
obj_before = @obj.clone
@obj.__send__(id, *a, &b)
if obj_before != @obj
@changed[@obj, id, a, b]
end
end
end

if $0 == __FILE__
a = []
c = Changed.new(a) do |obj, id, args, block|
STDOUT << "#{obj.inspect} changed by #{id}"
STDOUT << "(#{args.map { |x| x.inspect } * ','})" unless args.empty?
STDOUT << "\n"
end
c << 1
# [1] changed by <<(1)
c.to_s
c << 2
# [1, 2] changed by <<(2)
c.delete 2
# [1] changed by delete(2)
c.delete 2
c << 3
# [1, 3] changed by <<(3)
c[0] = 4
# [4, 3] changed by []=(0,4)
c.replace [6,6,6]
# [6, 6, 6] changed by replace([6, 6, 6])
c.clear
# [] changed by clear
end

--
Florian Frank


Juozas Gaigalas

1/15/2007 5:07:00 PM

0


>>
> class Changed
> def initialize(obj, &changed)
> @obj = obj
> @changed = changed
> end
>
> def method_missing(id, *a, &b)
> obj_before = @obj.clone
> @obj.__send__(id, *a, &b)
> if obj_before != @obj
> @changed[@obj, id, a, b]
> end
> end
> end

I like this solution because it's short. However, it requires cloning
the array every time a method is invoked on it, it seems that it would
slow it down too much for my needs. I'm not sure.

I think I'll google for "ruby event framework" as Marc suggested.

--
Posted via http://www.ruby-....

Verno Miller

1/15/2007 5:54:00 PM

0

> Juozas Gaigalas wrote:
>
> ..., but I'd prefer to reuse existing code.

Maybe also check out some design patterns (state pattern, observer
pattern):

http://rightfootin.blogspot.com/2006/08/implementing-state-pattern-in...

http://cwilliams.textdriven.com/articles/2006/11/02/patterns-in-ruby-observ...

Cheers,
verno

--
Posted via http://www.ruby-....