OpenStruct#update ?

F

Florian Gross

trans. (T. Onoma) said:
| > | Objection to the objection: The singleton pattern is not widely used in
| > | Ruby. Couldn't we rename the implementation of it? Maybe something like
| > | "SingleInstanceClass"?
| >
| > Well, I just used it. And the rest of the OOP world knows Singleton, yes?
|
| What did you use it for and why would another name be a problem in your
| case?

In current project I use it for markup BaseAdapter Subclasses. In past I've
used it for database pool, object pool, and CGI Singleton. There are others
too that I can't recall off the top of my head.

Why don't use globals (or a constant) or a Module with module functions
instead? I don't understand how singletons are useful for pools however.
Could you explain?
I actually started a thread on this matter a few weeks ago, David brought up
some good points. The nice thing about a singleton is that it is easily
initialized. Pretty sure the implementation is also thread safe. Two big
pluses in my book. Also, from a different vantage, singletons are nothing
more than fully unique multitons. So are multitons also outmoded? And, if
what you say is so, then what do other languages, lacking Ruby's proxy class,
use in their stay? Should't such a "pattern" be common ground across OOPLs?

Multitons are however often immutable value objects meaning that they
can not be used as hidden global state.
The problem I have is very simple: constant reoccuring confusion in
discussions. Look back just a few post --it's even happened in this thread!
And it was you who once again had to explain:

<quote>
Sorry, I was talking about the pattern that lets you only create a
single instance of a class. See singleton.rb in Ruby's standard library.
</quote>

Don't you get tired of doing this? Honestly, I see this same kind of thing
every time singleton comes up. There was a mention of singleton in the
current DI thread, and guess what? I had no idea which one was meant. And
changing the name of the module for Singleton to SingletonPattern or
Pattern::Singleton is not going to help this problem at all.

Of course I'm tired of this. That's why I wanted to rename singleton.rb
into SingleInstanceClass. (Which explains what it does in simpler terms
than "Singleton" anyway.) It's just that the more common thing always
deserves the simpler and shorter name. Classes that can only be
instantiated once seem not to be useful enough (except as a way of using
globals without using globals in which case they are an anti-pattern) to
deserve this name. Of course this would be no problem if matz had
decided for one of the other alternatives -- but isn't "singleton class"
the term that is most commonly used already?
 
T

trans. (T. Onoma)

| > | > | Objection to the objection: The singleton pattern is not widely
| > | > | used in Ruby. Couldn't we rename the implementation of it? Maybe
| > | > | something like "SingleInstanceClass"?
| > | >
| > | > Well, I just used it. And the rest of the OOP world knows Singleton,
| > | > yes?
| > |
| > | What did you use it for and why would another name be a problem in your
| > | case?
| >
| > In current project I use it for markup BaseAdapter Subclasses. In past
| > I've used it for database pool, object pool, and CGI Singleton. There are
| > others too that I can't recall off the top of my head.
|
| Why don't use globals (or a constant) or a Module with module functions
| instead? I don't understand how singletons are useful for pools however.
| Could you explain?

Well, with globals I can't control namespace. And modules have there one
issues --like what if I change my mind? And not being able to subclass.

As for a constant, in a way that basically what one's doing. But the singleton
also prevents any other instance of that kind. Granted in many cases that
probably doesn't really matter. So sure I could probably just use a constant
and not worry about the potential abuses. Of course I could also never bother
to make a method private too. Maybe that's overstating it a bit, but the
point is, there are always multiple ways of doing things. Singleton Pattern
is just another tool, and if the shoe fits then where it. I don;t think we
should throw it out just b/c it's easy to abuse.

| > I actually started a thread on this matter a few weeks ago, David brought
| > up some good points. The nice thing about a singleton is that it is
| > easily initialized. Pretty sure the implementation is also thread safe.
| > Two big pluses in my book. Also, from a different vantage, singletons are
| > nothing more than fully unique multitons. So are multitons also outmoded?
| > And, if what you say is so, then what do other languages, lacking Ruby's
| > proxy class, use in their stay? Should't such a "pattern" be common
| > ground across OOPLs?
|
| Multitons are however often immutable value objects meaning that they
| can not be used as hidden global state.

How about InfinityClass. Singletons can be immutable too.

