New magical version of Symbol.to_proc

On 9/29/06, Dr Nic [email protected] wrote:

You’re quoting techniques need some practise! I don’t think I said that
:slight_smile:

Indeed, indeed, I deleted the “Trans wrote”, I am very bad at that,
sorry
for the confusion

so flawed too. E.g. lots of programing conventions asking for methods to

In JQuery - the javascript library - everything is centered around a
“jquery” object which holds 1+ dom objects in it. All methods on the
jQuery object should return that same set of objects (via the jQuery
object container) so that you can chain method calls.

The idea of returning a proxy object (in the Magic Dot example of
.map.lengths) was very nifty. It works the normal way AND works in the
magical way.

Thx :wink: credits go to BDD of course

The more and more examples I see and concoct myself like this the more I

am happy to give up the core assumptions of “object oriented
programming” etc, and adopt “happy syntax programming”. Syntax that
reads nicely and makes sense as to what it will do and what it will
return.

You are heading for the future, I’ll try to keep up with your ideas.

Now if I could just get the code I originally wrote to work on

ActiveRecord associations I’d be such a happy camper. I’m in love with
that syntax.

Nic


Posted via http://www.ruby-forum.com/.

Robert


Deux choses sont infinies : l’univers et la bêtise humaine ; en ce qui
concerne l’univers, je n’en ai pas acquis la certitude absolue.

  • Albert Einstein

Hi –

On Fri, 29 Sep 2006, Robert D. wrote:

Nic
something.get_other().do_stuff().transform()

Terrible, it is only now that I realize that the concept of writing code
like this might be flawed, there are OTOH strong indications that it is not
so flawed too. E.g. lots of programing conventions asking for methods to
return objects.

I don’t think anyone objects to method-chaining in every case. My
dislike is for method chaining that, to my eye and brain, is just a
way of composing a longer method name (or something that could be done
by passing in arguments representing conditions) with dots.

Your.mileage.may.vary :slight_smile:

David

Hi –

On Fri, 29 Sep 2006, Dr Nic wrote:

Trans wrote:

But as I suggest,
if we see it for what it really is --an adapter, then it makes perfect
sense, and doesn;t seem so magical after all (except that it still
offers some nicely terse syntax).

I agree - it is very nice syntax.

The ship has clearly sailed on the magic dot, but for the record let
me explain what I don’t like about it.

My problem with something like this:

x.should.be.equal.to(y)

(and I don’t mean to parody RSpec; that’s a made-up example but I
think it’s pretty close) is that it uses method calling syntax for
method and/or argument name semantics. To my eye it’s basically
just clustering a bunch of words together that pertain to what’s going
on, and connecting them with dots in a kind of imitation of spaces or
underscores.

It’s very hard to know what “x.should.be” returns. I can figure it
out, of course. But it has a tone of “don’t worry about what’s
actually happening; just read the dot-connected words like a string”,
which makes me uncomfortable.

(Actually I think RSpec itself now allows underscores to formulate
method names.)

I do understand how the “magic dot” works. It works just like every
other dot :slight_smile: I just think there are better-fitted ways to do most of
these things.

array.lengths, for example :slight_smile:

Anyway, just to save some bandwidth:

  • I really do understand how it works :slight_smile:
  • I do know that all method chaining has a bit of this quality.
  • I’m not trying or expecting to stop anyone from doing it; I’m
    just discussing the possible drawbacks.

David

My problem with something like this:

x.should.be.equal.to(y)

It’s very hard to know what “x.should.be” returns. I can figure it
out, of course. But it has a tone of “don’t worry about what’s
actually happening; just read the dot-connected words like a string”,
which makes me uncomfortable.

This would be readable assuming that “should” on x meant something. If I
saw this I’d guess its like “assert”.

But, assuming that your list of words DID mean something, then it has to
be more readable to newcomers (and yourself in 12 mths time) than the
possible equivalent:

x.each {|an_x| assert_equal y, x}

or to rephrase the example, perhaps:

x.should {|an_x| an_x.be :equal, :to, y}

The magic dot gives you left-to-right readability, whereas the above
makes you figure out whats happening in the closure first, then go back
to the x.each part to see where an_x comes from.

Still, you’d have to create an appropriate proxy class for each message
you want to support. That could be a pain.

All good fun though :slight_smile:

Hi –

On Fri, 29 Sep 2006, Dr Nic wrote:

saw this I’d guess its like “assert”.

But, assuming that your list of words DID mean something, then it has to
be more readable to newcomers (and yourself in 12 mths time) than the
possible equivalent:

The intent is very clear, I think. I just don’t like the construct
:slight_smile:

