Attr

In the upcoming release of Ruby Carats I have a little lib called
attr.rb.

What it does is define a mater #define_attribute which all attribute
defintions are routed thru. Then I redefine #attr (since current
definition is basically never used) to call #define_attribute that
takes multiple args. Here's an example:

.. attr :a, :a=

which is equivalent to:

.. attr_reader :a
.. attr_writer :a

It also has some extra freatures that are nice like:

.. attr :a?, :b!

which is the same as

.. def a?
.. @a ? true : @a
.. end
..
.. def b!(x)
.. @b.replace x
.. end

Also these return an array of the symbols of the methods that get
defined, so you can use public, private, protected on them. eg.

.. private attr :a

There are a couple of other features too, but I'll leave those aside
for now, as they are not important to this inquery.

So I have a few questions. First, what do you think of this in general?
Second, there is no "extra" convenient way to do an accessor b/c I
haven't been able to find a nice notation --one just has to put both,
'attr :a, :a='. Is this too inconvenient? Can anyone think of a good
notation?

Thanks,
T.

In the upcoming release of Ruby Carats I have a little lib called
attr.rb.

What it does is define a mater #define_attribute which all attribute
defintions are routed thru. Then I redefine #attr (since current
definition is basically never used) to call #define_attribute that

Well.... claiming that it is "basically never used" is dangerous. I've
used it, and I know I've seen code that uses it. Changing the
semantics of an existing method is always going to be dangerous, no
matter how infrequently you believe the method is used in practice.

Caution, caution, caution. :slight_smile:

So I have a few questions. First, what do you think of this in general?
Second, there is no "extra" convenient way to do an accessor b/c I
haven't been able to find a nice notation --one just has to put both,
'attr :a, :a='. Is this too inconvenient? Can anyone think of a good
notation?

I like the features you've added, though. Could you perhaps call it
something other than "attr", to avoid breakage?

- Jamis

···

On 22:51 Mon 24 Jan , Trans wrote:

--
Jamis Buck
jamis_buck@byu.edu
http://jamis.jamisbuck.org
------------------------------
"I am Victor of Borge. You will be assimil-nine-ed."

"Trans" <transfire@gmail.com> schrieb im Newsbeitrag
news:1106574588.198173.83840@f14g2000cwb.googlegroups.com...

In the upcoming release of Ruby Carats I have a little lib called
attr.rb.

What it does is define a mater #define_attribute which all attribute
defintions are routed thru. Then I redefine #attr (since current
definition is basically never used) to call #define_attribute that
takes multiple args. Here's an example:

. attr :a, :a=

which is equivalent to:

. attr_reader :a
. attr_writer :a

It also has some extra freatures that are nice like:

. attr :a?, :b!

which is the same as

. def a?
. @a ? true : @a
. end

Why not "def a?() @a end"?

. def b!(x)
. @b.replace x
. end

Hm, I don't like that because it's too special case. Also you might want
to be able to assign and to replace...

Also these return an array of the symbols of the methods that get
defined, so you can use public, private, protected on them. eg.

. private attr :a

There are a couple of other features too, but I'll leave those aside
for now, as they are not important to this inquery.

So I have a few questions. First, what do you think of this in general?
Second, there is no "extra" convenient way to do an accessor b/c I
haven't been able to find a nice notation --one just has to put both,
'attr :a, :a='. Is this too inconvenient? Can anyone think of a good
notation?

Although I find "attr_accessor" quite lengthy, I don't really see the
benefit of your proposal. And attr_accessor does indeed define reader and
writer for several attributes...

Kind regards

    robert

Trans wrote:

So I have a few questions. First, what do you think of this in general?

Clever stuff for golfing, and possibly useful as a way to illustrate the meta-programming flexibility of Ruby, but it adds nothing meaningful while moderately obfuscating some simple tasks. You've come up with a way to compress two or three lines of trivially understood Ruby down to one line of obscure Ruby. To me, the original two or three "verbose" lines are preferable because they are more easily recognized and understood by a Ruby coder.

