# [Tutor] Losing the expressiveness ofC'sfor-statement?/RESENDwith example

Michael Sparks ms at cerenity.org
Fri Aug 10 19:55:08 CEST 2007

Stephen,

I've come into this thread late, but it looks like you're lamenting the fact
you can stipulate complex iterations on a single line, which can be nice. I'd
not really missed this in several years of programming with python.

However, Your post is interesting because it raises a point I've personally
not considered before.

for (node=start; value<threshold && node!=end; node=node->next) { ... }
for (i=30000; i>0; i=i/2) { ... }

The argument you got back is that this is just syntactic sugar for logic
along the lines of:

node=start;
while value<threshold && node!=end:
...
node=node->next

Which of course is true. However simply saying that does miss the fact
that it is syntactic sugar with a purpose. Syntactic sugar is generally added
for one of two reasons - speed of coding, or clarity of coding. In this case
it can be argued it does both, since it spells out the iterator algorithm
clearly on a single line.

Specifically you can look at one line and see the loop logic. This is nowhere
near as clear with this form:
node=start;

while value<threshold && node!=end:
...
last = node # hypothetical confuddling line
node=node->next

And its certainly not on one line.

If you still want to spell out the iteration in one location, then you're
right you do have to use a generator. However the fact that you can put a
def anyway means you can do this:

start = getNodesFromSomewhere()
def traverseNodes(start):
node = start
yield node
while node.next:
node = node.next
yield node
for node in traverseNodes(start):
...

Similarly you can do this:
def bisectdown(i=30000):
while i >0:
yield i
i = i/2
for node in bisectdown(30000):
...

That said, I agree that its not as nice perhaps as C's compact one liner for
each of these.

HOWEVER, you can rebuild C's version: (or something close)

import compiler
def cfor(iter_name, args,locals):
Y=[x.strip().rstrip() for x in args.split(";")]
Y[0] = compiler.compile(Y[0], "__main__.py", "exec")
Y[1] = compiler.compile(Y[1], "__main__.py", "eval")
Y[2] = compiler.compile(Y[2], "__main__.py", "exec")
Y.append( compiler.compile(iter_name, "__main__.py", "eval"))
exec(Y[0],locals,locals)
while eval(Y[1],locals,locals):
yield eval(Y[3],locals,locals)
exec(Y[2],locals,locals)

You can then use this as follows:
max = 10
for i in cfor("i", "i=30000; i>max; i=i/2",locals()):
print i

And also:
start = getNodesFromSomewhere()
for node in cfor("n", "n=start; n.next is not None; n = node.next",
locals()):
...

That's potentially quite useful. Yes there's a little cruft there (locals()),
but its not hideously inefficient either because I've made sure we compile the
code fragments and run those.

Personally I think its not a huge loss, but if you do, then you can always
reuse this cfor iterator if you like.

I disagree though regarding the idea that C's for syntax is a universal
syntax. It isn't. It's a commonly understood syntax due to C derived
languages (C/C++/Java), but far from universal. I've had to learn many
different "for" syntaxes over many years for different languages.

Even then where a C-type loop is availabe, it isn't always idiomatic to use
it. For example perl (which does have a C-type for loop) idiomatically uses
foreach extensively. And you also get *very* different iterative behaviour
in ruby.

Different languages have different concepts. Just because you can write one
language like another doesn't mean you should. That said, given that maxim,
it sounds like your beef with more with docs rather than the lack of the
construct, asking "is this a problem normally", to which the answer is most
definitely not, "what do people normally do", to which you have numerous
replies - people either create an iterator (as you often would in C++ and
Java) or use a while loop.

As for rudeness, bear in mind that text is a naturally harsh medium, and
also cultural norms are very different for different posters. One man's
polite behaviour is another man's gravest insult. No one means to be rude,
so it's worth remembering that. (And yes, I know, merely saying that can
be considered rude in itself in some cultures :-)

You found people rude, they found you rude. None of you intended to be,
and probably weren't from your own perspectives, that's what really matters.

Michael.