allowing braces around suites

  • Thread starter Kjetil Torgrim Homme
  • Start date
K

Kjetil Torgrim Homme

often when re-factoring code, I need to change the indent level of
some chunk of code. due to the lack of an end marker, my Emacs has to
use heuristics when re-indenting, and this will occasionally lead to
mistakes. of course this is really _my_ fault, not Emacs', but it's
annoying all the same.

a colleague uses #fi, #yrt etc. to mark the end of blocks, but I don't
find this satisfactory since neither Python nor Emacs has any
knowledge of what the magic comment means.

my suggestion is to allow braces to mark the suites. Python is still
strictly enforcing indentation, in fact, in some ways it's stricter
then before. code which uses braces and is wrongly re-indented will
always cause a syntax error during compilation.

code could look like this:

def appraise_insurance(rental_cars):
{
assert isinstance(rental_cars, (list, tuple))

for car in rental_cars:
{
if car.make == "Lamborghini":
{
car.insurance = 1000.00
}
elif car.make == "Lada":
{
car.insurance = 50.00
}
else:
{
car.insurance = 100.00
}
}
logger.debug("Insurance values updated")
}

now, I don't suggest to write code like that, that has far too much
air between actual codelines. I'd only add the braces where there is
a risk re-indentation changing the meaning of the program, like this:

def appraise_insurance(rental_cars):
assert isinstance(rental_cars, (list, tuple))

for car in rental_cars:
{
if car.make == "Lamborghini":
car.insurance = 1000.00
elif car.make == "Lada":
car.insurance = 50.00
else:
car.insurance = 100.00
}
logger.debug("Insurance values updated")

the single pair of braces is enough. there is now no risk of Emacs
including the debug line into the else branch unnoticed.

the patch to implement this is very simple and restricted to the
tokenizer. as it stands, it requires the braces to be placed as in
the above examples, you _can't_ write

if True: {
code
} else {
code
}

a single braces style improves readability and style consistency among
software projects. my patch does allow two styles, though: to reduce
line count you can put the else: on the same line as the closing
brace.

if True:
{
code
} else:
{
code
}

in both styles, the braces line up and IMHO this makes it easier to
identify where a medium sized block begins and ends.

there can be no code after an opening brace, but it's a good place to
put a comment, so in practice the number of added lines may not be so
large.


a small caveat: it breaks code which looks like this:

def test_varargs1(self):
"""some text"""
{}.has_key(0)

this function is taken from Lib/test/test_call.py, but the doc string
was added to make my patched Python reject it with a syntax error.
the problem is that a brace at the same indent level as the line above
will always mark the beginning of a new suite. I don't think such
code is widespread, but would be interested in hearing contrary
experiences. one fix for this issue is to have the parser tell the
tokenizer whether "a suite may follow" when it asks for the next
token, but I haven't persued writing such a patch.

a patch relative to Python 2.4a2 is available at

http://heim.ifi.uio.no/~kjetilho/hacks/braces-python-2.4a2.patch

what do you think? should I write a PEP?
 
M

Michael Sparks

Kjetil Torgrim Homme wrote:
...
what do you think? should I write a PEP?

It's more fun to ask python what it thinks:

michaels@pc474:~/Documents> python
Python 2.3.3 (#1, Apr 6 2004, 01:47:39)
[GCC 3.3.3 (SuSE Linux)] on linux2
Type "help", "copyright", "credits" or "license" for more information. ^^^^^^^^^^^^

I suspect you might have a hard time getting anywhere with this ;)

Regards,


Michael.
--
(e-mail address removed)
British Broadcasting Corporation, Research and Development
Kingswood Warren, Surrey KT20 6NP

This message (and any attachments) may contain personal views
which are not the views of the BBC unless specifically stated.
 
K

Kjetil Torgrim Homme

[Michael Sparks]:
I suspect you might have a hard time getting anywhere with this ;)

well, in the previous discussions I've read, the proponents of braces
want them as an alternative to strict indentation. that's not the
case here, so the code is still kept pythonic, IMO.
 
A

Andrew Durdin

Kjetil Torgrim Homme wrote:
...

The whole topic of explicit[*] end-of-block markers was brought up and
discussed at great length in May 1994:

http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&[email protected]

(I was looking at the old archives of c.l.py to try and find info on
the origins of triple-quoted strings and docstrings, both of which
were born around April 1994)

Regardless of history, it looks to me like your problem could be
better solved by modifying your emacs mode to consider whitespace more
correctly -- AFAICT there is no reason why it should ever pick up the
logging line in your example and indent it to the same level as the
else: block.
 
K

Kjetil Torgrim Homme

[Andrew Durdin]:
The whole topic of explicit[*] end-of-block markers was brought up
and discussed at great length in May 1994:

http://groups.google.com/[email protected]

