Struct is cleverer than the documentation claims

P

Paul Butcher

The Pickaxe book asserts that it will be possible to pass a block to
Struct.new in Ruby 1.9. While spelunking the code, I discovered that the
functionality has actually been present since 1.8.3. I've blogged about
this here:

http://www.texperts.com/2007/09/03/hidden-feature-in-rubys-struct/

But reading this mailing list, I notice that there's another way to
achieve a similar effect, specifically deriving from Struct.new.

So, both of the following achieve broadly the same effect:
Customer = Struct.new:)name, :address) do
def to_s
"Customer called '#{name}' living at '#{address}'"
end
end
class Customer < Struct.new:)name, :address)
def to_s
"Customer called '#{name}' living at '#{address}'"
end
end

Which leads to the question, what *are* the differences, and should I
prefer one approach over the other?

Thanks in advance for any light you can cast on this!

Paul.
 
R

Robert Klemme

2007/9/4 said:
The Pickaxe book asserts that it will be possible to pass a block to
Struct.new in Ruby 1.9. While spelunking the code, I discovered that the
functionality has actually been present since 1.8.3. I've blogged about
this here:

http://www.texperts.com/2007/09/03/hidden-feature-in-rubys-struct/

But reading this mailing list, I notice that there's another way to
achieve a similar effect, specifically deriving from Struct.new.

So, both of the following achieve broadly the same effect:



Which leads to the question, what *are* the differences, and should I
prefer one approach over the other?

Well, difference is that you get two classes vs. one class. I
frequently use the first idiom because I do not see the point in
creating two classes for this scenario. IMHO a base class makes sense
only if you want to inherit multiple times or separate concerns.
Neither is the case here.

Kind regards

robert
 
J

James Edward Gray II

So, both of the following achieve broadly the same effect:



Which leads to the question, what *are* the differences, and should I
prefer one approach over the other?

Thanks in advance for any light you can cast on this!

I too feel the block is better.

You can occasionally run into issues with the base class form. For
example, when Rails does it's reloading magic on a file containing
such a construct you will receive an error.

James Edward Gray II
 
P

Paul Brannan

Why not reopen the class?

Customer = Struct.new:)name, :address)
class Customer
def to_s
"Customer called '#{name}' living at '#{address}'"
end
end

Paul
 
R

Robert Klemme

2007/9/4 said:
Why not reopen the class?

Customer = Struct.new:)name, :address)
class Customer
def to_s
"Customer called '#{name}' living at '#{address}'"
end
end

Why should I reopen a class if I can have everything with the block?

Customer = Struct.new :name, :address do
def to_s
"Customer called '#{name}' living at '#{address}'"
end
end

Kind regards

robert
 
D

Daniel DeLorme

Robert said:
Why should I reopen a class if I can have everything with the block?

Customer = Struct.new :name, :address do
def to_s
"Customer called '#{name}' living at '#{address}'"
end
end

because, say, you'd want to add a constant to that class
Customer = Struct.new :name, :address do
K = 42
end
Customer::K
(irb):7: warning: toplevel constant K referenced by Customer::K

Daniel
 
L

Logan Capaldo

because, say, you'd want to add a constant to that class
Customer = Struct.new :name, :address do
K = 42
end
Customer::K
(irb):7: warning: toplevel constant K referenced by Customer::K
This is workaroundable, if a bit ugly as I recently learned:
Customer = Struct.new :name, :address do
self::K = 42
end
Customer::K
 
G

Giles Bowkett

I too feel the block is better.
You can occasionally run into issues with the base class form. For
example, when Rails does it's reloading magic on a file containing
such a construct you will receive an error.

I have some code in a Rails app which depends on a class derived from
Struct. I basically used that to create a presenter. I just switched
that class to a block form - I'd been using the class form - and the
unit tests all went nuts. Rails *thought* that its standard
expectation, that file xyz.rb will define Xyz, was violated. I got
"expected xyz.rb to define Xyz" errors, even though xyz.rb really
*did* define Xyz. So it kind of seems like a damned if you do, damned
if you don't here, with Structs and Rails.

--
Giles Bowkett

Blog: http://gilesbowkett.blogspot.com
Portfolio: http://www.gilesgoatboy.org
Tumblelog: http://giles.tumblr.com/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,970
Messages
2,570,162
Members
46,710
Latest member
bernietqt

Latest Threads

Top