New magical version of Symbol.to_proc

D

dblack

Hi --

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:

The intent is very clear, I think. I just don't like the construct
:)
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 :) 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

--
David A. Black | (e-mail address removed)
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
 
D

dblack

Hi --

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 :)


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 :)

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 A. Black | (e-mail address removed)
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
 
D

Dr Nic

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. :)

Nic
 
C

Charles O Nutter

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.
 
D

Dr Nic

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
 
D

dblack

Hi --

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 :)


David

--
David A. Black | (e-mail address removed)
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
 
C

Charles O Nutter

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.
 
T

Trans

Charles said:
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?)).

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.
 
T

Trans

Hi --



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.
 
D

Dr Nic

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 :)

Nic
 
R

Rob Sanheim

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" =)

- rob
 
D

Dr Nic

Rob said:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

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. :)
 
S

Seth Thomas Rasmussen

Charles said:
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.
 
D

Dr Nic

Seth said:
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 :)

Nic
 
D

Dr Nic

Trans said:
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. :(

Cheers
Nic
 
M

MonkeeSage

Seth said:
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

Regards,
Jordan
 
T

Trans

Seth said:
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.

Rails :\
 
C

Charles O Nutter

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.

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.
 
M

Martin DeMello

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

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

Oh so much fun :)

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,187
Latest member
RosaDemko

Latest Threads

Top