x.each {|an_x| assert_equal y, x}

or to rephrase the example, perhaps:

x.should {|an_x| an_x.be :equal, :to, y}

I think my example, in (say) TestUnit, would be more like:

assert_equal(y,x)

But as I said, the magic dot example was made up, so I can’t really
push the point of what it would be equal to in other terms.

The magic dot gives you left-to-right readability, whereas the above
makes you figure out whats happening in the closure first, then go back
to the x.each part to see where an_x comes from.

I can’t really comment without hooking my eyes up to a machine and
seeing where they go :slight_smile: But there’s no necessity to backtrack once
you’ve seen x.each {|an_x|, from the point of view of understanding
the code. Mind you, the magic dot doesn’t require backtracking
either.

David

Hi –

On Fri, 29 Sep 2006, Robert D. wrote:

As a matter of fact I took your concerns, and Tom’s [ I’ll come back to that
later ] very seriously and did not understand them in the first place.

You made a very good point in your last mail, but again I had the feeling
that I had inadevertly insulted you, it was not my intent.

No, I didn’t get that impression in the slightest. I’m just doing my
usually thing of burrowing down into Ruby stuff and seeing what’s
there – nothing personal riding on it.

David

David wrote

I don’t think anyone objects to method-chaining in every case. My
dislike is for method chaining that, to my eye and brain, is just a
way of composing a longer method name (or something that could be done
by passing in arguments representing conditions) with dots.

Your.mileage.may.vary :slight_smile:

I.see.your.point.emphasis_start.now.emphasis_end
Now that would be abuse of course, mixing content and presentation.

David I am sincerely sorry that my posts -always a bit odd, always a bit
funny [ in both senses of the word ] - have given you the impression
that I
wanted you to explain something.

I am, and all other regular readers are, well aware that your Ruby level
is
way above mine and even I understand the magic dot notation :slight_smile:

As a matter of fact I took your concerns, and Tom’s [ I’ll come back to
that
later ] very seriously and did not understand them in the first place.

You made a very good point in your last mail, but again I had the
feeling
that I had inadevertly insulted you, it was not my intent.

So we have the tool, and as always there is danger with power, Tom’s
link to
the Object Adapter Pattern fits very well and when getting into that
paradigm one might as well adapt more towards method chaining than
before,
even with some small magic.

Tom’s attitude “I do not like that”, “other people like that”, “hmmm why
do
they like it?”,
“hmm maybe because they see it differently, let us do some research”,
“see
that is interesting” is truely admirable and very productive.
I try to mimmick that attitude for sure :slight_smile:

OTOH one has to look out for code that is not too clear, we are starting
a
very philiosophic thread here, sorry folks, I thaught BDDs paradigm
change
was too radical too, but I think that is because I am very conservative
(c.f.
my POV towards ducktyping).

Those of us who want always to understand - count me in for 100% - might
sometimes fall into the trap of not allowing certain abstractions to
take
place because, we cannot - even the smartest - immediately understand
them.
It is a truely difficult process to decide if a new paradigm is worth
exploring and I am more than glad to have nice, competent people here
talking about their paradigms and ideas.

Nuff said for today.

Cheers
Robert

David


David A. Black | [email protected]
Author of “Ruby for Rails” [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB’s Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org


Deux choses sont infinies : l’univers et la bêtise humaine ; en ce qui
concerne l’univers, je n’en ai pas acquis la certitude absolue.

  • Albert Einstein

[David] wrote:

No, I didn’t get that impression in the slightest. I’m just doing my
usually thing of burrowing down into Ruby stuff and seeing what’s
there – nothing personal riding on it.

Ruby is great for burrowing. Java is bad. I remember burrowing in Java
and you always end up at something “final”; something you’d LIKE to
override or extend but you’re not allowed for reasons unknown.

Now we are officially OT. :slight_smile:

Nic

On 9/28/06, Dr Nic [email protected] wrote:

I like this idea too - something that allows you to pick which iterator
method to use (that is: select, each, map)

Implementable syntax might be:

%w{the meaning of 42}.map_length

FWIW I really prefer the magic underscore over anything else.

The pluralization thing has too much potential for collision and looks
jarring (to_as looks to me like “to” “as”, which doesn’t make any
sense; then again I’m not a fan of programmatic pluralization for any
reason, since it’s very western-language-centric and far from
foolproof (moose? virus? fish?)).

The magic dot has a potential to create scads more objects to handle
the adapting. With a magic dot, list.map.to_i necessarily has to
create some adapter object for the call to map so there’s a receiver
for to_i where no object was required before. Unless Ruby is adding a
pretty powerful GC in the future, perhaps we should avoid adding tons
of transient objects just for the magic dot.

The magic underscore has far less potential to cause a collision and
requires no intermediate objects to be created. And as others have
mentioned, it’s been proven to look and feel really nice by
ActiveRecord.

I like your summary.

The pluralization thing has too much potential for collision and looks
jarring (to_as looks to me like “to” “as”, which doesn’t make any
sense; then again I’m not a fan of programmatic pluralization for any
reason, since it’s very western-language-centric and far from
foolproof (moose? virus? fish?)).

I agree that you shouldn’t use it if the resulting code makes no sense
or might cause conflicts. If I’ve got an array of ActiveRecords that
have a name field, then calling @list.names to return an array of names
still seems to be readable and conflictless imo.

The magic dot has a potential to create scads more objects to handle
the adapting. With a magic dot, list.map.to_i necessarily has to
create some adapter object for the call to map so there’s a receiver
for to_i where no object was required before. Unless Ruby is adding a
pretty powerful GC in the future, perhaps we should avoid adding tons
of transient objects just for the magic dot.

Perhaps the proxy could be associated with the class and reused?

The magic underscore has far less potential to cause a collision and
requires no intermediate objects to be created. And as others have
mentioned, it’s been proven to look and feel really nice by
ActiveRecord.

I like this a lot too.

#1 and #3 are currently available in the .rb file on my blog page for
anyone finding this thread.

Nic

On 9/29/06, Dr Nic [email protected] wrote:

The magic dot has a potential to create scads more objects to handle
the adapting. With a magic dot, list.map.to_i necessarily has to
create some adapter object for the call to map so there’s a receiver
for to_i where no object was required before. Unless Ruby is adding a
pretty powerful GC in the future, perhaps we should avoid adding tons
of transient objects just for the magic dot.

Perhaps the proxy could be associated with the class and reused?

Threading, threading, threading…remember JRuby is native-threaded
and Ruby 2.0 should be as well. Even if not native-threaded, a
green-thread context switch could try to use it twice.

And before someone suggests a “proxy pool”, almost all benchmarks I’ve
seen show that with a good GC, just creating transient objects is way
faster than pooling. Of course, Ruby’s GC is not on the same level as
the JVM’s, so a pool may be faster in Ruby’s case.

Hi –

On Fri, 29 Sep 2006, Charles O Nutter wrote:

On 9/28/06, Dr Nic [email protected] wrote:

I like this idea too - something that allows you to pick which iterator
method to use (that is: select, each, map)

Implementable syntax might be:

%w{the meaning of 42}.map_length

FWIW I really prefer the magic underscore over anything else.

I do too, generally, though map_length sounds like “the length of the
map of this object”. One starts to think there’s a reason that map
takes a block…

The pluralization thing has too much potential for collision and looks
jarring (to_as looks to me like “to” “as”, which doesn’t make any
sense; then again I’m not a fan of programmatic pluralization for any
reason, since it’s very western-language-centric and far from
foolproof (moose? virus? fish?)).

Yeah, that was my point with sheep, even though I do rather like the
way the plural things read (when they work). How about:

array.meese.each do |moose| … end

The mind boggles :slight_smile:

David

Charles O Nutter wrote:

The pluralization thing has too much potential for collision and looks
jarring (to_as looks to me like “to” “as”, which doesn’t make any
sense; then again I’m not a fan of programmatic pluralization for any
reason, since it’s very western-language-centric and far from
foolproof (moose? virus? fish?)).

You are right there. Pluralization is really going overboard, besides
the exceptions it creates a great deal of computational overhead. It
seems great on the surface, but in the end it is simply is not worth
the effort. Although it can seem odd for the English speaker at times,
Ruby’s general favoring of the singular is a very good thing. And this
is one area in which I feel Rails has been unhelpful.

The magic dot has a potential to create scads more objects to handle
the adapting. With a magic dot, list.map.to_i necessarily has to
create some adapter object for the call to map so there’s a receiver
for to_i where no object was required before. Unless Ruby is adding a
pretty powerful GC in the future, perhaps we should avoid adding tons
of transient objects just for the magic dot.

Actually this is largely mitigated. Best practice is to cache the
adapter object. So for example Enumerable#every:

def every
@_functor_every ||= Functor.new do |op,*args|
self.collect{ |a| a.send(op,*args) }
end
end

This is something not often shown in examples and admittedly may not
make it into first editions of such functions in practice, but
utlimately it gets incorporated and makes a huge difference in the over
head you mention.

The magic underscore has far less potential to cause a collision and
requires no intermediate objects to be created. And as others have
mentioned, it’s been proven to look and feel really nice by
ActiveRecord.

I disagree. “Magic underscore”[1] is either a function of
method_missing or dynamic method creation. There is acually more
potential for name collision in these cases. IN fact that is one of the
uses of the magic dot, to create namespaces. Also care must be taken to
propogte method_missing through the class heirarchy so as not to step
on other people’s magic toes. And dynamic method creation adds a lot of
additional methods to a class that Ruby must sort through when
dispatching a call. It certainly looks nice, and I’m in no way agasint
it’s use. But there are tradoffs to be considered, and one should apply
that techinique that works best to the need at hand.

[1]FYI, “magic underscore” isn’t an a good name b/c we’re really just
talking about dynamic method names. These can be anything and do not
neccessarly need an underscore.

T.

[email protected] wrote:

I agree - it is very nice syntax.

The ship has clearly sailed on the magic dot, but for the record let
me explain what I don’t like about it.

My problem with something like this:

x.should.be.equal.to(y)

I agree. Unless #should, #be and #equal are all creating some truly
useful and generally applicable adaptation then this is just “fluff
code”. Again overhead is being added for no appreciable gain. Of
course, I making an assumption here since I haven’t looked at the code
, but I suspect that a magic dot notation like:

x.should_be.equal_to(y)

is more appropriate. In this case it is easy to see that #should_be is
an assertion adapter. This is interesting, b/c when you break it down
like this one could actaully go a bit further and create more natural
ruby constructs:

x.should == y

T.

With everyone’s well founded concerns about name collisions, we should
all know full well that we live with them in Ruby world on a daily
basis: monkey patching, method overriding in subclasses, aliasing and
chain aliasing (how many times do ActiveRecords need to alias some
methods?!), etc. So hopefully our internal namespace collision detectors
are already turned on :slight_smile:

Nic

Rob S. wrote:

On 9/29/06, Dr Nic [email protected] wrote:

With everyone’s well founded concerns about name collisions, we should
all know full well that we live with them in Ruby world on a daily
basis: monkey patching, method overriding in subclasses, aliasing and
chain aliasing (how many times do ActiveRecords need to alias some
methods?!), etc. So hopefully our
internal namespace collision detectors are already turned on :slight_smile:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

You misspelt “extensive test suite running continuously” =)

No spellchecker on Ruby forums UI. Perhaps I can whip up a greasemonkey
script to help me with such simple/common typos. :slight_smile:

On 9/29/06, Rob S. [email protected] wrote:

On 9/29/06, Dr Nic [email protected] wrote:

internal namespace collision detectors are already turned on :slight_smile:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

You misspelt “extensive test suite running continuously” =)

