[#20675] RCR: non-bang equivalent to []= — Tobias Reif <tobiasreif@...>

Hi,

49 messages 2001/09/01
[#20774] Re: RCR: non-bang equivalent to []= — Tobias Reif <tobiasreif@...> 2001/09/03

I wrote:

[#20778] Re: RCR: non-bang equivalent to []= — Kevin Smith <kevinbsmith@...> 2001/09/03

--- Tobias Reif <tobiasreif@pinkjuice.com> wrote:

[#20715] oreilly buch von matz - website online — markus jais <info@...>

hi

43 messages 2001/09/02
[#20717] Re: OReilly Ruby book has snail on cover — ptkwt@...1.aracnet.com (Phil Tomson) 2001/09/02

Actually, thanks for posting it here. I was trying to search OReilly's

[#20922] Re: OReilly Ruby book has snail on cover — Paul Brannan <pbrannan@...> 2001/09/05

On Mon, 3 Sep 2001, Phil Tomson wrote:

[#20768] Minor cgi.rb question — "Hal E. Fulton" <hal9000@...>

I don't have much experience with

25 messages 2001/09/03

[#20770] Calling member methods from C++ — jglueck@... (Bernhard Glk)

Some quetsions have been solved for me, but my message system does not

12 messages 2001/09/03

[#20976] destructor — Frank Sonnemans <ruby@...>

Does Ruby have a destructor as in C++?

25 messages 2001/09/07

[#21218] Ruby objects <-> XML: anyone working on this? — senderista@... (Tobin Baker)

Are there any Ruby analogs of these two Python modules (xml_pickle,

13 messages 2001/09/15

[#21296] nested require files need path internally — Bob Gustafson <bobgus@...>

Version: 1.64

29 messages 2001/09/18
[#21298] Re: nested require files need path internally — David Alan Black <dblack@...> 2001/09/18

Hello --

[#21302] Re: nested require files need path internally — Bob Gustafson <bobgus@...> 2001/09/18

On Tue, 18 Sep 2001, David Alan Black wrote:

[#21303] Re: nested require files need path internally — matz@... (Yukihiro Matsumoto) 2001/09/18

Hi,

[#21306] Re: nested require files need path internally — Lars Christensen <larsch@...> 2001/09/18

On Tue, 18 Sep 2001, Yukihiro Matsumoto wrote:

[#21307] Re: nested require files need path internally — matz@... (Yukihiro Matsumoto) 2001/09/18

Hi,

[#21331] Re: nested require files need path internally — Paul Brannan <pbrannan@...> 2001/09/18

> The big difference is C++ search done in compile time, Ruby search

[#21340] Re: nested require files need path internally — matz@... (Yukihiro Matsumoto) 2001/09/18

Hi,

[#21353] Re: nested require files need path internally — Paul Brannan <pbrannan@...> 2001/09/18

On Wed, 19 Sep 2001, Yukihiro Matsumoto wrote:

[#21366] Re: nested require files need path internally — matz@... (Yukihiro Matsumoto) 2001/09/19

Hi,

[#21368] Re: nested require files need path internally — "Julian Fitzell" <julian-ml@...4.com> 2001/09/19

On 19/09/2001 at 10:12 AM matz@ruby-lang.org wrote:

[#21376] Re: nested require files need path internally — matz@... (Yukihiro Matsumoto) 2001/09/19

Hi,

[#21406] Re: nested require files need path internally — Paul Brannan <pbrannan@...> 2001/09/19

On Wed, 19 Sep 2001, Yukihiro Matsumoto wrote:

[#21315] Suggestions for new CGI lib — anders@... (Anders Johannsen)

From the comp.lang.ruby thread "Minor cgi.rb question" (2001-09-03), I

21 messages 2001/09/18

[#21413] Ruby/objects book in style of The Little Lisper — Brian Marick <marick@...>

I fell in love with Lisp in the early 80's. Back then, I read a book called

36 messages 2001/09/19
[#21420] Re: Ruby/objects book in style of The Little Lisper — Christopher Sawtell <csawtell@...> 2001/09/20

On 20 Sep 2001 06:19:44 +0900, Brian Marick wrote:

[#21479] Re: Ruby/objects book in style of The Little Lisper — Kevin Smith <kevinbsmith@...> 2001/09/21

--- Christopher Sawtell <csawtell@paradise.net.nz> wrote:

[#21491] SV: Re: Ruby/objects book in style of The Little Lisper — "Mikkel Damsgaard" <mikkel_damsgaard@...> 2001/09/21

[#21494] Re: SV: Re: Ruby/objects book in style of The Little Lisper — Kevin Smith <kevinbsmith@...> 2001/09/21

--- Mikkel Damsgaard <mikkel_damsgaard@mailme.dk> wrote:

[#21510] Re: SV: Re: Ruby/objects book in style of The Little Lisper — Todd Gillespie <toddg@...> 2001/09/22

On Sat, 22 Sep 2001, Kevin Smith wrote:

[#21514] Re: SV: Re: Ruby/objects book in style of The Little Lisper — Kevin Smith <kevinbsmith@...> 2001/09/22

--- Todd Gillespie <toddg@mail.ma.utexas.edu> wrote:

[#21535] irb — Fabio <fabio.spelta@...>

Hello. :) I'm new here, and I have not found an archive of the previous

15 messages 2001/09/22

[#21616] opening a named pipe? — "Avdi B. Grimm" <avdi@...>

I'm having trouble reading from a named pipe in linux. basicly, I'm

12 messages 2001/09/24

[#21685] manipulating "immutable" objects such as Fixnum from within callbacks & al... — Guillaume Cottenceau <gc@...>

Hello,

15 messages 2001/09/25

[#21798] Ruby internal (guide to the source) — "Benoit Cerrina" <benoit.cerrina@...>

Hi,

22 messages 2001/09/28

[ruby-talk:20948] Re: pop code review

From: Brian Marick <marick@...>
Date: 2001-09-06 03:21:36 UTC
List: ruby-talk #20948
At 02:27 PM 9/5/01, you wrote:
>class Module
>     def attr_default(symbol, default)
>         default = "'#{default}'" if default.type == String
>         module_eval "def #{symbol}() if @#{symbol}.nil?; #{default}; else
>@#{symbol}; end; end"
>     end
>
>     def attr_filter(symbol, *filters)
>         filtered_setter = "def #{symbol}=(value) "
>         filters.each { |f|
>             filtered_setter += " value=#{f}(value);"
>         }
>         filtered_setter += " @#{symbol}=value; end"
>         module_eval filtered_setter
>     end
>end

Thanks very much for posting this. I was really in the mood for
tinkering with code, and this was just the thing I needed. A crummy
day has ended as a fun one.

I've made a series of changes that I hope are useful. Warning: they
haven't been tested well.

First, I noticed a problem. The code doesn't work with arrays as the
default:

class Cat
   attr_default :lives, [1, 2, 3, 4, 5, 6, 7, 8, 9]
end

 > Cat.new.lives
123456789

The problem is #{default} here:

         module_eval "def #{symbol}() if @#{symbol}.nil?; #{default}; else 
@#{symbol}; end; end"

#{default.inspect} would work for Arrays (and Strings, as well,
eliminating the need for the String test in the line above).

But 'inspect' isn't quite the thing, since its contract is to produce
a human-readable form. What we want is a method that produces a string
which, when evaled, produces a copy of the original object. I'm going
to call that "to_e". For a lot of things, to_e can be the same as
inspect. For convenience, I'll stick it on Object:

class Object
   def to_e() inspect; end
end

But for my own classes, it can be defined differently than inspect:

class Cat
   def initialize(name) @name = name; end

   def inspect() "<The cat named '#{@name}'>"; end

   def to_e() "Cat.new(#{@name.to_e})"; end
end

Now I can define attr_default like this:

class Module
     def attr_default(symbol, default)
         module_eval "def #{symbol}() if @#{symbol}.nil?; #{default.to_e}; else
@#{symbol}; end; end"
     end
end

So now I can initialize Cat with lives:

class Cat
   attr_default :lives, [1, 2, 3, 4, 5, 6, 7, 8, 9]
end

 > Buffy = Cat.new("buffy")
<The cat named 'buffy'>
 > Buffy.lives
[1, 2, 3, 4, 5, 6, 7, 8, 9]

Moreover, Cats can be the default values for attributes of other
classes:

class Dog
   attr_default :friend, Buffy
end

(Buffy is a constant so that it's in scope for the class definition.)

 > Dog.new.friend
<The cat named 'buffy'>

But this raises a question: how can I have all Dogs share the same
friend? Because right now they don't:

 > towser = Dog.new
#<Dog:0xa0ab860>
 > ralph = Dog.new
#<Dog:0xa09d790>
 > towser.friend
<The cat named 'buffy'>
 > ralph.friend
<The cat named 'buffy'>
 > towser.friend == ralph.friend
false

I decided to store the defaults in the class. Along the way, I also
decided to change something that bugged me a bit about the original:
that you couldn't set the created variables to nil:

class Var
   attr_default :val, true

   def val=(val)
     @val = val
   end
end

 > v = Var.new
#<Var:0xa092480>
 > v.val
true
 > v.val=nil
nil
 > v.val         # expect nil
true

I can fix this by initially setting the instance variable to the
default *unless* it already exists. If it already exists, it's already
been explicitly assigned to. Instance variables don't exist until the
first assignment. Here's the code. I also added a setter method.

class Module
   attr_accessor :attribute_defaults

   def attr_default(symbol, default)
     @attribute_defaults ||= Hash.new
     @attribute_defaults[symbol] = default

     getter = %Q{
       def #{symbol}()
         unless instance_variables.include? '@#{symbol}'
           @#{symbol} = self.class.attribute_defaults[:#{symbol}]
         end
         @#{symbol}
       end
     }
     puts getter
     module_eval getter

     setter = %Q{
       def #{symbol}=(val)
         @#{symbol}=val
       end
     }
     puts setter
     module_eval setter
   end
end

Both the Var and Dog examples work as I'd prefer. (Note: for some
reason I haven't tried to figure out, pasting the above into irb
causes parse errors, but loading it from a file does not.)

Finally, I thought that it would be better to use the existing name
attr_accessor, passing in the defaults as keyword arguments, like
this:

attr_accessor :ordinary, ordinary2, :defaulted=>5, :other=>9

I suspect there's a better way to do this, but the kids have come home
from skating and my hacking time is through for tonight:

class Module
   alias_method :old_attr_accessor, :attr_accessor

   attr_accessor :attribute_defaults

   def attr_accessor(*accessors)
     accessors.each { | e |
       if e.type == Hash
         e.each { | key, value |
           install_default_accessor(key, value)
         }
       else
         old_attr_accessor e
       end
     }
   end

   def install_default_accessor(symbol, default)
     @attribute_defaults ||= Hash.new
     @attribute_defaults[symbol] = default

     getter = %Q{
       def #{symbol}()
         unless instance_variables.include? '@#{symbol}'
           @#{symbol} = self.class.attribute_defaults[:#{symbol}]
         end
         @#{symbol}
       end
     }
     puts getter
     module_eval getter

     setter = %Q{
       def #{symbol}=(val)
         @#{symbol}=val
       end
     }
     puts setter
     module_eval setter
   end
end

class Multi
   attr_accessor :ordinary, :ordinary2, :defaulted=>5, :other=>9
end


 > m = Multi.new
#<Multi:0xa0ac2b0>
 > m.ordinary
nil
 > m.ordinary2
nil
 > m.defaulted
5
 > m.other
9


--
Brian Marick, marick@testing.com
www.testing.com - Software testing services and resources
www.testingcraft.com - Where software testers exchange techniques
www.visibleworkings.com - Adequate understanding of system internals

In This Thread

Prev Next