"Readability" inflation

R

Ryan Leavengood

This whole discussion is silly. If you really think this is "longer" or
"less readable"

ObjectSpace.select(Class) { |c| c.name =3D~ /^S/ }

Than this:

ObjectSpace.enum_for:)each_object, Class).select { |c| c.name =3D~ /^S/
}

Then by all means, type away.

But you are cheating here by leaving out the "setup code" that allows
you to call ObjectSpace.select. I would be curious to see other
examples where you use EnumerableArgs, because as Robert says there
aren't many "each" methods that take a parameter. Using ri on my 1.8.2
install, I could only find String#each and IO#each, both of which take
an optional "separator" parameter. I personally don't see many cases
where I would need to override the default, especially when calling
Enumerable methods. Plus since both already include Enumerable, I'm
not sure what kinds of wacky things would happen if you mixed in
EnumerableArgs as well.

Ryan
 
T

Trans

Ryan said:
But you are cheating here by leaving out the "setup code" that allows
you to call ObjectSpace.select.

I don't really see that as cheating since the code is already written
and stored in a reusable lib. EnumerableArgs is not something you'd use
on an existing classes in general, but on something you've created new
--otherwise you'd be redefining #each in a core/standard lib which is
not something you want to do lightly in the first place. It doesn't
really bother ObjectSpace b/c it has no #each method or Enumerable
inclusion, but has an each-like method. So it makes a good example
case.
I would be curious to see other
examples where you use EnumerableArgs, because as Robert says there
aren't many "each" methods that take a parameter. Using ri on my 1.8.2
install, I could only find String#each and IO#each, both of which take
an optional "separator" parameter.

And those are poor parameters to beign with --they have bad side effect
b/c they default to a global var. Not a very robust solution. I hope
Matz will be changing that for 2.0.
I personally don't see many cases
where I would need to override the default, especially when calling
Enumerable methods. Plus since both already include Enumerable, I'm
not sure what kinds of wacky things would happen if you mixed in
EnumerableArgs as well.

If you did include EnumerableArgs there would be no adverse effects
--assumming I it's working as it was designed to. The design goal was
complete transparency. Of course nothing's perfect. I originally wrote
the code for 1.6 so some things have changed. But I did just spend a
couple hours rewritting it to use Enumerator and dynamically generate
the methods based on Enumerable. That way I no longer need to keep it
up-to-date by hand. (Seems a tad slower though suprisingly) So it
should work nearly flawslessly. There are only two caveats. 1) #inject
and #zip can not pass parameters to #each due to their negative arity,
so they work just as they do in Enumerable. And 2) #find (alias
#detect) has been modified to get rid of the 'ifnone' parameter, and
instead made an optional keyword parameter :)ifnone=>...), which makes
more sense considering what it is and how rare it's usage is (it only
accepts a proc). So only this last caveat would present a compatabilty
issue if you were for some strange reason to try and make it a complete
drop in replacemet for Enumerable.

Now what kind of use real might it have besides ObjectSpace? Simply
imagine any class that might have multipe each methods:

class House
include EnumerableArgs

def each_bedroom ...
def each_closet ...
def each_room ...
def each_hallway ...

def each(which=:room, &blk)
send("each_#{which}", &blk)
end
end

h = House.new
h.select:)bathroom) { |b| ... }

T.
 
R

Ryan Leavengood

Now what kind of use real might it have besides ObjectSpace? Simply
imagine any class that might have multipe each methods:

class House
include EnumerableArgs

def each_bedroom ...
def each_closet ...
def each_room ...
def each_hallway ...

def each(which=3D:room, &blk)
send("each_#{which}", &blk)
end
end

h =3D House.new
h.select:)bathroom) { |b| ... }

I see your point, but:

require 'enumerator'

h =3D House.new
h.enum_for:)each_bathroom).select {|b| ... }

I *really* don't see how yours is much better. In fact, I'd argue the
enumerator one is better because it is more explicit...anyone who
knows how enumerator works can see what is happening. Only you, me and
the people paying attention to this thread would understand what the
EnumeratorArgs thing was doing.

But I guess we will just have to agree to disagree, since we are both
dragging this into one of those endless discussions threads that I
dislike so much ;)

Signing off,
Ryan
 
J

