-[NSMutableSet randomObject]

2010-05-25 Thread Michael A. Crawford
I'd like to extend Apple implementation of NSMutableSet to include a 
randomObject method.  The purpose of this method is self-explanatory and its 
potential use is I'm sure obvious to most of you.

For my first idea I thought about simply adding a category to NSMutableSet but 
any obvious implementation of -randomObject would require accessing existing 
instance variables or adding my own in order to implement the random access I 
would need to for the set.  I also don't know how objects are stored 
internally.  Is it an array?  Is it a key/value pair? I don't know.  How am I 
going to correlate the random numbers I generate with the objects in the set?

Next, I thought about using inheritance with NSMutableArray.  I even wrote some 
code:

+ (void)initialize
{
if ( self == [MCRandomlyAccessedArray class] )
{
srandom(time(NULL));
}
}

- (id)randomObject
{
// If the array is empty, throw an exception.  The caller should know 
better.
// If there is only one, return object zero every time.
// If there are only two, alternate with every access.
// If there are three or more, randomize but never provide the same object
// twice in a row.
if ( [self count] )
{
NSUInteger index = 0;

if ( [self count]  1 )
{
if ( 2 == [self count] )
{
index = (++lastObjectIndex % 2);
}
else
{
do
{
index = (random() % [self count]);
} while (index == lastObjectIndex);
}
lastObjectIndex = index;
}
return [self objectAtIndex:index];
}
else
{
[[NSException exceptionWithName:NSRangeException
 reason:@Array is empty
   userInfo:nil] raise];
}
return nil; // unreachable
}

Come to find out at runtime that this won't work either because NSMutableArray 
is abstract!

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', 
reason: '*** -[NSMutableArray addObject:]: method only defined for abstract 
class.  Define -[MCRandomlyAccessedArray addObject:]!'

This would seem to indicate that I need to write a lot more code in order to 
have a complete implementation.  I'm not in the mood to re-invent the wheel.  
I'm not lazy, I just have a lot of other code that needs to be written, which 
pertains to the big picture.

Next, I thought maybe I could simply wrap-up an NSMutableArray in my own class 
and let it do most of the heavy lifting when it comes to all of those existing 
methods.  The only problem is that I'm no expert on how to duplicate all of the 
class and instance init methods and memory management code.

So, that brings me to you lovely people.  What do you recommend?  Do I bite the 
bullet and re-implement NSMutableArray?  If so, where can I find guidance on 
this?  I love the containers provided by Apple.  They simply work and I don't 
have to think about them.  So much so, that I don't really know how they work.  
My expertise is/was in C/C++ and STL.

Is there fourth alternative or something I missed in my brief examination as 
described above?

Thanks.

-Michael
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: -[NSMutableSet randomObject]

2010-05-25 Thread Dave DeLong
What about something like:

@implementation NSSet (Random)

- (id) randomObject {
  NSArray * allObjects = [self allObjects];
  if ([allObjects count] == 0) { @throw ...; }
  return [allObjects objectAtIndex:(arc4random() % [allObjects count])];
}

@end