···

--
Glenn Parker | glenn.parker-AT-comcast.net | <http://www.tetrafoil.com/&gt;

Trans wrote:

In the upcoming release of Ruby Carats I have a little lib called
attr.rb.

. attr :a, :a=
. attr :a?, :b!

Quite nifty, all that. I don't quite understand the people who think it is obscure or who think it clutters the built-in methods.

This is a nice extension. While I would not use attr :a, :a= over attr_accessor :a (the latter has already become a convention) I could see myself using this because of the attr :a?, :a= and attr :x => :to_s functionality.

What I don't quite understand is why you're not remaining compatible with the original attr(). After all you would just have to check if you have two arguments of which the second is either false or true. (While this would still be slightly incompatible in the attr :foo, "I like to use Strings for true" case I'm pretty sure you can safely ignore it. Maybe a note ought to go into the documentation, but I can't see this causing trouble.)

Oh, and I think that the :x! feature is quite useless. This is an extremely rare special case and I think it's more obvious if written out. Or did you find lots of use cases for it?

Perhaps you could also allow it to take a block that would be instance_eval()uated in the method at the beginning. That could be used for introducing checks, converting values and so on. It would not provide much above writing the method out, but it could still make sense.

I like the features you've added, though.
Could you perhaps call it something other than
"attr", to avoid breakage?

I suppose, but first let me explain. It used to be called #def_attr for
the reason you state. But I always felt like I might as well use #attr
due to its _relative_ uselessness (i.e. overlap functionality with much
more commonly used methods). So I posted a topic here on this list
(110245) that asked about it, and the jist seemed to be that it was
pretty much abandoned. Also, keep in mind that programs using the old
#attr won't be effected unless they become a part of something that
requires this lib --and hell, the current definition of #attr almost
seems like a bug anyway; maybe poeple be happy to finally root them
out. Further, it is backward compatible with reader notation; just not
the accessor notation (i.e. 'attr :a, true').

Oh I forgot a question too. Sould 'attr :a=' create just a writer, like
I have it, or should it instead create a reader and a writer, since
writers are very uncommon? (Though in that case I don't know what
notation to use for just writer.)

-T.

. def a?
. @a ? true : @a
. end

Why not "def a?() @a end"?

Becasue that would be the exact same as 'attr :a'. What would be the
point? This guaruntees only three possible return values: true, false,
and nil.

. def b!(x)
. @b.replace x
. end

Hm, I don't like that because it's too special case.

Well, these _are_ special cases. Don't see any reason not to like them
b/c of that. Just dont use them. Since the "functional space" is simply
going unused anyway (i.e. symbols can end in ? and ! without quoting),
and it coorepsonds to certain forms of method definitions, I gave them
the most reasonble base-line usage I could think of.

Also you might want to be able to assign and to replace...

I think you'd just replace first from the calling routine, and then
assign. Or perhaps I misunderstand?

Although I find "attr_accessor" quite lengthy, I don't
really see the benefit of your proposal. And attr_accessor
does indeed define reader and writer for several attributes

Ah, but there are many advantages, not just the fact that attr is
shorter. You can define both readers and writers in the same call. The
names of the methods defined are returned so you can use public,
private, protected (and user defined methods too!) in front of them.
They also route through a common #define_attribute method, so there is
central control, and it stores all defined attribute methods so you can
ask for a list of them. It also has casting, somthing I came up with a
few years ago. Eg.
.. attr :a => :to_s

which defines

.. def a
.. @a.to_s
.. end

~T.

You know, this is commonly called "aspect oriented programming" if I am not mistaken. You may want to look into it. I didn't find this paradigm very easy to think in, but there are people out there who swear by it, so maybe you should head in that direction and name the library accordingly.

I did a quick google search for aspect oriented programming ruby and found some stuff out there that's already done. (http://aspectr.sf.net/\)

-Jeff

···

