Yeah the inheritance chain thing is hard.
The closest you can come is with modules.
...
class Object
override do
def print *args
super *(args + ["
"])
end
end
end
3
Nifty! Thanks.
The only complaint I've heard about it was from Tony Arcieri's post
wondering "how do you return anything from blocks?"
i.e. in Ruby "array.collect{|a|}.reject{|b| true}"
how to do that with indented blocks.
I still have a tough time understanding this objection. What I'm
essentially proposing is that at least in the case of code blocks that
start with a colon, a de-dent takes the place of an end. Given that, I
just don't see what it is that could be done without end that couldn't
be done without dedenting. In this example, the braces would continue
to work as expected (and there are no end statements), but for
something like this:
array.reject do |b|
true
end
.... it would just be:
array.reject do |b|:
true
I guess with the collect thrown in, the current implementation with do-
end rather than braces would be
array.collect do |a|
end.reject do |b|
true
end
...is that right? Using indentation to deliniate blocks does have the
problem that you can't have a null block like the one passed to
collect here. Python gets around it with the keyword "pass", as in:
for x in xrange(50): # Python equivalent of (0...50).each do |x|
end
pass
So this could be:
arra.collect do |a|:
pass
..reject do |b|:
true
Interesting--so you propose to use : when you want a block but *dont*
care about using its return value, is that right?
No, not exactly. The issue with return values is orthogonal to this.
My proposal is to use the : if you want dedent to substitute for end
to terminate the block. I still don't see why return values are
affected.
and then afterward it picks up the previous indentation? I
suppose...that would work. It's an odd use for {}'s though which are
already pretty heavily used.
True, and I'm not too thrilled with the solution, but maybe there's
something better. {} is heavily used, but on the other hand one of its
common uses is to divide code into blocks, and that's what it's doing
here.
Overall I like the idea--making "end's" optional would indeed be kind.
It is better than a similar idea I had recently, which was to use : for
single line blocks (only), i.e.
if a == b : do_something
instead of
if a == b; do_something; end
This suggestion is not at all incompatible with mine, and in fact
that's the way Python does it too (except you'd have to put parens
after do_something
...
if a==b:
# Nothing follows the colon, so this starts a new scope indented
past the if statement
do_something()
do_something_else()
if a==b: do_something() # code follows the colon, so it constitutes
the entire block
do_something_else()
if a==b:
do_something_else() # error, the parser expects a new level of
indentation
if a==b: do_something()
do_something_else() # error, the parser does not expect a deeper
indent
The other concern is that "the allure of magic indentation wears thin
for large docs" which fact "worked to ensure you kept your methods
short."[1]
Well, all I can say is, that's his opinion. Hasn't lost its allure for
me. And if it did lose its allure, I would think that it wouldn't be
for large docs, it would be for deeply _nested_ docs. I definitely
sympathize with his mockery of the notion that this limitation is a
blessing in disguise because it encourages you to keep your methods
short... it reminds me of how I felt when I first heard that Java's
lack of pointers meant you couldn't write any pointer bugs. But my
employer imposes a strict 80-column limit on source files including
Python, we have a lot of Python code, and it all works out.
Also could parsers handle it?
I think so, especially since the preprocessor I've used (wish I could
remember its name... it's not Lazibi [1]) does it in a fairly clever
way in Ruby itself, so I don't see why the parser couldn't do what it
does.
Thanks for your comments, I appreciate the feedback.
[1]
http://lazibi.rubyforge.org/