| > The problem I have is very simple: constant reoccuring confusion in
| > discussions. Look back just a few post --it's even happened in this
| > thread! And it was you who once again had to explain:
| >
| > <quote>
| > Sorry, I was talking about the pattern that lets you only create a
| > single instance of a class. See singleton.rb in Ruby's standard library.
| > </quote>
| >
| > Don't you get tired of doing this? Honestly, I see this same kind of
| > thing every time singleton comes up. There was a mention of singleton in
| > the current DI thread, and guess what? I had no idea which one was meant.
| > And changing the name of the module for Singleton to SingletonPattern or
| > Pattern::Singleton is not going to help this problem at all.
|
| Of course I'm tired of this. That's why I wanted to rename singleton.rb
| into SingleInstanceClass. (Which explains what it does in simpler terms
| than "Singleton" anyway.) It's just that the more common thing always
| deserves the simpler and shorter name. Classes that can only be
| instantiated once seem not to be useful enough (except as a way of using
| globals without using globals in which case they are an anti-pattern) to
| deserve this name. Of course this would be no problem if matz had
| decided for one of the other alternatives -- but isn't "singleton class"
| the term that is most commonly used already?

Not substantially so. We've seen cases of the term virtual class. And I've
seen the term metaclass at least as often --especially in libs.

The monotheistic doctrine of an OOP developer: God is Singleton.

T.
 
T

trans. (T. Onoma)

Yes, no, maybe?

--- Original Message ---

On Sunday 14 November 2004 06:16 pm, Yukihiro Matsumoto wrote:
| Can you be more specific, preferably with code example?
|
| matz.

Ah, what the hek! I pulled down 1.9 and modified. Below you will find code.
Let me know if you'd like me to send code as attachment via private mail.

Okay so the trick was simply to move everything into a mixin module (expect
the initialize method). I also changed @table to @__table__ to help prevent
possible name clash. The only other changed required was using

@__table__ ||= {}

in a number of places (too bad no better way to do that). Finally I just
called the module OpenStructable --seems like a good a name as any.

Also, I found what looks to be a bug in current 1.9 version. The initialize
method wasn't calling the newly added #new_ostruct_member method. I fixed and
added #update method. Also, is #new_ostruct_member supposed to be private?
Currently it is public. If it remains public, I recommend a more generic
name. Not sure what though.

Hope you like,
T.

------------

#
# = ostruct.rb: OpenStruct implementation
#
# Author:: Yukihiro Matsumoto
# Contributor:: Thomas Sawyer
# Documentation:: Gavin Sinclair
#
# OpenStruct allows the creation of data objects with arbitrary attributes.
# See OpenStruct for an example. OpenStruct is implemented with a resuable
# mixin module OpenStructable.
#

# OpensStructable is a mixin module which can provide OpenStruct behavior to
# any class or object.
#
# require 'ostruct'
#
# record = Object.new
# record.extend OpenStructable
#
# record.name = "John Smith"
# record.age = 70
# record.pension = 300
#
# puts record.name # -> "John Smith"
# puts record.address # -> nil
#
module OpenStructable

# Duplicate an OpenStruct object members.
def initialize_copy(orig)
super
@__table__ = @__table__.dup
end

def new_ostruct_member(name)
self.instance_eval %{
def #{name}; @__table__[:#{name}]; end
def #{name}=(x); @__table__[:#{name}] = x; end
}
end

#
# Generate additional attributes and values.
#
def update(hash)
@__table__ ||= {}
if hash
for k,v in hash
@__table__[k.to_sym] = v
new_ostruct_member(k)
end
end
end

def method_missing(mid, *args) # :nodoc:
mname = mid.id2name
len = args.length
if mname =~ /=$/
if len != 1
raise ArgumentError, "wrong number of arguments (#{len} for 1)",
caller(1)
end
if self.frozen?
raise TypeError, "can't modify frozen #{self.class}", caller(1)
end
mname.chop!
@__table__ ||= {}
@__table__[mname.intern] = args[0]
self.new_ostruct_member(mname)
elsif len == 0
@__table__ ||= {}
@__table__[mid]
else
raise NoMethodError, "undefined method `#{mname}' for #{self}",
caller(1)
end
end

#
# Remove the named field from the object.
#
def delete_field(name)
@__table__ ||= {}
@__table__.delete name.to_sym
end

#
# Returns a string containing a detailed summary of the keys and values.
#
def inspect
str = "<#{self.class}"
for k,v in (@__table__ ||= {})
str << " #{k}=#{v.inspect}"
end
str << ">"
end

def __table__ # :nodoc:
@__table__ ||= {}
end
protected :__table__

#
# Compare this object and +other+ for equality.
#
def ==(other)
return false unless(other.kind_of?(OpenStruct))
return @__table__ == other.table
end
end

