Pythonic indentation (or: beating a dead horse)

“J Haas” [email protected] schrieb im Newsbeitrag
news:[email protected]
…“pythonic insertion”…

I have some suspicion this was a joke thread.
(Hint: Format of OP)
However.
I don’t want to discuss this issue because people using non-existing
whitespaces for serious coding probably have a value system which is
orthogonal to my value system.
This sort of structuring pieces of code stopped me from trying Python
seriously.
However.

Isn’t there an Syntax-Highlighting Editor out there which allows
assigning
1-Point size to End-Only-Lines?
Or, why not just use white-on-white for “end”-statement?
(Maybe you additionally should use CTRL-BS as macro for “end”…)

Wouldnt this be the easiest way to solve your problem?

Regards,
Michael B.

On May 20, 2009, at 11:51 AM, Rick DeNatale wrote:

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

That would be a valid criticism if J Haas’s suggestion made things
less readable. But having to scroll less makes things more readable.

On May 19, 2009, at 5:40 PM, J Haas wrote:

means what you’d expect: there are four places in the scanned files

This is not DRY. Or anything remotely resembling it. This is an
ugly blemidh on a language that otherwise is very beautiful.

It’s at this point that I started to wonder if you’ve had a look-see
at _why’s new language, Potion? Specifically:

…maybe something like this:

module Kernel
override print(*args)
do_something
overridden *(args + [" :-)"])
end
end

Yeah the inheritance chain thing is hard.
The closest you can come is with modules.

class Class
def override &block
m = Module.new
m.module_eval &block
include m
end
end

now

class Object
override do
def print *args
super *(args + [" :-)"])
end
end
end

print 3
3 :slight_smile:

ref: http://www.ruby-forum.com/topic/176080#new last post
alias_method_chain in models

But I digress… the purpose of this post is to talk about one of the
relatively
few areas where I think Python beats Ruby, and that’s syntatically-
significant
indentation.

Not having the “end” is indeed very clean and kind on the eyes–kind of
reminds me of what Ruby does, which is try to make things look better
for you.

The only complaint I’ve heard about it was from Tony A.'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.

That being said, splitting it up into 3 neat python blocks doesn’t look
bad at all, so it’s not a big loss there. I’m not too familiar with
Python syntax so I’m not exactly sure what’s possible, either. What
would a good syntax be to return values from indented blocks?

My proposal is to, first, not change a thing with respect to existing
syntax. Second, steal the : from Python and use it to signify a scope
that’s marked by indentation:

I did note Matz recent comment on using the “:” as a separator:
http://redmine.ruby-lang.org/issues/show/1389

Perhaps you could take your pitch to him :slight_smile:

while some_condition:
# this scope will terminate when the indentation level decreases
to the
# level before it was entered
do_something

Interesting–so you propose to use : when you want a block but dont
care about using its return value, is that right?

We can get around this by saying that braces, wherever they may appear,
always define a new scope nested within the current scope, regardless
of indentation.

def do_something(a, b, c):
{ print a, b, c } # this works
a + b + c

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.

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

but your suggestion seems to include even more than that.

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]

Also could parsers handle it?
Thoughts?

=-r
[1] Ruby Buzz Forum - Thoughts on Haml

Joshua B. wrote:

The closing “_ say” ends the block saved to “say” var.
Or maybe some variation on Lisp’s superparenthesis?

http://www.gavilan.edu/csis/languages/parentheses.html

On May 20, 8:51 am, Rick DeNatale [email protected] wrote:

Seriously, if you measure things by avoiding extra keystrokes, get a
better editor. I value readability over parsimony of lexical items.

Cluttering up your code with “end” everywhere makes it less readable,
not more.

On May 20, 9:01 am, “Michael Bruschkewitz”
[email protected] wrote:

I have some suspicion this was a joke thread.
(Hint: Format of OP)

Nope, I’m sincere. As I said before, I’m new. The formatting was a
misguided attempt to make things look nice by manually wrapping them
at 80 columns. Oops.