In the upcoming release of Ruby Carats I have a little lib called
attr.rb.

What it does is define a mater #define_attribute which all attribute
defintions are routed thru. Then I redefine #attr (since current
definition is basically never used) to call #define_attribute that

Well.... claiming that it is "basically never used" is dangerous. I've
used it, and I know I've seen code that uses it. Changing the
semantics of an existing method is always going to be dangerous, no
matter how infrequently you believe the method is used in practice.

Caution, caution, caution. :slight_smile:

So I have a few questions. First, what do you think of this in general?
Second, there is no "extra" convenient way to do an accessor b/c I
haven't been able to find a nice notation --one just has to put both,
'attr :a, :a='. Is this too inconvenient? Can anyone think of a good
notation?

I like the features you've added, though. Could you perhaps call it
something other than "attr", to avoid breakage?

- Jamis

--
Jamis Buck
jamis_buck@byu.edu
http://jamis.jamisbuck.org
------------------------------
"I am Victor of Borge. You will be assimil-nine-ed."

Thanks Glenn,

But do you really find something like:

attr :a, :a=, :c?

so obfuscating? Every thing has some learning curve to it. I grant you.
But my bet is that this notation would be almost completely undestood
on one's first hunch.

T.

I fully agree, unless you have access to all the source code ever
written in Ruby it is pretty hard to say that is never used. Of
course, it is very easy to say something such as "I never use it".
But, then how do we know if other people are using certain methods and
syntax? I was pretty shocked to see lots of usage of the for statement
in some of the source code included in the standard Ruby libraries.
Why would anyone use for when the each method exists, especially those
who have committed to the Ruby base? Ignore that last question it is
only to highlight how I thought most Ruby experts would not use the
for statement.

Assuming we have access to lots of source we could run a few
searches of various method/syntax usage and tally up the results.
Luckily, Satoru Takabayashi, is writing a nice tool called "gonzui" to
help speed up searching your source. I installed it this weekend and
did a bit of playing around with it. Though it is a bit rough around
the edges, it shows a lot of potential and is pretty useful now.
Certainly faster than grep once you build the indexes.

Check it out:
http://namazu.org/~satoru/gonzui/

Cheers,
Zev

···

On Mon, 24 Jan 2005 23:12:17 +0900, Jamis Buck <jamis_buck@byu.edu> wrote:

On 22:51 Mon 24 Jan , Trans wrote:

What it does is define a mater #define_attribute which all attribute
defintions are routed thru. Then I redefine #attr (since current
definition is basically never used) to call #define_attribute that

Well.... claiming that it is "basically never used" is dangerous. I've
used it, and I know I've seen code that uses it. Changing the
semantics of an existing method is always going to be dangerous, no
matter how infrequently you believe the method is used in practice.

Caution, caution, caution. :slight_smile:

Thanks for the support Florian.

What I don't quite understand is why you're not
remaining compatible with the original attr().

An excellent point! All things being equal, I will do exactly that.
Thanks!

Oh, and I think that the :x! feature is quite useless. This is
an extremely rare special case and I think it's more obvious
if written out. Or did you find lots of use cases for it?

No. The only thing that comes to mind is in combination with a casting.
Somthing like:

attr :a! => :upcase

which creates

def a!(x)
   @a.replace(x.upcase)
end

Better, but still doesn't seem all that useful really --as has been
pointed out. I've though about using the ! to build a reader and
writer, but that doesn't fit the profile. ! has a general meaning of
effecting the object in a special internal way.

There is also another form which I thought might be nice to have, a
getter/setter: If an argument is given it acts as a setter, if not it
acts as a getter. But I have no simple notion to use for it. At the
moment it can be done like this:

attr :"a()"

But I'm not too sure about it.

Perhaps you could also allow it to take a block that would
be instance_eval()uated in the method at the beginning.

I've thought about that. In fact I think I had that in there at one
point. But like you say it seemed like you'd might as well be writting
the method out at that point. But maybe there's merit to it for other
reasons --sometimes I wish def itself took a block form, eg.