#
# OpenStruct allows you to create data objects and set arbitrary attributes.
# For example:
#
# require 'ostruct'
#
# record = OpenStruct.new
# record.name = "John Smith"
# record.age = 70
# record.pension = 300
#
# puts record.name # -> "John Smith"
# puts record.address # -> nil
#
# It is like a hash with a different way to access the data. In fact, it is
# implemented with a hash, and you can initialize it with one.
#
# hash = { "country" => "Australia", :population => 20_000_000 }
# data = OpenStruct.new(hash)
#
# p data # -> <OpenStruct country="Australia" population=20000000>
#
class OpenStruct
include OpenStructable

#
# Create a new OpenStruct object. The optional +hash+, if given, will
# generate attributes and values. For example.
#
# require 'ostruct'
# hash = { "country" => "Australia", :population => 20_000_000 }
# data = OpenStruct.new(hash)
#
# p data # -> <OpenStruct country="Australia" population=20000000>
#
# By default, the resulting OpenStruct object will have no attributes.
#
def initialize(hash=nil)
update(hash)
end
end
 
M

Mauricio Fernández

Yes, no, maybe?

--- Original Message ---

On Sunday 14 November 2004 06:16 pm, Yukihiro Matsumoto wrote:
| Can you be more specific, preferably with code example?
|
| matz.

Ah, what the hek! I pulled down 1.9 and modified. Below you will find code.
Let me know if you'd like me to send code as attachment via private mail.
[...]

While you are at it, please consider

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/3687

and the other msgs in that thread.
 
T

trans. (T. Onoma)

04 am, Mauricio Fernández wrote:
| | While you are at it, please consider
| |
| | http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/3687
| |
| | and the other msgs in that thread.
|
| Okay, thanks. So what constitutes compatible marshal data?

Off the top of my head, would this work?

def marshal_dump
Marshal.dump(@table)
end

def marshal_load(obj)
@table = Marshal.load(obj)
@table.each_key{|key| self.new_ostruct_member(key) }
end

T.
 
M

Mauricio Fernández

| | While you are at it, please consider
| |
| | http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/3687
| |
| | and the other msgs in that thread.
|
| Okay, thanks. So what constitutes compatible marshal data?

Off the top of my head, would this work?

def marshal_dump
Marshal.dump(@table)
end

def marshal_load(obj)
@table = Marshal.load(obj)
@table.each_key{|key| self.new_ostruct_member(key) }
end

It introduces an unneeded indirection level (you end up
marshalling a string with the marshalled table; compare to
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/3690) and
doesn't solve the data compatibility problem: I believe that the goal
is having

# run with the new code
File.open("data", "w"){|f| f.write Marshal.dump(OpenStruct.new:)a => 1))}

# run with the old code
p Marshal.load(File.read("data")) # we want => OpenStruct, not String or Hash

and vice versa.
 
F

Florian Gross

trans. (T. Onoma) said:
On Tuesday 16 November 2004 09:18 am, Florian Gross wrote:
| Why don't use globals (or a constant) or a Module with module functions
| instead? I don't understand how singletons are useful for pools however.
| Could you explain?

Well, with globals I can't control namespace. And modules have there one
issues --like what if I change my mind? And not being able to subclass.

It depends:

$colors::red # => "red"
$colors::blue # => "blue"
$colors::green # => "two colors ought to be enough for everyone"

where:

$colors = Module.new do; extend self
define_method("red") { "red" }
define_method("blue") { "blue" }
define_method("green"){"two colors ought to be enough for everyone"}
end

I'm pretty sure I could also come up with a syntax that makes it feel
more natural.
As for a constant, in a way that basically what one's doing. But the singleton
also prevents any other instance of that kind. Granted in many cases that
probably doesn't really matter. So sure I could probably just use a constant
and not worry about the potential abuses. Of course I could also never bother
to make a method private too. Maybe that's overstating it a bit, but the
point is, there are always multiple ways of doing things. Singleton Pattern
is just another tool, and if the shoe fits then where it. I don;t think we
should throw it out just b/c it's easy to abuse.

I guess your problem is that you are creating a class at all. Why don't
just assign a single Object to a constant and add methods to that single
object directly? (The def obj.method() end syntax makes this quite
convenient.)

I'm still interested in how to do resource pools using Singletons.
How about InfinityClass. Singletons can be immutable too.

I think they should only be allowed to be immutable or else they lead to
very tight coupling. But I still wonder why you need a class when all
you want is a single Object anyway.
| isn't "singleton class"
| the term that is most commonly used already?
Not substantially so. We've seen cases of the term virtual class. And I've
seen the term metaclass at least as often --especially in libs.