On May 25, 2010, at 10:49 AM, Michael A. Crawford wrote:

 I'd like to extend Apple implementation of NSMutableSet to include a 
 randomObject method.  The purpose of this method is self-explanatory and its 
 potential use is I'm sure obvious to most of you.
 
 For my first idea I thought about simply adding a category to NSMutableSet 
 but any obvious implementation of -randomObject would require accessing 
 existing instance variables or adding my own in order to implement the random 
 access I would need to for the set.  I also don't know how objects are stored 
 internally.  Is it an array?  Is it a key/value pair? I don't know.  How am I 
 going to correlate the random numbers I generate with the objects in the set?
 
 Next, I thought about using inheritance with NSMutableArray.  I even wrote 
 some code:
 
 + (void)initialize
 {
if ( self == [MCRandomlyAccessedArray class] )
{
srandom(time(NULL));
}
 }
 
 - (id)randomObject
 {
// If the array is empty, throw an exception.  The caller should know 
 better.
// If there is only one, return object zero every time.
// If there are only two, alternate with every access.
// If there are three or more, randomize but never provide the same object
// twice in a row.
if ( [self count] )
{
NSUInteger index = 0;
 
if ( [self count]  1 )
{
if ( 2 == [self count] )
{
index = (++lastObjectIndex % 2);
}
else
{
do
{
index = (random() % [self count]);
} while (index == lastObjectIndex);
}
lastObjectIndex = index;
}
return [self objectAtIndex:index];
}
else
{
[[NSException exceptionWithName:NSRangeException
 reason:@Array is empty
   userInfo:nil] raise];
}
return nil; // unreachable
 }
 
 Come to find out at runtime that this won't work either because 
 NSMutableArray is abstract!
 
 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', 
 reason: '*** -[NSMutableArray addObject:]: method only defined for abstract 
 class.  Define -[MCRandomlyAccessedArray addObject:]!'
 
 This would seem to indicate that I need to write a lot more code in order to 
 have a complete implementation.  I'm not in the mood to re-invent the wheel.  
 I'm not lazy, I just have a lot of other code that needs to be written, which 
 pertains to the big picture.
 
 Next, I thought maybe I could simply wrap-up an NSMutableArray in my own 
 class and let it do most of the heavy lifting when it comes to all of those 
 existing methods.  The only problem is that I'm no expert on how to duplicate 
 all of the class and instance init methods and memory management code.
 
 So, that brings me to you lovely people.  What do you recommend?  Do I bite 
 the bullet and re-implement NSMutableArray?  If so, where can I find guidance 
 on this?  I love the containers provided by Apple.  They simply work and I 
 don't have to think about them.  So much so, that I don't really know how 
 they work.  My expertise is/was in C/C++ and STL.
 
 Is there fourth alternative or something I missed in my brief examination as 
 described above?
 
 Thanks.
 
 -Michael
 ___
 
 Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
 
 Please do not post admin requests or moderator comments to the list.
 Contact the moderators at cocoa-dev-admins(at)lists.apple.com
 
 Help/Unsubscribe/Update your Subscription:
 http://lists.apple.com/mailman/options/cocoa-dev/davedelong%40me.com
 
 This email sent to davedel...@me.com



smime.p7s
Description: S/MIME cryptographic signature
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: -[NSMutableSet randomObject]

2010-05-25 Thread Dave DeLong
Ah, I see;  you don't want to provide the same object twice in a row.  If 
that's the case, is it really random? ;)

Dave

On May 25, 2010, at 10:52 AM, Dave DeLong wrote:

 What about something like:
 
 @implementation NSSet (Random)
 
 - (id) randomObject {
  NSArray * allObjects = [self allObjects];
  if ([allObjects count] == 0) { @throw ...; }
  return [allObjects objectAtIndex:(arc4random() % [allObjects count])];
 }
 
 @end


smime.p7s
Description: S/MIME cryptographic signature
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: -[NSMutableSet randomObject]

2010-05-25 Thread Michael A. Crawford
Hey, not bad.  Does the -allObjects method always return the same sequence?  
Did you just cobble this up or is this running in a system somewhere?  It 
doesn't do everything I want but it is definitely the better part of the 80/20 
rule.

-Michael

