[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

An idiom I like... modifiable defaults

Hal E. Fulton

5/9/2005 2:43:00 PM

Just thought I'd share a little concept that I find
useful. Your comments are welcome.

Sometimes objects are created with certain defaults.
One way to override them is with default values in
the constructor (and often corresponding writer methods).

But sometimes I "don't like" the default and want to
change it (for this program/session).

Often I use class-level accessors for that purpose.

Here's a contrived example...


Cheers,
Hal


class Text

class << self
attr_accessor :color
Text.color = "black"
end

attr_accessor :color

def initialize(txt, color="black")
# Hint: You can improve this further by saying
# def initialize(txt, color=Text.color)
puts "#{color} text..."
end
end


# The old way...

a = Text.new("some") # black
b = Text.new("random","blue") # blue
c = Text.new("text") # black
c.color = "blue" # but now it's blue

# The new way...

Text.color = "blue"

e = Text.new("Ruby is cool") # blue
f = Text.new("as dry ice") # blue




10 Answers

Robert Klemme

5/9/2005 3:31:00 PM

0

Hal Fulton wrote:
> Just thought I'd share a little concept that I find
> useful. Your comments are welcome.
>
> Sometimes objects are created with certain defaults.
> One way to override them is with default values in
> the constructor (and often corresponding writer methods).
>
> But sometimes I "don't like" the default and want to
> change it (for this program/session).
>
> Often I use class-level accessors for that purpose.
>
> Here's a contrived example...
>
>
> Cheers,
> Hal
>
>
> class Text
>
> class << self
> attr_accessor :color
> Text.color = "black"
> end
>
> attr_accessor :color
>
> def initialize(txt, color="black")
> # Hint: You can improve this further by saying
> # def initialize(txt, color=Text.color)
> puts "#{color} text..."
> end
> end
>
>
> # The old way...
>
> a = Text.new("some") # black
> b = Text.new("random","blue") # blue
> c = Text.new("text") # black
> c.color = "blue" # but now it's blue
>
> # The new way...
>
> Text.color = "blue"
>
> e = Text.new("Ruby is cool") # blue
> f = Text.new("as dry ice") # blue

Thinking in code - some other approach:

def hash_replace(hash, replacement)
tmp = hash.dup

begin
hash.update replacement
return yield
ensure
hash.clear
hash.update tmp
end
end


>> class Test
>> DEFAULTS = {:foo => "bar", 1 => 2}
>> end
=> {1=>2, :foo=>"bar"}
>> p Test::DEFAULTS
{1=>2, :foo=>"bar"}
=> nil
>> hash_replace( Test::DEFAULTS, {:foo => "replaced"} ) do
?> p Test::DEFAULTS
>> end
{1=>2, :foo=>"replaced"}
=> nil
>> p Test::DEFAULTS
{1=>2, :foo=>"bar"}
=> nil

Hm...

Kind regards

robert


Ilmari Heikkinen

5/9/2005 3:44:00 PM

0


On 9.5.2005, at 17:42, Hal Fulton wrote:

> Just thought I'd share a little concept that I find
> useful. Your comments are welcome.
>
> Sometimes objects are created with certain defaults.
> One way to override them is with default values in
> the constructor (and often corresponding writer methods).
>
> But sometimes I "don't like" the default and want to
> change it (for this program/session).
>
> Often I use class-level accessors for that purpose.
>
> Here's a contrived example...
>
>
> Cheers,
> Hal
>

Hi,
I quite like this, but wonder if it works with inheritance?

On a related note, it seems a lot of people (you, me, Ara Howard,
probably many others) are coming up with these configuration idioms,
maybe we could find a way that fulfills most needs (and perhaps even
try to get it into ruby core)?

Here's a quick list of features for discussion, feel free to add your
own:
- named arguments (ie. hash argument way)
- auto-assigning configuration vars to instance variables
- works with inheritance (this is probably the most difficult -- and
useful -- one)
- auto-generated accessors
- configuration by block
- maybe some way to co-operate with the regular positional params


Would look something like this in use:

class Image
include TheAutoConfigModule
config_accessor{
name # defaults to nil
width = 100
height = 100
depth = 32
}
def bytes
@width * @height * @depth / 8
end
end

class BWImage < Image
config_accessor{ depth = 8 }
end

i = Image.new(:height => 200, :depth => 16)
i.width == 100 and i.height == 200 and i.depth == 16
#=> true
i.name
#=> nil
i.bytes
#=> 40000

bwi = BWImage.new( 'holiday shots', 10, 10 )
bwi.width == 10 and bwi.height == 10 and bwi.depth == 8
#=> true
bwi.name
#=> 'holiday shots'
bwi.bytes
#=> 100

Image.config
#=> {:name => nil, :width => 100, :height => 100, :depth => 32}

BWImage.config.height = 200
BWImage.config
#=> {:name => nil, :width => 100, :height => 200, :depth => 8}

Thoughts?


Cheers,
Ilmari

>
> class Text
>
> class << self
> attr_accessor :color
> Text.color = "black"
> end
>
> attr_accessor :color
>
> def initialize(txt, color="black")
> # Hint: You can improve this further by saying
> # def initialize(txt, color=Text.color)
> puts "#{color} text..."
> end
> end
>
>
> # The old way...
>
> a = Text.new("some") # black
> b = Text.new("random","blue") # blue
> c = Text.new("text") # black
> c.color = "blue" # but now it's blue
>
> # The new way...
>
> Text.color = "blue"
>
> e = Text.new("Ruby is cool") # blue
> f = Text.new("as dry ice") # blue
>



Ara.T.Howard

5/9/2005 5:29:00 PM

0

Glenn Parker

5/9/2005 6:33:00 PM

0

Hal Fulton wrote:
>
> Sometimes objects are created with certain defaults.
> One way to override them is with default values in
> the constructor (and often corresponding writer methods).
>
> But sometimes I "don't like" the default and want to
> change it (for this program/session).
>
> Often I use class-level accessors for that purpose.

Not very thread-safe, at least not in your example's implementation.

--
Glenn Parker | glenn.parker-AT-comcast.net | <http://www.tetrafoi...


Ara.T.Howard

5/9/2005 8:08:00 PM

0

Glenn Parker

5/9/2005 9:39:00 PM

0

Ara.T.Howard@noaa.gov wrote:
> On Tue, 10 May 2005, Glenn Parker wrote:
>>
>> Not very thread-safe, at least not in your example's implementation.
>
> even this is not:
>
> class C
> attr_accessor :x
> end

Yes, if instances of class C are to be accessed from multiple threads,
then some extra care is needed, but that depends very much on the actual
uses of the class. A lot of classes never need to worry about it, even
in highly threaded applications.

In the OP's code, it's clear that all threads using class Text will be
in contention for Text.color. In that style of interface, a per-thread
variable is practically mandatory.

--
Glenn Parker | glenn.parker-AT-comcast.net | <http://www.tetrafoi...


Hal E. Fulton

5/9/2005 10:56:00 PM

0

Glenn Parker wrote:
> Hal Fulton wrote:
>
>>
>> Sometimes objects are created with certain defaults.
>> One way to override them is with default values in
>> the constructor (and often corresponding writer methods).
>>
>> But sometimes I "don't like" the default and want to
>> change it (for this program/session).
>>
>> Often I use class-level accessors for that purpose.
>
>
> Not very thread-safe, at least not in your example's implementation.
>

No. I suppose if I were using this with threads I would
wrap the thread-safety code around it rather than hiding
it inside.


Hal




Martin DeMello

5/10/2005 4:50:00 AM

0

Ilmari Heikkinen <kig@misfiring.net> wrote:
> I quite like this, but wonder if it works with inheritance?

This is actually my primary use case for class variables (@@var) -
inheriting configuration defaults down a class tree.

martin

Ilmari Heikkinen

5/10/2005 5:27:00 AM

0


On 10.5.2005, at 07:54, Martin DeMello wrote:

> Ilmari Heikkinen <kig@misfiring.net> wrote:
>> I quite like this, but wonder if it works with inheritance?
>
> This is actually my primary use case for class variables (@@var) -
> inheriting configuration defaults down a class tree.
>
> martin
>

The problem with class vars is that changing them in the subclass
affects the superclass aswell.

class A
@@foo = "A"
def foo; @@foo; end
end

class B < A
@@foo = "B"
end

A.new.foo
=> "B"



Martin DeMello

5/10/2005 5:41:00 AM

0

Ilmari Heikkinen <kig@misfiring.net> wrote:
> On 10.5.2005, at 07:54, Martin DeMello wrote:
> >
> > This is actually my primary use case for class variables (@@var) -
> > inheriting configuration defaults down a class tree.
>
> The problem with class vars is that changing them in the subclass
> affects the superclass aswell.

Yes, but you're the programmer - simply don't change them in the
subclass.

martin