On Aug 22, 2005, at 2:31 AM, Robert Klemme wrote:
> A simpler alternative is to just use Struct:
>
> # direct
> Song = Struct.new :name, :artist, :duration
>
> class Song
>   # other methods
> end

Wait wait wait...I never grokked Struct before.

Is it really just a convenient factory for generating classes with a  
set of accessor properties, and a constructor that accepts zero or  
more of those properties in order?

Holy crap, I see that Song.class is in fact Class.

I may finally get it! Re-reading the ri documentation for Struct, I  
see that the above is sort of what it's trying to say. But the  
wording always made me believe that the returned object was some sort  
of non-class class. Some half-breed freakiness.


The combination of the name and documentation threw me off before. I  
suppose 'Struct' sort of works, but something like  
'AttributeClass' (while wordier and not as memorable). So apparently  
I have no better suggestion for the name. But for the documentation...

At a minimum, I suggest replacing the first sentence:
"A +Struct+ is a convenient way to bundle a number of attributes  
together, using accessor methods, without having to write an explicit  
class."

Maybe I'm the only one (am I the only one?) but that makes it sound  
like the return value isn't a class. Instead, I suggest something like:

The +Struct+ class provides a convenient way to quickly create a  
class that contains a set of attributes. In addition to predefining  
the accessor methods for these attributes, the returned class  
contains other instance methods for accessing and modifying the  
attributes. (These methods are documented below as instance methods  
of the Struct class, but are in fact methods available to instances  
of the class returned from the call to Struct.new).

For example:
   User = Struct.new( :first, :last, :email )
   p User.class       #=> Class
   p User.superclass  #=> Struct

   nobody = User.new
   gk = User.new( 'Gavin', 'Kistner' )
   p nobody      #=> #<struct User first=nil, last=nil, email=nil>
   p gk          #=> #<struct User first="Gavin", last="Kistner",  
email=nil>
   p gk.size     #=> 3
   gk.email = 'gavin / refinery.com'

   p gk.members         #=> ["first", "last", "email"]
   p gk.values          #=> ["Gavin", "Kistner", "gavin / refinery.com"]
   p gk.values_at(1..2) #=> ["Kistner", "gavin / refinery.com"]
   p gk.first           #=> "Gavin"
   p gk['last']         #=> "Kistner"

   class User
     def fullname
       "#{first} #{last}"
     end
   end

   p gk.fullname         #=> "Gavin Kistner"




(I think it's very helpful to have an example usage at the very top  
of the documentation, showing a simple usage with a type of object  
that everyone understands. Obviously, it doesn't have to be my name  
or email, though ;)

Also, the documentation for the Struct#values_at method seems to have  
been lifted from the Array#values_at method, without changing the  
example code to use a Struct rather than array. The example should be  
something like:

Stuff = Struct.new( :a, :b, :c, :d, :e, :f )
chars = Stuff.new( 'a1', 'b1', 'c1', 'd1', 'e1', 'f1' )
p chars.values_at(1, 3, 5)     #=> ["b1", "d1", "f1"]
p chars.values_at(-1, -3, -5)  #=> ["f1", "d1", "b1"]
p chars.values_at(1..3, 2...5) #=> ["b1", "c1", "d1", "c1", "d1", "e1"]
p chars.values_at(1,7)  #=> offset 7 too large for struct(size:6)  
(IndexError)


(Aside: Has anyone ever used the #values_at method of the Struct  
class? If so, what for?)


cc: ruby-doc mailing list