This sort of structuring pieces of code stopped me from trying Python
seriously.

And I specifically addressed this in my OP. A lot of engineers who
haven’t done work in Python think that the idea of giving syntactical
significance to whitespace is a ridiculous idea. I used to be one of
them. Now I know better. Don’t knock it until you’ve tried it.

Isn’t there an Syntax-Highlighting Editor out there which allows assigning
1-Point size to End-Only-Lines?

Aside from the fact that this wouldn’t solve the problem that I’d
still have to write the damned things, this is possibly the
kludgiest solution imaginable.

Wouldnt this be the easiest way to solve your problem?

The easiest way to solve my problem would be for me to use one of
the preprocessing scripts that impose Python-like indentation syntax
on Ruby. But that wouldn’t solve the larger problem, which is that
Ruby could be better than it is.

On May 20, 10:04 am, Joshua B. [email protected] wrote:

It’s at this point that I started to wonder if you’ve had a look-see
at _why’s new language, Potion?

Nope. but I’ll check it out. Thanks.

On Wed, May 20, 2009 at 2:35 PM, J Haas [email protected] wrote:

On May 20, 8:51 am, Rick DeNatale [email protected] wrote:

Seriously, if you measure things by avoiding extra keystrokes, get a
better editor. I value readability over parsimony of lexical items.

Cluttering up your code with “end” everywhere makes it less readable,
not more.

Honestly, that’s subjective. Some people prefer delimiters some don’t.

In general I’m not a fan of languages whose syntax depends on the
number of rather than just the presence of whitespace characters. I
find it hard to count blanks while reading.

I tried hard to like haml for instance. It has a lot of good points,
but the pythonic style of nesting just doesn’t work for me.

In code, the real solution is not to nest so deeply that it becomes a
problem, learn to use the composed method pattern.


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

On Wed, May 20, 2009 at 1:10 PM, J Haas [email protected] wrote:

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.

I already responded to this. I guess you didn’t see it. There are
several
types of statements which contain multiple indent blocks (and thus
multiple
dedent tokens). These would include if statements:

if foo
blah
elsif bar
blah2
else
baz

Begin statements (ala try/catch in Python)

begin
somecode
morecode
rescue FooError
some_rescue_action
rescue BarError
another_rescue_action
ensure
something_gets_done

Case statements:

case foo
when bar
do_something
when baz
do_something_else

Each of these statements is an expression with multiple clauses. How do
you
tell when these expressions are complete? Obviously a naive “dedent =
end
of expression” approach doesn’t work in these cases.

These work in Python because Python has a special grammar for statements
which doesn’t require a statement separator for any statements which
have
indent blocks. This doesn’t work in a language where everything is an
expression, because all expressions must be treated the same and all
expressions must have an expression terminator (newline or semicolon)

On May 20, 10:23 am, Roger P. [email protected] wrote:

print 3

3 :slight_smile:

Nifty! Thanks.

The only complaint I’ve heard about it was from Tony A.'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.

def do_something(a, b, c):
{ print a, b, c } # this works
a + b + c

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/

On Wed, May 20, 2009 at 1:25 PM, Tony A. [email protected] wrote:

do_something
when baz
do_something_else

And yet another consideration with this in Ruby vs. Python: in Ruby
these
are all expressions (as has been stated repeatedly) and therefore you
can do
this sort of thing:

x = case foo
when bar
do_something
when baz
do_something_else
else
whatever
end

i.e. the case statement returns the value of the last expression
evaluated
in the taken branch.

This is not the case in Python (well first because Python doesn’t have
case
statements) where no expressions can contain indent blocks.

On May 20, 2009, at 3:10 PM, J Haas wrote:

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.

A friendly suggestion: One of Ruby’s strengths (one that it shares
with Perl) is its power to manipulate and parse strings. If you’re new
to Ruby, a script which takes your colon/de-indent syntax and turns it
into the proper do/end syntax sounds like a great project to get
started. Since you desire to write Ruby code in this way, it would
also give you a great excuse to approach this problem using TDD. That
is, write the code in the way you would like it to appear as a test,
then write the parser/de-re-mangler to have the test pass. I honestly
think you could have done this with the same amount of effort as it
has taken to reply to each of the e-mails in this thread.