On May 25, 2010, at 12:52 PM, Dave DeLong wrote:

 What about something like:
 
 @implementation NSSet (Random)
 
 - (id) randomObject {
  NSArray * allObjects = [self allObjects];
  if ([allObjects count] == 0) { @throw ...; }
  return [allObjects objectAtIndex:(arc4random() % [allObjects count])];
 }
 
 @end
 
 On May 25, 2010, at 10:49 AM, Michael A. Crawford wrote:
 
 I'd like to extend Apple implementation of NSMutableSet to include a 
 randomObject method.  The purpose of this method is self-explanatory and its 
 potential use is I'm sure obvious to most of you.
 
 For my first idea I thought about simply adding a category to NSMutableSet 
 but any obvious implementation of -randomObject would require accessing 
 existing instance variables or adding my own in order to implement the 
 random access I would need to for the set.  I also don't know how objects 
 are stored internally.  Is it an array?  Is it a key/value pair? I don't 
 know.  How am I going to correlate the random numbers I generate with the 
 objects in the set?
 
 Next, I thought about using inheritance with NSMutableArray.  I even wrote 
 some code:
 
 + (void)initialize
 {
   if ( self == [MCRandomlyAccessedArray class] )
   {
   srandom(time(NULL));
   }
 }
 
 - (id)randomObject
 {
   // If the array is empty, throw an exception.  The caller should know 
 better.
   // If there is only one, return object zero every time.
   // If there are only two, alternate with every access.
   // If there are three or more, randomize but never provide the same object
   // twice in a row.
   if ( [self count] )
   {
   NSUInteger index = 0;
 
   if ( [self count]  1 )
   {
   if ( 2 == [self count] )
   {
   index = (++lastObjectIndex % 2);
   }
   else
   {
   do
   {
   index = (random() % [self count]);
   } while (index == lastObjectIndex);
   }
   lastObjectIndex = index;
   }
   return [self objectAtIndex:index];
   }
   else
   {
   [[NSException exceptionWithName:NSRangeException
reason:@Array is empty
  userInfo:nil] raise];
   }
   return nil; // unreachable
 }
 
 Come to find out at runtime that this won't work either because 
 NSMutableArray is abstract!
 
 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', 
 reason: '*** -[NSMutableArray addObject:]: method only defined for abstract 
 class.  Define -[MCRandomlyAccessedArray addObject:]!'
 
 This would seem to indicate that I need to write a lot more code in order to 
 have a complete implementation.  I'm not in the mood to re-invent the wheel. 
  I'm not lazy, I just have a lot of other code that needs to be written, 
 which pertains to the big picture.
 
 Next, I thought maybe I could simply wrap-up an NSMutableArray in my own 
 class and let it do most of the heavy lifting when it comes to all of those 
 existing methods.  The only problem is that I'm no expert on how to 
 duplicate all of the class and instance init methods and memory management 
 code.
 
 So, that brings me to you lovely people.  What do you recommend?  Do I bite 
 the bullet and re-implement NSMutableArray?  If so, where can I find 
 guidance on this?  I love the containers provided by Apple.  They simply 
 work and I don't have to think about them.  So much so, that I don't really 
 know how they work.  My expertise is/was in C/C++ and STL.
 
 Is there fourth alternative or something I missed in my brief examination as 
 described above?
 
 Thanks.
 
 -Michael
 ___
 
 Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
 
 Please do not post admin requests or moderator comments to the list.
 Contact the moderators at cocoa-dev-admins(at)lists.apple.com
 
 Help/Unsubscribe/Update your Subscription:
 http://lists.apple.com/mailman/options/cocoa-dev/davedelong%40me.com
 
 This email sent to davedel...@me.com
 
 ___
 
 Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
 
 Please do not post admin requests or moderator comments to the list.
 Contact the moderators at cocoa-dev-admins(at)lists.apple.com
 
 Help/Unsubscribe/Update your Subscription:
 http://lists.apple.com/mailman/options/cocoa-dev/michaelacrawford%40me.com
 
 This email sent to michaelacrawf...@me.com

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:

Re: -[NSMutableSet randomObject]

2010-05-25 Thread John Joyce
Implementation should probably include various options for what kind of pseudo 
randomness is desired.

