From: Albert Wagner Date: 2001-10-30T12:11:56+09:00 Subject: [ruby-talk:23797] Re: RCR: Fun with attribute shortcuts solves RCR #3 and more On Monday 29 October 2001 08:37 pm, you wrote: > On Tue, 30 Oct 2001, Albert Wagner wrote: > > Wow, keep this up and you can boil a whole application down into a single > > obtuse statement :-) > > Actually, I find such methods much less obtuse than the code they replace. > Although it's very easy to recognize an accessor method when you see one, > using attr_accessor makes the concept more explicit and more readable, > not less. Similarly, == methods impose a certain cognitive load when > reading them; I have to read the entire method to make sure it doesn't do > anything unusual. With attr_equality, I know that the implementation of > the method is the usual one. Macros and metaprogamming are not about > obfuscation - quite the opposite, in fact. The more you can bring > explicit design concepts and vocabulary into your code, the better. Sorry. I guess I needed more smiley faces. Still...how long would it take a newbie (or anyone as slow-witted as myself) to figure out what was happening here? After scouring the pickaxe for the construction I would plague the NG with yet another stupid question. There is a very thin line between flexibility and chaos. You gurus be careful. > > > On Monday 29 October 2001 04:45 pm, you wrote: > > > Hi everyone, remember this? > > > > > > >I'm constantly creating small classes, and many of them start > > > > something like: > > > > class Msg > > > > def initialize(name, type, txt) > > > > @name, @type, @txt = name, type, txt > > > > end > > > > # ... > > > > end > > > > > > Yeah, it's a classic, RCR #3. We all hate repetition and typing > > > stuff that is obvious, right? > > > > > > Last time it was Joe McDonald who said: > > > > and if you have a sec, vote on RCR #3. It's a pet peeve of mine. > > > > > > I think it's a pet peeve for a lot of us but I can see why > > > RCR #3 was rejected as it stands now. > > > What would it mean for example, if you created another > > > function in the same way, like def func(@instance_var) - > > > is @instance_var assigned also in that case? > > > If not, why should there be a special case for initialize? > > > > > > So instead I propose to extend on the much loved shortcut > > > methods that exist for accessors. > > > > > > I.e. attr_accessor :a, :b, :c creates getters and setters for > > > @a, @b and @c so why not: > > > > > > class Mine > > > attr_initializer :a, :b, :c > > > ... > > > end > > > > > > attr_initializer creates an initializer > > > for them: > > > > > > def initialize(a, b, c) > > > @a, @b, @c = a, b, c > > > end > > > > > > So there's the idea - I thought it was quite nice but > > > now comes the fun part. I love this - when you get a good idea, > > > often it's easy to implement in Ruby without touching any > > > interpreter or such! For example, if you didn't get this yet, > > > notice that "attr_accessor" and the like are described in docs as > > > being just plain methods, in the class Module! > > > > > > So in some spare time at RubyConf and OOPSLA I fooled around with this > > > and got really positive responses, for example at the BOF session > > > at OOPSLA. > > > Trying it out for real makes a much better impact. > > > Using the eval-family of functions and the open classes, for > > > example "Class" and "Module", you can do a lot of cool stuff > > > that looks a lot like extentions of the language syntax, so here > > > is my implementation of attr_initializer: > > > > > > # file: AttrInitializer > > > class Module > > > def attr_initializer(*attrs) > > > alist = plist = "" > > > attrs.each do |v| > > > alist += "@#{v}," # >> @var1,@var2,@var3, ... > > > plist += "#{v}," # >> var1,var2,var3, ... > > > end > > > alist.chop!; plist.chop! # Remove last comma > > > class_eval "def initialize(#{plist}); #{alist} = #{plist}; end" > > > end > > > end > > > > > > Since the Class class inherits from Module, now you can just > > > require this file and you are able to use the attr_initializer > > > shortcut in all classes. > > > > > > > > > OK, now let's keep it going. What else is common to define in many > > > classes? Well, the default definition of equality is that the > > > compared references must be refs to the same object. However, it is > > > more common to want to compare (part of) the inner state of objects > > > and if they are equal, then the two different objects should be > > > considered equal. > > > > > > So you end up often defining == in your classes, like this, right? > > > > > > class Mine > > > attr_accessor :foo, :bar, :moo > > > # @foo, @bar, and @moo are my > > > # important inner state > > > > > > def ==(obj) > > > @foo = obj.foo && > > > @bar = obj.bar && > > > @moo = obj.moo > > > end > > > end > > > > > > Nowadays I just do this: > > > > > > class Mine > > > attr_equality :foo, :moo, :bar > > > ... > > > end > > > > > > Another option is to leave out the names of objects to make > > > it even simpler. This requires the equality function to introspect > > > self and the compared object to find all their instance vars. > > > > > > class Mine > > > attr_equality > > > ... > > > end > > > > > > I won't post the implementation of attr_equality because it's > > > longish, to support also the second option but you get the > > > idea from the attr_initializer example. > > > > > > I'll make an RCR for this and we'll see if people like it. > > > If you want a full implementation of both shortcuts > > > with some tests to go with them Drop me an email directly. > > > Don't reply to the list by mistake... > > > (Yes, XP-enthusiasts, I wrote the tests first! Great isn't it? > > > Although I updated them to run with Lapidary later) > > > > > > Have fun > > > > > > /Gunnar > > > > > > --- > > > Gunnar Andersson > > > gand -at- acm.org > > > > > > > > > __________________________________________________ > > > Do You Yahoo!? > > > Make a great connection at Yahoo! Personals. > > > http://personals.yahoo.com