Array and NSMutableArray mutability
Hey, I was trying to implement a breadth first search where I would mutate the search queue while iterating through it. Simplified, it was something like this: numbers = [1, 2, 3, 4] numbers.each { |number| numbers << (1+number) unless number > 3 puts number } This works fine for arrays that are being made in the MacRuby VM, but if I get an array back from an Objective-C method and try to iterate over that array then I would get an exception (which segfaulted the VM) when I tried to mutate the array during iteration. Simplified, it would be something like this: numbers = NSMutableArray.alloc.init numbers.addObjectsFromArray [1, 2, 3, 4] numbers.each { |number| numbers << (1+number) unless number > 3 puts number } Should both types of arrays work the same way? An instance of NSMutableArray says its class is Array, so I thought that they would. Also, is this type of exception one that should be caught by the VM and propagated as a normal Ruby Exception that I could rescue? Mark Rada mrada@marketcircle.com
On 2011-01-30, at 23:55 , Mark Rada wrote:
Should both types of arrays work the same way? An instance of NSMutableArray says its class is Array, so I thought that they would.
There's something weird going on in there, I don't really know the details of it, but: A while back I had issues calling #count(foo) on a NSMutableArray, even though it #is_a?Array, because it tried to call ObjC's count, which doesn't take an optional argument. Whenever I need ruby semantics on an array returned from a Cocoa framework, I use Array.new(my_ns_array). Clearly your case is a bit worse than mine. I don't believe it should segfault. Anyway, I can see this Array/NSArray incomplete equivalence being a source of endless confusion. I'm curious what tradeoffs are at play here.
On 31/01/2011, at 6:37 PM, Caio Chassot wrote:
On 2011-01-30, at 23:55 , Mark Rada wrote:
Should both types of arrays work the same way? An instance of NSMutableArray says its class is Array, so I thought that they would.
There's something weird going on in there, I don't really know the details of it, but:
A while back I had issues calling #count(foo) on a NSMutableArray, even though it #is_a?Array, because it tried to call ObjC's count, which doesn't take an optional argument.
Whenever I need ruby semantics on an array returned from a Cocoa framework, I use Array.new(my_ns_array).
Anyway, I can see this Array/NSArray incomplete equivalence being a source of endless confusion. I'm curious what tradeoffs are at play here.
This behaviour is the same with most (all?) Ruby/Cocoa objects, eg. an NSString object will claim to be a Ruby String but doesn't respond to the same methods. See this ticket... https://www.macruby.org/trac/ticket/726 And yes, this can be very confusing. Henry
Hi,
I was trying to implement a breadth first search where I would mutate the search queue while iterating through it. Simplified, it was something like this:
numbers = [1, 2, 3, 4] numbers.each { |number| numbers << (1+number) unless number > 3 puts number }
Modifying the object you're iterating on is undefined behavior, even in Ruby: http://www.ruby-forum.com/topic/188211#821599 It's generally easy to modify your code to either iterate on a copy of the array or looping with an index (numbers.length.times {...} or i = 0; while i < numbers.length; ..; end depending on what you want to do).
Also, is this type of exception one that should be caught by the VM and propagated as a normal Ruby Exception that I could rescue?
It should definitively be propagated as a normal Ruby exception. Could you file a ticket on trac for that?
Hi,
Should both types of arrays work the same way? An instance of NSMutableArray says its class is Array, so I thought that they would.
This is indeed pretty confusing, so I filed a ticket to be able to easily differentiate Array and NSMutableArray: https://www.macruby.org/trac/ticket/1141 I can't really remember why we did it in the first place, maybe dating from the time when Array was using NSArray internally.
participants (4)
-
Caio Chassot
-
Henry Maddocks
-
Mark Rada
-
Vincent Isambart