On May 25, 2010, at 11:52 AM, Dave DeLong wrote:

 What about something like:
 
 @implementation NSSet (Random)
 
 - (id) randomObject {
  NSArray * allObjects = [self allObjects];
  if ([allObjects count] == 0) { @throw ...; }
  return [allObjects objectAtIndex:(arc4random() % [allObjects count])];
 }
 
 @end
 
 On May 25, 2010, at 10:49 AM, Michael A. Crawford wrote:
 
 I'd like to extend Apple implementation of NSMutableSet to include a 
 randomObject method.  The purpose of this method is self-explanatory and its 
 potential use is I'm sure obvious to most of you.
 
 For my first idea I thought about simply adding a category to NSMutableSet 
 but any obvious implementation of -randomObject would require accessing 
 existing instance variables or adding my own in order to implement the 
 random access I would need to for the set.  I also don't know how objects 
 are stored internally.  Is it an array?  Is it a key/value pair? I don't 
 know.  How am I going to correlate the random numbers I generate with the 
 objects in the set?
 
 Next, I thought about using inheritance with NSMutableArray.  I even wrote 
 some code:
 
 + (void)initialize
 {
   if ( self == [MCRandomlyAccessedArray class] )
   {
   srandom(time(NULL));
   }
 }
 
 - (id)randomObject
 {
   // If the array is empty, throw an exception.  The caller should know 
 better.
   // If there is only one, return object zero every time.
   // If there are only two, alternate with every access.
   // If there are three or more, randomize but never provide the same object
   // twice in a row.
   if ( [self count] )
   {
   NSUInteger index = 0;
 
   if ( [self count]  1 )
   {
   if ( 2 == [self count] )
   {
   index = (++lastObjectIndex % 2);
   }
   else
   {
   do
   {
   index = (random() % [self count]);
   } while (index == lastObjectIndex);
   }
   lastObjectIndex = index;
   }
   return [self objectAtIndex:index];
   }
   else
   {
   [[NSException exceptionWithName:NSRangeException
reason:@Array is empty
  userInfo:nil] raise];
   }
   return nil; // unreachable
 }
 
 Come to find out at runtime that this won't work either because 
 NSMutableArray is abstract!
 
 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', 
 reason: '*** -[NSMutableArray addObject:]: method only defined for abstract 
 class.  Define -[MCRandomlyAccessedArray addObject:]!'
 
 This would seem to indicate that I need to write a lot more code in order to 
 have a complete implementation.  I'm not in the mood to re-invent the wheel. 
  I'm not lazy, I just have a lot of other code that needs to be written, 
 which pertains to the big picture.
 
 Next, I thought maybe I could simply wrap-up an NSMutableArray in my own 
 class and let it do most of the heavy lifting when it comes to all of those 
 existing methods.  The only problem is that I'm no expert on how to 
 duplicate all of the class and instance init methods and memory management 
 code.
 
 So, that brings me to you lovely people.  What do you recommend?  Do I bite 
 the bullet and re-implement NSMutableArray?  If so, where can I find 
 guidance on this?  I love the containers provided by Apple.  They simply 
 work and I don't have to think about them.  So much so, that I don't really 
 know how they work.  My expertise is/was in C/C++ and STL.
 
 Is there fourth alternative or something I missed in my brief examination as 
 described above?
 
 Thanks.
 
 -Michael
 ___
 
 Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
 
 Please do not post admin requests or moderator comments to the list.
 Contact the moderators at cocoa-dev-admins(at)lists.apple.com
 
 Help/Unsubscribe/Update your Subscription:
 http://lists.apple.com/mailman/options/cocoa-dev/davedelong%40me.com
 
 This email sent to davedel...@me.com
 
 ___
 
 Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
 
 Please do not post admin requests or moderator comments to the list.
 Contact the moderators at cocoa-dev-admins(at)lists.apple.com
 
 Help/Unsubscribe/Update your Subscription:
 http://lists.apple.com/mailman/options/cocoa-dev/jjoyce%40apple.com
 
 This email sent to jjo...@apple.com

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: -[NSMutableSet randomObject]

2010-05-25 Thread Dave DeLong
Since an NSSet is, by definition, unordered, the allObjects method is not 
guaranteed to return the same ordering of objects every time.  However, once 
you have the array, you could easily order it yourself using 
sortedArrayUsing(Selector/Comparator/Descriptors):.