thank you for the reference! I'm happy to see that Guido wasn't
strictly opposed to such a feature 10 years ago.
Regardless of history, it looks to me like your problem could be
better solved by modifying your emacs mode to consider whitespace
more correctly -- AFAICT there is no reason why it should ever
pick up the logging line in your example and indent it to the same
level as the else: block.

how can Emacs tell? if I press TAB and thus ask Emacs to re-indent
the line, that's what it will do. arguably, the correct fix is to
disable the "clever" re-indentation code of Emacs since it's too easy
to fool it, but this makes coding more awkward in other cases. it
also doesn't solve cut-n-paste errors.
 
W

Wolfram Kraus

Kjetil Torgrim Homme wrote:
[...]
how can Emacs tell? if I press TAB and thus ask Emacs to re-indent
the line, that's what it will do. arguably, the correct fix is to
disable the "clever" re-indentation code of Emacs since it's too easy
to fool it, but this makes coding more awkward in other cases. it
also doesn't solve cut-n-paste errors.

You can use C-c < or C-c > in Emacs to (de-)indent regions.

Wolfram
 
A

Anthony Baxter

thank you for the reference! I'm happy to see that Guido wasn't
strictly opposed to such a feature 10 years ago.

Regardless of what he thought back then, I think I can say with
absolutely no fear of contradiction that there is no chance in hell of
braces appearing in Python... ever.

If your tool gets something wrong, fix the tool, don't try and change
the language, just for the convenience of a broken tool.
 
I

Isaac To

Kjetil> how can Emacs tell? if I press TAB and thus ask Emacs to
Kjetil> re-indent the line, that's what it will do.

If the aim is simply to do a local change that is sufficient to deal
with the problem just in your computer, then the simplest answer might
be to use "pass": if your code contains

if t1 == t2:
t1 = t3
else:
t2 = t3
pass
t = t2

and you tab at the last line, Emacs won't try to indent the t=t2 line
further to after the pass line where it is impossible to execute.

If you want something that is done globally and everybody will use
it... not a chance.

Kjetil> arguably, the correct fix is to disable the "clever"
Kjetil> re-indentation code of Emacs since it's too easy to fool
Kjetil> it, but this makes coding more awkward in other cases.

The indent-region command of Emacs (M-C-\) is really disabled in
Python mode, I think it is done by nullifying the
indent-region-function. Anyway, reindent makes sense only when the
indentation does not constitute the meaning of a program and thus the
editor can freely change it. If indentation does mean something, it
doesn't make sense at all.

Kjetil> it also doesn't solve cut-n-paste errors.

Use C-c > and C-c < might work for you.

Regards,
Isaac.
 
A

Aaron Bingham

Wolfram said:
Kjetil Torgrim Homme wrote:
[...]
how can Emacs tell? if I press TAB and thus ask Emacs to re-indent
the line, that's what it will do. arguably, the correct fix is to
disable the "clever" re-indentation code of Emacs since it's too easy
to fool it, but this makes coding more awkward in other cases. it
also doesn't solve cut-n-paste errors.

You can use C-c < or C-c > in Emacs to (de-)indent regions.

Or C-M-\ to re-indent the region "correctly" with respect to its
context. This works far more reliably the using TAB to re-indent single
lines.

--
 
K

Kjetil Torgrim Homme

[Isaac To]:
If the aim is simply to do a local change that is sufficient to
deal with the problem just in your computer, then the simplest
answer might be to use "pass": if your code contains

if t1 == t2:
t1 = t3
else:
t2 = t3
pass
t = t2

and you tab at the last line, Emacs won't try to indent the t=t2
line further to after the pass line where it is impossible to
execute.

interesting idea, but Python won't discover inconsistencies. if only
an Emacs solution is sought, a "# end" convention is preferable since
it's more explicit. an explicit convention that Python recognises
would be even better.
If you want something that is done globally and everybody will use
it... not a chance.

I don't expect everybody to use it. miscellaneous projects where the
developers are comfortable with it might want to add it to their
coding standards.
 
I

Isaac To

^^^^^^^^^^^^^^^^^^^^^

At the second glance this statement is false. If you have a statement
after "pass" it actually will execute after the pass statement which
does nothing. So this is purely a convention of Emacs, making use of
a pattern that is never useful in programs anyway. (If you have such
pass statement and the next statement is in the same suite, you simply
would delete the pass statement.) The "return" statement also has the
same effect.

Kjetil> interesting idea, but Python won't discover
Kjetil> inconsistencies.

It's a Emacs convention, so it is of course the burden of Emacs to
detect inconsistency, i.e., a change of indentation is not indicated
by a "pass", "return", or a statement ending with ":" and perhaps some
comments after it. I imagine that it would be a very simple regular
expression to write if you really want to do it.