James Edward Gray II

I see your point, but:

require 'enumerator'

h = House.new
h.enum_for:)each_bathroom).select {|b| ... }

I *really* don't see how yours is much better. In fact, I'd argue the
enumerator one is better because it is more explicit...anyone who
knows how enumerator works can see what is happening.

Yes, an isn't Enumerator in the core as of 1.9? Time to get use to
seeing it. ;)

James Edward Gray II
 
C

Christophe Grandsire

Selon James Edward Gray II said:
Yes, an isn't Enumerator in the core as of 1.9? Time to get use to
seeing it. ;)

Indeed, check: http://ruby-doc.org/core-1.9/

Not only that, but there is also the plan to have enumerating methods ret=
urn an
enumerator when they aren't given a block. I don't know if it still will
happen, but it sure is a great idea (that would only be for the methods t=
hat
don't already have a defined meaning when they aren't given a block I sup=
pose).
--
Christophe Grandsire.

http://rainbow.conlang.free.fr

It takes a straight mind to create a twisted conlang.
 
T

Trans

Ryan said:
I see your point, but:

require 'enumerator'

h = House.new
h.enum_for:)each_bathroom).select {|b| ... }

I *really* don't see how yours is much better. In fact, I'd argue the
enumerator one is better because it is more explicit...anyone who
knows how enumerator works can see what is happening. Only you, me and
the people paying attention to this thread would understand what the
EnumeratorArgs thing was doing.

But I guess we will just have to agree to disagree, since we are both
dragging this into one of those endless discussions threads that I
dislike so much ;)

I see your point too. Enumerator, and things like #every, are starting
to come into their own. I wrote EnumerableArgs some time ago when the
clearest approach was a beefed up Mixin (we didn't even have #inject
yet). Like I said to David easlier, I think we will just have to get
used to this new paradigm of intermediate objects acting as "roles".
(And I have to admit I've propogated it mayself with the Functor
class). So to it's end may I then suggest:

h.enumerate:)each_bathroom).select { ...

;)

ciao,
T.
 
D

David A. Black

Hi --

Indeed, check: http://ruby-doc.org/core-1.9/

Not only that, but there is also the plan to have enumerating methods return an
enumerator when they aren't given a block. I don't know if it still will
happen, but it sure is a great idea (that would only be for the methods that
don't already have a defined meaning when they aren't given a block I suppose).

I'm not sure where that stands either. It always looked too
elliptical to me, if I'm remembering it correctly -- too much in the
category of "dot syntax for non-dot semantics". I know that a method
call can return an enumerator as well as anything else, but it just
always looked a little odd to me:

people.each.something...

It looks like chaining but it isn't really.


David
 
D

daz

Ryan said:
I see your point, but:

require 'enumerator'

h = House.new
h.enum_for:)each_bathroom).select {|b| ... }

I *really* don't see how yours is much better. In fact, I'd argue the
enumerator one is better because it is more explicit...anyone who
knows how enumerator works can see what is happening. Only you, me and
the people paying attention to this thread would understand what the
EnumeratorArgs thing was doing.

But I guess we will just have to agree to disagree, since we are both
dragging this into one of those endless discussions threads that I
dislike so much ;)

Signing off,
Ryan


IMHO, both are just circuitously avoiding:

class House

def bathrooms
@rooms.select {|r| r.typ == :bathroom}
end
def bedrooms ...
def closets ...
def hallways ...

end

h = House.new
h.bathrooms.each { |b| ... }


Yes, Enumerator is available in 1.9 without a /require/.
I think it'll stay because it works and there'll be no cause to
remove it.

It'll be an occasional source of amusement for me to mentally
rewrite any posted usage. I envisage being able to backport
#enum_for and its ilk, in all but the most contrived examples,
instinctively. :p

daz
 
J

James Edward Gray II

Yes, Enumerator is available in 1.9 without a /require/.
I think it'll stay because it works and there'll be no cause to
remove it.

It'll be an occasional source of amusement for me to mentally
rewrite any posted usage. I envisage being able to backport
#enum_for and its ilk, in all but the most contrived examples,
instinctively. :p

I must be one of the few Enumerator fans in this thread. I think
it's just cool. ;)

James Edward Gray II
 

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,744
Messages
2,569,479
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top