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.
I just could not resist, I am still amazed - after 20 years of Ruby
experience 8-], how easily things can be done, when did I say Ty the last
time Matz? Probably 20 years ago!!!
Ty Matz!!!
for those who like the notation, very, very lazily tested, but amazingly
simple, probably rather slow etc....
--------------------- 8< ---------------------
module Enumerable
class MapProxy
def initialize obj @obj = obj
end #def initialize obj
def method_missing name, *args, &blk @obj.map do
> ele |
ele.send name, *args, &blk
end
end #def method_missing name, *args, &blk
end #class MapProxy
alias_method :aliased_map, :map
def map *args, &blk
return MapProxy.new( self ) if args.length.zero? && blk.nil?
aliased_map *args, &blk
end #def map *args, &blk
end #module Enumerable
---------------- 8< --------------------
Cheers
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.
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).
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.
···
On 9/29/06, Dr Nic <drnicwilliams@gmail.com> 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?
--
Contribute to RubySpec! @ Welcome to headius.com
Charles Oliver Nutter @ headius.blogspot.com
Ruby User @ ruby.mn
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
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}
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 way I coded it, it singularizes the string and passes that as the
method call for the items of the collection. So if you pass a singular
method name, then it will still be singular when its passed to the
children.
That is:
people.names
returns the same list of names as
people.name
So non-English speakers can be happy too. Of course, if the people Array
class had a name method, the latter wouldn't work. But unless you have
an Array of Arrays, you won't get many name conflicts btw the Array
class and the container class.
Re: performance overhead - I'm not sure if the standard map+block is
more or less efficient than a for-loop, but I use it anyway because my
code is much more readable and writable. If I later discovered that I
had a performance bottleneck near my map+blocks, then I could refactor
them for speed.
I don't think that in a thread on "fun syntax ideas" disapproving on the
ideas based on small performance hits like "apply a gsub on a string" is
much fun.
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
It can...
class Array
def map(sym=nil, &block)
self.inject() { |col, item|
if block_given?
col << block.call(item)
elsif not sym.nil?
col << item.send(sym)
else
col << item
end
}
end
def map!(sym=nil, &block)
self.replace(map(sym, &block))
end
end
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.
It is for the first time that I hear that very honorable members of the
community dislike this feature.
For me it was the most intreaging of Ruby at all (at the beginning)
I recall my old Python code
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.
Now, to complicate things even more, very often that object is "self",
personally I find the idea to return other objects, especially proxy objects
to self, very intriguing, the idea came to me when I looked at the BDD video
cast.
Cheers
Robert
···
On 9/29/06, Dr Nic <drnicwilliams@gmail.com> 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).
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 I just think there are better-fitted ways to do most of
these things.
array.lengths, for example
Anyway, just to save some bandwidth:
* I really do understand how it works
* 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.
You misspelt "extensive test suite running continuously" =)
- rob
···
On 9/29/06, Dr Nic <drnicwilliams@gmail.com> 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
The JRuby code started out as a port of the C Ruby code, and for us a
'for' is just an 'each' over a range...so it's probably about the
same, performance-wise.
···
On 10/1/06, Dr Nic <drnicwilliams@gmail.com> wrote:
Re: performance overhead - I'm not sure if the standard map+block is
more or less efficient than a for-loop, but I use it anyway because my
code is much more readable and writable. If I later discovered that I
had a performance bottleneck near my map+blocks, then I could refactor
them for speed.
--
Contribute to RubySpec! @ Welcome to headius.com
Charles Oliver Nutter @ headius.blogspot.com
Ruby User @ ruby.mn
I did this a while back by adding an f (for functional) to the method
name - so if you said people.mapf :fullname method_missing would see
that it ended with an f, strip the f out and construct a block to pass
to map. map_fullname reads even better, though.
martin
···
On 10/1/06, Dr Nic <drnicwilliams@gmail.com> wrote:
This would allow:
people.map :fullname, :split
as the equivalent of:
people.map {|p| p.fullname}.map {|n| n.split}
I'll have a look at T's link but it is a truely interesting discussion.
You're quoting techniques need some practise! I don't think I said that
It is for the first time that I hear that very honorable members of the
community dislike this feature.
For me it was the most intreaging of Ruby at all (at the beginning)
I recall my old Python code
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.
Now, to complicate things even more, very often that object is "self",
personally I find the idea to return other objects, especially proxy
objects
to self, very intriguing, the idea came to me when I looked at the BDD
video cast.
In Smalltalk all methods return self unless they return something else,
thus inferring that something.get_other().do_stuff().transform() (using
Smalltalk syntax is common.
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.
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.
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
···
On 9/29/06, Dr Nic <drnicwilliams@gmail.com> wrote:
On 9/29/06, Dr Nic <drnicwilliams@gmail.com> 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'll have a look at T's link but it is a truely interesting discussion.
It is for the first time that I hear that very honorable members of the
community dislike this feature.
For me it was the most intreaging of Ruby at all (at the beginning)
I recall my old Python code
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.
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.
> 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)
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:
On 9/29/06, Dr Nic <drnicwilliams@gmail.com> 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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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.