When Python is concerned and Emacs is not, Python only sees there is
indentation, and only indentation, to define the suites. And it is
also what people will perceive when they stare at the code. There is
nothing to be inconsistent with it.

Regards,
Isaac.
 
K

Kjetil Torgrim Homme

[Isaac To]:
When Python is concerned and Emacs is not, Python only sees there
is indentation, and only indentation, to define the suites. And
it is also what people will perceive when they stare at the code.
There is nothing to be inconsistent with it.

how long do you have to stare before spotting the bug?

db.update_name(person)
if is_student(person):
db.update_courses(person)
db.commit()

only students have their names updated. I wonder why.

real world examples have taken hours or days.
 
J

Jacek Generowicz

Kjetil Torgrim Homme said:
often when re-factoring code, I need to change the indent level of
some chunk of code. due to the lack of an end marker, my Emacs has
to use heuristics when re-indenting,

You've lost me here.

When you want to change the indent level of some chunk of Python code
in Emacs, you highlight the chunk of code and hit C-c > or C-c <.

I don't see any scope for heuristics here.
def appraise_insurance(rental_cars):
assert isinstance(rental_cars, (list, tuple))

for car in rental_cars:
{
if car.make == "Lamborghini":
car.insurance = 1000.00
elif car.make == "Lada":
car.insurance = 50.00
else:
car.insurance = 100.00
}
logger.debug("Insurance values updated")
the single pair of braces is enough. there is now no risk of Emacs
including the debug line into the else branch unnoticed.

How about

for car in rental_cars:
if car.make == "Lamborghini":
car.insurance = 1000.00
elif car.make == "Lada":
car.insurance = 50.00
else:
car.insurance = 100.00
pass
pass
logger.debug("Insurance values updated")

?

Hmm ... not pretty, but at least it doesn't PERLize the language.
what do you think? should I write a PEP?

Yes please write a PEP. It will be formally rejected, thereby forming
an excellent reference to which we might direct people who come up
with similar ideas.
 
T

Thomas Heller

Aaron Bingham said:
Wolfram said:
Kjetil Torgrim Homme wrote:
[...]
how can Emacs tell? if I press TAB and thus ask Emacs to re-indent
the line, that's what it will do. arguably, the correct fix is to
disable the "clever" re-indentation code of Emacs since it's too easy
to fool it, but this makes coding more awkward in other cases. it
also doesn't solve cut-n-paste errors.

You can use C-c < or C-c > in Emacs to (de-)indent regions.

Or C-M-\ to re-indent the region "correctly" with respect to its
context. This works far more reliably the using TAB to re-indent
single lines.

How do you enter that on a german keyboard?

Thomas
 
V

Ville Vainio

Kjetil> what do you think? should I write a PEP?

No - you should see C:\Python23\Tools\Scripts\pindent.py (if you are
on windos) or snatch the file from the source distribution.
 
A

Antoon Pardon

Op 2004-08-27 said:
Regardless of what he thought back then, I think I can say with
absolutely no fear of contradiction that there is no chance in hell of
braces appearing in Python... ever.

If your tool gets something wrong, fix the tool, don't try and change
the language, just for the convenience of a broken tool.

Well people do make mistakes and it would be helpfull if the language
provides some feautures to help in repairing those mistakes.

It has happend that through some faulty manipulations code that
came after a loop became indented at the same level as the loop.
Because python has no end-markers that meant it wasn't obvious
to spot where the loop was supposed to stop and from where I
had to start deindenting the code.

Now of course I can remedy this situation by using comments
like #end, #if etc. That will make it obvious to correct such
mistakes. However I think one could argue that providing such
endmarkers helps readability as much as indenting code does
and since that is the principal argument for the enforced
indentation, one could consider the case for endmarkers.
 
T

Thomas Heller

[...]
CTRL-ALT-ALTGR-ß

Not for me - it only beeps. Well, maybe because I'm using XEmacs on win2k.

Do you mean the function py-indent-region? Apparently this is bound to
C-c tab or C-c C-i.

Thomas
 
K

Kjetil Torgrim Homme

[Jacek Generowicz]:
How about

for car in rental_cars:
if car.make == "Lamborghini":
car.insurance = 1000.00
elif car.make == "Lada":
car.insurance = 50.00
else:
car.insurance = 100.00
pass
pass
logger.debug("Insurance values updated")

?

Hmm ... not pretty, but at least it doesn't PERLize the language.

"pass" is a no-op, and should only be used when a suite is required,
but the suite should do nothing. you're proposing a convention saying

''if "pass" appears in a suite which also contains other
expressions, the "pass" signals the end of the suite''

that's a hack, and IMHO not worthy of a Python program. not even Perl
has anything like that, AFAIK.
 

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,990
Messages
2,570,211
Members
46,796
Latest member
SteveBreed

Latest Threads

Top