Miss Van Pelt, reread your Peanuts,
but you have a point of course!

  • rob…

…ert

Charles O Nutter wrote:

The pluralization thing has too much potential for collision and looks
jarring (to_as looks to me like “to” “as”, which doesn’t make any
sense; then again I’m not a fan of programmatic pluralization for any
reason, since it’s very western-language-centric and far from
foolproof (moose? virus? fish?)).

And just about every programming language syntax isn’t already? I like
programmatic pluralization because it allows us to write code in the
same way we talk about it. It’s like optimization for our brains, and
expressive power that seems to get closer to more intelligent programs,
as well as making syntax more accessible to laypersons. As for the
potential inaccuracy of converting certain terms, you could provide an
interface to add definitions as Rails’ Inflector does.

On the topic at hand, I don’t like the plurals option. The
Symbol#to_proc style currently in ActiveSupport seems just about
perfect to me, although I don’t see why it couldn’t just be:

foos.map :bar

p.s. I got totally lost with all that crazy.dot.talk. That hypothetic
code made me want to cry.

Seth Thomas R. wrote:

foos.map :bar

That’d be workable syntax.

class Array
alias old_map map
def map(*args)
if args.length > 0
return self.map {|item| item.send args.first}.map *args[1…-1]
else
return self.old_map
end
end
end

This would allow:
people.map :fullname, :split

as the equivalent of:
people.map {|p| p.fullname}.map {|n| n.split}

Oh so much fun :slight_smile:

Nic

On 9/29/06, Dr Nic [email protected] wrote:

With everyone’s well founded concerns about name collisions, we should
all know full well that we live with them in Ruby world on a daily
basis: monkey patching, method overriding in subclasses, aliasing and
chain aliasing (how many times do ActiveRecords need to alias some
methods?!), etc. So hopefully our
internal namespace collision detectors are already turned on :slight_smile:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

You misspelt “extensive test suite running continuously” =)

  • rob