Still, I feel like "singleton class" is used more than the others. Maybe
you could grep #ruby-talk logs and compare the usage of the terms? (But
be sure to filter out the few occurrences of SingleInstanceClasses that
currently share the same name or the statistic will be slightly biased.)
The monotheistic doctrine of an OOP developer: God is Singleton.

Most gods want you to believe that so that they can get power
exclusively. Having just one god will make it difficult to replace it by
a mock god when testing your believes.
 
T

trans. (T. Onoma)

| > On Tuesday 16 November 2004 09:18 am, Florian Gross wrote:
| > | Why don't use globals (or a constant) or a Module with module functions
| > | instead? I don't understand how singletons are useful for pools
| > | however. Could you explain?
| >
| > Well, with globals I can't control namespace. And modules have there one
| > issues --like what if I change my mind? And not being able to subclass.
|
| It depends:
|
| $colors::red # => "red"
| $colors::blue # => "blue"
| $colors::green # => "two colors ought to be enough for everyone"
|
| where:
|
| $colors = Module.new do; extend self
| define_method("red") { "red" }
| define_method("blue") { "blue" }
| define_method("green"){"two colors ought to be enough for everyone"}
| end
|
| I'm pretty sure I could also come up with a syntax that makes it feel
| more natural.

Cute. Never thought of using globals in that manner before --but I guess one
might as well use a module in such case.

| > As for a constant, in a way that basically what one's doing. But the
| > singleton also prevents any other instance of that kind. Granted in many
| > cases that probably doesn't really matter. So sure I could probably just
| > use a constant and not worry about the potential abuses. Of course I
| > could also never bother to make a method private too. Maybe that's
| > overstating it a bit, but the point is, there are always multiple ways of
| > doing things. Singleton Pattern is just another tool, and if the shoe
| > fits then where it. I don;t think we should throw it out just b/c it's
| > easy to abuse.
|
| I guess your problem is that you are creating a class at all. Why don't
| just assign a single Object to a constant and add methods to that single
| object directly? (The def obj.method() end syntax makes this quite
| convenient.)

Sure. One could do that, but it lacks for straightforward instantiation and
can't be subclassed. Since it amount to the about same thing, it just seems
easier to create a Singleton.

| I'm still interested in how to do resource pools using Singletons.

class MyPool
include Singleton
def initialize
@pool = {}
end
def [](key)
@pool[key]
end
def []=(key, thing)
@pool[key] = thing
end
# ...
end

# else where ...

mp = MyPool.instance

| > How about InfinityClass. Singletons can be immutable too.
|
| I think they should only be allowed to be immutable or else they lead to
| very tight coupling. But I still wonder why you need a class when all
| you want is a single Object anyway.

Like I said, pretty much the same thing. But take the above:

class MySuperPool < MyPool
def add(key, thing)
raise "thing no good" unless thing.kind_of?(SuperThing)
@pool[key] = thing
end
end

Of course one could use a module and 'extend self' and so on, but again, why
go through the extras trouble?

| > | isn't "singleton class"
| > | the term that is most commonly used already?
| >
| > Not substantially so. We've seen cases of the term virtual class. And
| > I've seen the term metaclass at least as often --especially in libs.
|
| Still, I feel like "singleton class" is used more than the others. Maybe
| you could grep #ruby-talk logs and compare the usage of the terms? (But
| be sure to filter out the few occurrences of SingleInstanceClasses that
| currently share the same name or the statistic will be slightly biased.)

How to access those logs?

| > The monotheistic doctrine of an OOP developer: God is Singleton.
|
| Most gods want you to believe that so that they can get power
| exclusively. Having just one god will make it difficult to replace it by
| a mock god when testing your believes.

LOL :) Test God? That'll be some interesting code.

assert_divine(GodClass)

What kind of error message would you expect? A bolt of lightening? :)

T.
 
F

Florian Gross

trans. (T. Onoma) said:
| > As for a constant, in a way that basically what one's doing. But the
| > singleton also prevents any other instance of that kind. Granted in many
| > cases that probably doesn't really matter. So sure I could probably just
| > use a constant and not worry about the potential abuses. Of course I
| > could also never bother to make a method private too. Maybe that's
| > overstating it a bit, but the point is, there are always multiple ways of
| > doing things. Singleton Pattern is just another tool, and if the shoe
| > fits then where it. I don;t think we should throw it out just b/c it's
| > easy to abuse.
|
| I guess your problem is that you are creating a class at all. Why don't
| just assign a single Object to a constant and add methods to that single
| object directly? (The def obj.method() end syntax makes this quite
| convenient.)