And I've used this code (or really similar code) in production stuff before.

Dave

On May 25, 2010, at 10:58 AM, Michael A. Crawford wrote:

 Hey, not bad.  Does the -allObjects method always return the same sequence?  
 Did you just cobble this up or is this running in a system somewhere?  It 
 doesn't do everything I want but it is definitely the better part of the 
 80/20 rule.
 
 -Michael


smime.p7s
Description: S/MIME cryptographic signature
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: -[NSMutableSet randomObject]

2010-05-25 Thread Thomas Davie
If this is indeed the desired effect, you're much better off writing a - 
(NSArray *)arrayByRandomlyOrderingObjects in an NSArray category, and then 
calling [[mySet allObjects] arrayByRandomlyOrderingObjects];.

Bob

On 25 May 2010, at 17:54, Dave DeLong wrote:

 Ah, I see;  you don't want to provide the same object twice in a row.  If 
 that's the case, is it really random? ;)
 
 Dave
 
 On May 25, 2010, at 10:52 AM, Dave DeLong wrote:
 
 What about something like:
 
 @implementation NSSet (Random)
 
 - (id) randomObject {
 NSArray * allObjects = [self allObjects];
 if ([allObjects count] == 0) { @throw ...; }
 return [allObjects objectAtIndex:(arc4random() % [allObjects count])];
 }
 
 @end
 ___
 
 Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
 
 Please do not post admin requests or moderator comments to the list.
 Contact the moderators at cocoa-dev-admins(at)lists.apple.com
 
 Help/Unsubscribe/Update your Subscription:
 http://lists.apple.com/mailman/options/cocoa-dev/tom.davie%40gmail.com
 
 This email sent to tom.da...@gmail.com

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: -[NSMutableSet randomObject]

2010-05-25 Thread Ricky Sharp

On May 25, 2010, at 11:49 AM, Michael A. Crawford wrote:

// If the array is empty, throw an exception.  The caller should know 
 better.
// If there is only one, return object zero every time.
// If there are only two, alternate with every access.
// If there are three or more, randomize but never provide the same object
// twice in a row.


These are definitely strange rules...  please note the following which 
describes basically all rules where n  1

In your starting state, nothing is picked.  You then pick something at random 
from the set. But, that item is not placed back in the set.  The 2nd pick comes 
from the new set.  The original item that was picked is now put back into the 
set.  So part of what's going on is a pick without replacement as well as 
pick with replacement.

Having said that, depending upon your needs, I highly recommend the Mersenne 
Twister algorithm for your psuedo-random generator.  Depending upon speed 
constraints, you may also want to experiment with a Fisher-Yates shuffle of the 
array, then grab the 0th element as the next random object.

___
Ricky A. Sharp mailto:rsh...@instantinteractive.com
Instant Interactive(tm)   http://www.instantinteractive.com



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: -[NSMutableSet randomObject]

2010-05-25 Thread Jens Alfke

On May 25, 2010, at 9:49 AM, Michael A. Crawford wrote:

// If the array is empty, throw an exception.  The caller should know 
 better.
// If there is only one, return object zero every time.
// If there are only two, alternate with every access.
// If there are three or more, randomize but never provide the same object
// twice in a row.

I don’t think you can provide this behavior as a category, because it requires 
extra state: each call has to remember what object was returned by the previous 
call. That state is per-object so it would need to live in the object. But 
categories don’t give you extra instance variables*. Even if you could put 
state into the object, I don’t think it’s a good design — what if you ended up 
with two clients that wanted to get random access to the same set and 
interleaved their calls?

It sounds like what you want is the iterator (aka enumerator) design pattern, 
where you create a separate lightweight object that returns the “next” item 
each time it’s called. You can then put the state in the iterator.

—Jens

* I know there are ways of doing this; but I still think it’s a bad idea, as 
the next sentence explains.___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com