Let me be frank: Your suggestion is not new. Code speaks louder than
words. When you do implement this alternative Ruby syntax, I think
you may be surprised at the number of corner and edge cases. Ruby is
currently in the process of being standardized. I would imagine the
last thing that Ruby needs while undergoing the standardization
process is a new, optional syntax with a multitude of corner and edge
cases.

Cheers,

Josh

On Wed, May 20, 2009 at 3:44 PM, Juan Z. [email protected]
wrote:

Cluttering up your code with “end” everywhere makes it less readable,
not more.

Honestly, that’s subjective. Some people prefer delimiters some don’t.

Is it subjective? Neither method is ambiguous. So no problem there. But
scrolling 16% more often? That must have some cost to readability.

If you break up code into more files, or use a folding editor, or use
an editor that lets you jump to code by a method name, scrolling is a
non-issue.

Rick’s point remains. If this is an issue you’re facing, get a better
editor.

-greg

On 19.05.2009 23:35, J Haas wrote:

I am not a zealot and have little tolerance for zealotry, and I have
no
desire to get involved in holy wars.

The length of your statement and the wording seem to indicate
differently:

hate that
Ruby doesn’t have it.

My friends, when ONE OUT OF EVERY SIX of your code lines consists of
just the
word “end”, you have a problem with conciseness.

(So far I can only see that you are having a problem.)

But let me say that again: ONE OUT OF EVERY SIX LINES, for
crying out
loud! This should be intolerable to engineers who value elegance.

Well, tough. Programmers shouldn’t be using freakin’ tabs anyway, and

I don’t think
it’s worthwhile to inflate the code base by a staggering 20% to
accommodate
people who want to write ugly code,

Kind regards

robert

On May 20, 2009, at 2:51 PM, Rick DeNatale wrote:

On Wed, May 20, 2009 at 2:35 PM, J Haas [email protected] wrote:

On May 20, 8:51 am, Rick DeNatale [email protected] wrote:

Seriously, if you measure things by avoiding extra keystrokes, get a
better editor. I value readability over parsimony of lexical items.

Cluttering up your code with “end” everywhere makes it less readable,
not more.

Honestly, that’s subjective. Some people prefer delimiters some don’t.

Is it subjective? Neither method is ambiguous. So no problem
there. But scrolling 16% more often? That must have some cost to
readability.

On Thu, May 21, 2009 at 12:21 AM, Rick DeNatale
[email protected] wrote:

Honestly, that’s subjective. Some people prefer delimiters some don’t.

Scheme strikes a beautiful balance, I think

(class Object
(def initialize foo bar
(whatever
whatever)))

no strings of ends, but no significant whitespace, and vim users can
bounce on the % key and be happy.

martin

J Haas:

A lot of engineers who haven’t done work in Python think that the idea
of giving syntactical significance to whitespace is a ridiculous idea.
I used to be one of them. Now I know better. Don’t knock it until
you’ve tried it.

I’m one of the idealists who actually loved Python’s idea of
indentation, meaningful whitespace and the least possible clutter
(to the point that I actually preferred tabs to spaces – that’s the
whole point of a tab, to indent), and I did write quite a few lines
of Python in my life – and after all that, I’m now strongly in the
‘no significant whitespace’ camp.

I might miss my idealism, but the practical advantages of
non-significant whitespace win for me on all fronts: I can
actually use code snippets without reindenting them, badly-indented
code tells me outright that I shoudn’t even bother reading it, and
I can do all kinds of commenting-out/debug print calls really fast.

Aside from the fact that this wouldn’t solve the problem
that I’d still have to write the damned things

If you have to write the ‘end’ statements yourself (and it bothers you),
then you either don’t use a sane editor or didn’t configure it properly.

— Shot

On May 20, 12:25 pm, Tony A. [email protected] wrote:

I already responded to this. I guess you didn’t see it.

I responded to your response, I guess you didn’t see that. Tell me
what’s wrong with the following alternatives to your examples:

if foo
blah
elsif bar
blah2
else
baz

Just like with your case example before, whoops! You’re missing an
end, and the parser will complain when it sees the end-of-file without
a missing end. And just as I said with your case example before, I
sure hope this missing end isn’t in the middle of a long file or you
get to spend a lot of time scrolling through your code looking for the
place where it’s missing.

But if we amend your example to

if foo
blah
elsif bar
blah2
else
bar
end

…I really don’t see what’s wrong with this as an alternative:

if foo:
blah
elsif bar:
blah
else:
bar

No end necessary.

something_gets_done
Again, you’re missing an end. Applying the same pattern I applied in
the if and case examples, I do not see what the problem is. How is it
any less functional than the current Ruby?

Each of these statements is an expression with multiple clauses. How do you
tell when these expressions are complete? Obviously a naive “dedent = end
of expression” approach doesn’t work in these cases.

Okay, I think I see what you’re saying now. But each of those also, in
the clauses after the first one, begins with a keyword that is not
valid except as part of the previous expression. Does it solve the
problem if dedenting ends an expression unless it’s immediately
followed by a keyword that makes no sense except as a continuation of
the expression?

This doesn’t work in a language where everything is an
expression, because all expressions must be treated the same and all
expressions must have an expression terminator (newline or semicolon)

You keep on saying this, yet I have not seen one example of code that
demonstrates that using dedent couldn’t work. Basically, we’re looking
for some code which, if you removed the all ends, a script following
simple deterministic rules would not be able to unambigiously decide
where to put them back. I agree that “put an end wherever you see a
dedent” is naive and wouldn’t work… but “put an end wherever you see
a dedent which isn’t followed by a keyword which extends the current
expression, such as elsif or rescue or ensure” might.

On May 20, 2009, at 3:50 PM, Gregory B. wrote:

get a
Is it subjective? Neither method is ambiguous. So no problem
-greg

You want me to have even more files and spend even more time folding
and unfolding things. And you assume I use a crummy editor and there
is a better one that magically makes a surprising number of wasted
lines irrelevant. I think you accidentally illustrated that extra
lines have a cost.

I can understand that people grow attached to certain styles. That’s
no big deal. I really like Ruby a lot. I like it better than
Python. I believe in most ways it’s a better language. But I’m
willing to admit that Python programs are generally shorter and that
is an advantage. It’s silly to pretend it isn’t.

Maybe it’s too hard to get rid of the redundancy. Or maybe we just
don’t know how yet. I’m not sure. But let us at least admit it’s
there. We should give people credit for trying to solve the problem.

On Wed, May 20, 2009 at 12:35 PM, J Haas [email protected] wrote:

On May 20, 8:51 am, Rick DeNatale [email protected] wrote:

This sort of structuring pieces of code stopped me from trying Python
seriously.

And I specifically addressed this in my OP. A lot of engineers who
haven’t done work in Python think that the idea of giving syntactical
significance to whitespace is a ridiculous idea. I used to be one of
them. Now I know better. Don’t knock it until you’ve tried it.

And you’re on a mailing list full of people who find that the Ruby-way
makes sense to them. Don’t knock it until you’ve tried it.

Wouldnt this be the easiest way to solve your problem?

The easiest way to solve my problem would be for me to use one of
the preprocessing scripts that impose Python-like indentation syntax
on Ruby. But that wouldn’t solve the larger problem, which is that
Ruby could be better than it is.

Or not. Beauty is in the eye of the beholder. Thinking that the new
(to you) language that you’re working with today would be better if
it were more like your old language is a big reason that so many
people write [perl|C|fortran] code in so many different languages.


thanks,
-pate

Don’t judge those who choose to sin differently than you do

Juan Z. wrote:

I’m willing to admit that Python programs are generally shorter

Are you sure of that? Care for a round of golf?