Sure. One could do that, but it lacks for straightforward instantiation and
can't be subclassed. Since it amount to the about same thing, it just seems
easier to create a Singleton.

Subclassing is done by .dup()ing the Object and then adding new methods.
I still don't know why you need "instantiation" (don't we usually
instantiate with .new? -- Yet singleton.rb forces you to use .instance).
| I'm still interested in how to do resource pools using Singletons.

class MyPool
include Singleton
def initialize
@pool = {}
end
def [](key)
@pool[key]
end
def []=(key, thing)
@pool[key] = thing
end
# ...
end

I don't get why one needs "include Singleton" there -- it looks like it
would make perfect sense to be able to have multiple pools. Are you sure
you are not using a Singleton for making one single pool easily
reachable from anywhere in your application? There's better alternatives
for that.
| > How about InfinityClass. Singletons can be immutable too.
|
| I think they should only be allowed to be immutable or else they lead to
| very tight coupling. But I still wonder why you need a class when all
| you want is a single Object anyway.

Like I said, pretty much the same thing. But take the above:

class MySuperPool < MyPool
def add(key, thing)
raise "thing no good" unless thing.kind_of?(SuperThing)
@pool[key] = thing
end
end

Of course one could use a module and 'extend self' and so on, but again, why
go through the extras trouble?

Well, I'd rather use a Class in this context. Limiting the amount of
Pools to 1 seems a bit arbitrary.
| Still, I feel like "singleton class" is used more than the others. Maybe
| you could grep #ruby-talk logs and compare the usage of the terms? (But
| be sure to filter out the few occurrences of SingleInstanceClasses that
| currently share the same name or the statistic will be slightly biased.)

How to access those logs?

Hm, sorry, I can not find an official site that has them. But I could
package up my own local ones and mail them to you, if that is of help.
| > The monotheistic doctrine of an OOP developer: God is Singleton.
|
| Most gods want you to believe that so that they can get power
| exclusively. Having just one god will make it difficult to replace it by
| a mock god when testing your believes.

LOL :) Test God? That'll be some interesting code.

assert_divine(GodClass)

What kind of error message would you expect? A bolt of lightening? :)

Maybe a wide angle disintegration ray.
 
T

trans. (T. Onoma)

| > Sure. One could do that, but it lacks for straightforward instantiation
| > and can't be subclassed. Since it amount to the about same thing, it just
| > seems easier to create a Singleton.
|
| Subclassing is done by .dup()ing the Object and then adding new methods.
| I still don't know why you need "instantiation" (don't we usually
| instantiate with .new? -- Yet singleton.rb forces you to use .instance).

Give me a prototype-based OOPL, baby! Yes, I dislike using #instance usually,
and have changed it to #new before. If you do that an interesting consequence
arises --you can force all one's code to use the same instance irregardless.
(Although I don't know how useful that is in practice, but it's interesting
nonetheless.)

| I don't get why one needs "include Singleton" there -- it looks like it
| would make perfect sense to be able to have multiple pools. Are you sure
| you are not using a Singleton for making one single pool easily
| reachable from anywhere in your application? There's better alternatives
| for that.

| Well, I'd rather use a Class in this context. Limiting the amount of
| Pools to 1 seems a bit arbitrary.

Yes. You could Of course. The idea is that there should be one and one of
these pools. But perhaps that is unnecessarily enforced, and docs can specify
"USE THIS CONSTANT".

| > | Still, I feel like "singleton class" is used more than the others.
| > | Maybe you could grep #ruby-talk logs and compare the usage of the
| > | terms? (But be sure to filter out the few occurrences of
| > | SingleInstanceClasses that currently share the same name or the
| > | statistic will be slightly biased.)
| >
| > How to access those logs?
|
| Hm, sorry, I can not find an official site that has them. But I could
| package up my own local ones and mail them to you, if that is of help.

Getting back to the earlier notion. This is basically what I decided. In my
lib I created Object#special_class and aliased #singleton_class to it. In the
future I will refer to it as the "special singleton" or "singleton
special-class".

| > | > The monotheistic doctrine of an OOP developer: God is Singleton.
| > |
| > | Most gods want you to believe that so that they can get power
| > | exclusively. Having just one god will make it difficult to replace it
| > | by a mock god when testing your believes.
| >
| > LOL :) Test God? That'll be some interesting code.
| >
| > assert_divine(GodClass)
| >
| > What kind of error message would you expect? A bolt of lightening? :)
|
| Maybe a wide angle disintegration ray.

Oo.. that'll hurt! :)

Laters,
T.
 

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

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top