def a { #... }

T.

Update:

I've now fixed #attr to be backward compatible. The only caveat being
that one mustuse true (or false or nil) for it to work. ie.

attr :a, "as if it were true"

will not work. But as Florian pointed out, this is fairly
insignificant.

The feature BTW is a bit extended. It can now take more than one
attribute as follows:

attr :a, :b, :c, true

And all three will get writers too.

One last thing, it doesn't just create writers but the
"contra-positive" of the attributes you can give it. In other words:

attr :a=, true

Will also create a reader. And

attr :a?, true

Will get a writer (#a=).

Note that casting can not be used with this notation. So

attr :a => :to_s, true

Will not work. This is b/c casted attributes must always be at then end
of the argument list (it's a hash after all).

Oh, one last thing. All the "attr_*" methods are still there but now
they accept casting and I've added #attr_tester (for #a? methods)

Hope you like. It will be available when I release Carats in a month or
two. (Sooner if I can find a helping hand.)

T.

I personally always define them as:
def a?
  !!@a
end

to ensure a boolean value is returned.

···

On Jan 24, 2005, at 9:25 AM, Robert Klemme wrote:

. def a?
. @a ? true : @a
. end

Why not "def a?() @a end"?

"Trans" <transfire@gmail.com> schrieb im Newsbeitrag news:1106585454.733119.216360@z14g2000cwz.googlegroups.com...

. def a?
. @a ? true : @a
. end

Why not "def a?() @a end"?

Becasue that would be the exact same as 'attr :a'. What would be the
point? This guaruntees only three possible return values: true, false,
and nil.

So you want to protect the real value. Is that the reasoning behind this?

. def b!(x)
. @b.replace x
. end

Hm, I don't like that because it's too special case.

Well, these _are_ special cases. Don't see any reason not to like them
b/c of that. Just dont use them. Since the "functional space" is simply
going unused anyway (i.e. symbols can end in ? and ! without quoting),
and it coorepsonds to certain forms of method definitions, I gave them
the most reasonble base-line usage I could think of.

Still you introduce a method in class Module that has some special behavior which at least clutters namespace - even if unused. As Module is a very basic class it's behavior should be most general, too - my 0.02 EUR. (You can always define an add on that adds these methods.)

Also you might want to be able to assign and to replace...

I think you'd just replace first from the calling routine, and then
assign. Or perhaps I misunderstand?

I meant that with only the replace version of the method there is no option to assign to the member var. But with the getter you can already replace. Of course, a.c! "foo" is shorter than a.c.replace "foo" - but then again, it's a special case as it applies only to String (or at least mostly). :slight_smile:

Although I find "attr_accessor" quite lengthy, I don't
really see the benefit of your proposal. And attr_accessor
does indeed define reader and writer for several attributes

Ah, but there are many advantages, not just the fact that attr is
shorter. You can define both readers and writers in the same call.

I can do that with attr_accessor.

The
names of the methods defined are returned so you can use public,
private, protected (and user defined methods too!) in front of them.

This works only if the method returns a single symbol. Otherwise it's going to be ugly:

class Module
  def a(*x) :single end
  def b(*x) [:a,:b] end
end

class Foo
  def single; end
  def a;end
  def b;end

  private a :a, :b
  private b :c, :d # doesn't work
  private *b :c, :d # doesn't work
  private *b( :c, :d) # ugly
end

They also route through a common #define_attribute method, so there is
central control, and it stores all defined attribute methods so you can
ask for a list of them. It also has casting, somthing I came up with a
few years ago. Eg.
. attr :a => :to_s

which defines

. def a
. @a.to_s
. end

Interesting.

I'm sorry that I don't share your enthusiasm - I simply don't miss this functionality.

Regards

    robert

Hi Jeffery,

I wouldn't exaclty call it AOP, although I can understand some analogy
here.

If you'd like to see some extensive work on the subject of Ruby and AOP
have a look at the RcrFoundy on the Ruby Garden Wiki. It's also a
common topic at on the suby-ruby mailing list.

Thanks,
-T.

That's right, but what's the use of such a method? Could you show me a
situation when one would intend to restrict a query to have only
true/false/nil as a result? Upon testing, true and the (not nil, false)
object nil, object itself does to same, so what's the point then?

Csaba

···

On 2005-01-24, Trans <transfire@gmail.com> wrote:

. def a?
. @a ? true : @a
. end

Why not "def a?() @a end"?

Becasue that would be the exact same as 'attr :a'. What would be the
point? This guaruntees only three possible return values: true, false,
and nil.

Trans wrote:

Thanks Glenn,

But do you really find something like:

> attr :a, :a=, :c?

so obfuscating? Every thing has some learning curve to it. I grant you.
But my bet is that this notation would be almost completely undestood
on one's first hunch.

I would probably guess correctly about ":a=", but not ":c?".

I would view these things differently if they were incorporated into the language standard, but as add-ons they just confuse things for little perceivable benefit. I mean, "attr_accessor :symbol" is not transparent to me either, but it's part of the accepted programming conventions for Ruby, and I use it because it requires nothing beyhond baseline Ruby knowledge for the reader. When you want to push beyond that baseline, you should aim to get more bang for your buck.

···

--
Glenn Parker | glenn.parker-AT-comcast.net | <http://www.tetrafoil.com/&gt;

Hi --

I like the features you've added, though.
Could you perhaps call it something other than
"attr", to avoid breakage?

I suppose, but first let me explain. It used to be called #def_attr for
the reason you state. But I always felt like I might as well use #attr
due to its _relative_ uselessness (i.e. overlap functionality with much
more commonly used methods). So I posted a topic here on this list
(110245) that asked about it, and the jist seemed to be that it was
pretty much abandoned. Also, keep in mind that programs using the old
#attr won't be effected unless they become a part of something that
requires this lib --and hell, the current definition of #attr almost
seems like a bug anyway; maybe poeple be happy to finally root them
out. Further, it is backward compatible with reader notation; just not
the accessor notation (i.e. 'attr :a, true').

laptop:/usr/local/lib/ruby/1.8$ ruby -ne 'print $_ if /^\s+attr\s/'
`find . -name "*.rb"` | wc
      76 217 1902

I think some of the ideas you're suggesting might have some interest
but I definitely wouldn't include a module that redefined attr in an
incompatible way.

David

···

On Mon, 24 Jan 2005, Trans wrote:

--
David A. Black
dblack@wobblini.net

Hi --

Oh, and I think that the :x! feature is quite useless. This is
an extremely rare special case and I think it's more obvious
if written out. Or did you find lots of use cases for it?

No. The only thing that comes to mind is in combination with a casting.
Somthing like:

> attr :a! => :upcase

which creates

> def a!(x)
> @a.replace(x.upcase)
> end

But think of that from the point of view of someone using the class,
and writing code in a different file. What you'd see is just this
(using 'text' as the accessor):

   require 'some_file'

   obj = A.new
   obj.text = "Hi there."
   obj.text!
   puts obj.text # "HI THERE."

which is awfully obscure. In essence, there's a verb missing; it's
like doing:

   some_string!

instead of

   some_string.upcase!

Also, !-methods don't have any special correspondence to the 'replace'
operation. All the ! means is that the operation is dangerous (I
think that's the adjective Matz has used) -- which often means it
changes the receiver, but doesn't have to, and it could be a change
that isn't a replace operation.

David

···

On Wed, 26 Jan 2005, Trans wrote:

--
David A. Black
dblack@wobblini.net

Trans wrote:

There is also another form which I thought might be nice to have, a
getter/setter: If an argument is given it acts as a setter, if not it
acts as a getter. But I have no simple notion to use for it. At the
moment it can be done like this:

> attr :"a()"

But I'm not too sure about it.

That's perl style. It does not make sense in Ruby.