python code with indention

B

Brian van den Broek

Xah Lee said unto the world upon 2005-02-07 14:39:
is it possible to write python code without any indentation?

Xah
(e-mail address removed)
http://xahlee.org/PageTwo_dir/more.html

print "It would seem it is indeed possible."
print
print "Note: although I know this, I don't consider myself an "
print "accomplished Pythoner."
print
print "In the face of that, "
print "I know enough not to post Python 'tutorials'."

Best,

Brian vdB
 
D

Dan Perl

Xah Lee said:
is it possible to write python code without any indentation?

I read just today in a tutorial that "Python on the other hand, does not
even allow changes in code's indentation". Maybe the author of that
tutorial can help?
 
C

Christopher De Vries

I read just today in a tutorial that "Python on the other hand, does not
even allow changes in code's indentation". Maybe the author of that
tutorial can help?

And to think he posted both on the same day. It'd be funny if it weren't so
sad... actually it's just funny.

Anyway, in response to the question see
http://docs.python.org/ref/indentation.html#l2h-9

A sequence of statements without any looping or function or class definitions
can probably be done without any indenting.

Chris
 
J

Jeremy Bowers

It's possible to implement a turing machine with a single list
comprehension. No indentation needed.

I had to think about it, it's an interesting, and I'm going to tentatively
disagree, because of the statement/expression dichotomy. "Tentatively"
because if somebody can answer these objections than I will happily change
my mind :)

I can't figure out how to write a TM in a Python List Comprehension
without one of either "variable binding" (so we can store the last symbol
list and manipulate it in the next iteration) or "recursive function" (to
express the whole tape as a recursive function), both of which require
statements. I can figure out how to write a single state transition, but
in a single LC I can't figure out how to feed the new state into the next
iteration; the previous values generated in the LC are, to my knowledge,
not accessible to the LC as it is running. (If they are, I *think* that
would indeed be enough.)

I'm sure Haskell could do both, being a functional language, and I am
satisfied that it is probably possible in that language, as long as you
are resigned to creating a wasted list (which may not even matter in
Haskell). But I think you're screwed in Python with an LC.

However, hack hack hack, I think you could do this in Python 2.4 with a
*generator* comprehension and a couple of supporting lines of non-indented
code:

Python 2.4 (#1, Jan 2 2005, 22:17:50)
[GCC 3.4.3 (Gentoo Linux 3.4.3, ssp-3.4.3-0, pie-8.7.6.6)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
import sys
this = sys.modules[__name__]
magicGenerator = (getattr(this, "results")[-1] + 1 for x in range(5))
results = [0] # you have to prime the state here
results.extend(magicGenerator)
results [0, 1, 2, 3, 4, 5]

Now you *can* get at the previous state and write a state-transition
expression in perfectly legal Python.

What do you know, generator comprehensions are Turing Complete and list
comprehensions aren't. I wouldn't have expected that.

People caught using this technique in real code will be caught and forced
to code in Intercal for the rest of their lives.
 
J

Jeremy Bowers

How about:
... f = [1]
... f.extend(i*j for i,j in it.izip(xrange(1,1+n), f))
... return f
...
fact_ge(10) [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800]

as a "stateful" genexp?

That's not a generator expression, that's a generator function. Nobody
contests they can reference earlier states, that's most of their point :)

For context, we're trying to build Turing Completeness into Python without
indentation. I bailed out of a Xah Lee thread because people have
probably killed it :) and this is entirely unrelated by now, except in
the vague sense he started with an (I'm sure entirely accidentally)
thought-provoking question.
 
J

Jeremy Bowers

I see no difference between LCs and GEs in this respect:
... f = [1]
... f.extend(i*j for i,j in it.izip(xrange(1,1+n), f))
... return f
...... f = [1]
... [f.append(i*j) for i,j in it.izip(xrange(1,1+n), f)]
... return f

The comments in my other post still hold true w.r.t. these not being just
LCs or genexps, but you have a point here. Allowing an external list will
give you the storage you need even for a LC.

OK then, I still don't quite see how you can build a Turing Machine in one
LC, but an LC and one preceding list assignment should be possible,
although the resulting list from the LC is garbage; the preceding list
will have the actual state data.
 
J

John Roth

Xah Lee said:
is it possible to write python code without any indentation?

Xah

Depends on what you mean by "python code."
If you mean using the full facilities of the language,
then the answer is clearly no - indentation is not
optional.

You can, of course, write a silly little inline script without
any control structures that will all line up at the left
margain. So what?

John Roth
 
B

Bernhard Herzog

Nick Vargish said:
Not if Turing-completeness is something you desire.

It's possible to implement a turing machine with a single list
comprehension. No indentation needed.

Bernhard
 
M

Michael Spencer

Jeremy said:
I can't figure out how to write a TM in a Python List Comprehension
without one of either "variable binding" (so we can store the last symbol
list and manipulate it in the next iteration) or "recursive function" (to
express the whole tape as a recursive function), both of which require
statements. I can figure out how to write a single state transition, but
in a single LC I can't figure out how to feed the new state into the next
iteration; the previous values generated in the LC are, to my knowledge,
not accessible to the LC as it is running. (If they are, I *think* that
would indeed be enough.)
How about:
.... f = [1]
.... f.extend(i*j for i,j in it.izip(xrange(1,1+n), f))
.... return f
....
>>> fact_ge(10) [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800]
>>>

as a "stateful" genexp?


Michael
 
M

Michael Spencer

Now you *can* get at the previous state and write a state-transition
expression in perfectly legal Python.

What do you know, generator comprehensions are Turing Complete and list
comprehensions aren't. I wouldn't have expected that.
I see no difference between LCs and GEs in this respect:
... f = [1]
... f.extend(i*j for i,j in it.izip(xrange(1,1+n), f))
... return f
... ... f = [1]
... [f.append(i*j) for i,j in it.izip(xrange(1,1+n), f)]
... return f
...
...
>>> fact_ge(10) [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800]
>>> fact_lc(10)
[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800]

Michael
 
M

Michael Spencer

Jeremy said:
That's not a generator expression, that's a generator function. Nobody
contests they can reference earlier states, that's most of their point :)


Are you sure?

I just wrote my examples in functions to label them

Here's your example with this method:
>>> import itertools as it
>>> results = [0]
>>> magicGenerator = (i+1 for i,lastresult in it.izip(xrange(5),results))
>>> results.extend(magicGenerator)
>>> results [0, 1, 2, 3, 4, 5]
>>>
> For context, we're trying to build Turing Completeness into Python without
> indentation. I bailed out of a Xah Lee thread because people have
> probably killed it :)
Didn't see it, but this looked interesting - presumably your point
and this is entirely unrelated by now, except in
> the vague sense he started with an (I'm sure entirely accidentally)
> thought-provoking question.

Michael
 
M

Michael Spencer

Jeremy said:
OK then, I still don't quite see how you can build a Turing Machine in one
LC, but an LC and one preceding list assignment should be possible,
although the resulting list from the LC is garbage;

Not necessarily garbage - could be anything, say a copy of the results:
>>> results = [0]
>>> [(results.append(lastresult+1) or lastresult) for i, lastresult in
it.izip(xrange(5),results)]
[0, 1, 2, 3, 4]
I don't think the assignment is avoidable though.

I should clarify a point I made earlier
I see no difference between LCs and GEs in this respect:

What I meant was that both LCs and GEs can reference their prior state in the
same way. Of course, there is an important difference in that the LC returns
its list as soon as it is executed whereas the executing the genexp returns an
iterator that can delay the evaluation of all but the outer loop until its
next() is called. This makes a genexp equivalent to (at least some) functions,
and perhaps that was part of your point that I missed.

Michael
 
B

Bernhard Herzog

Jeremy Bowers said:
I had to think about it, it's an interesting, and I'm going to tentatively
disagree, because of the statement/expression dichotomy. "Tentatively"
because if somebody can answer these objections than I will happily change
my mind :)


Here's an implementation of a turing machine simulator I hacked up a
while ago. For readability's sake, it's a function definition with a
doc-string, but the heart of it is a single list comprehension which
could be written without indentation:


def listcomp_turing(M, T, initial_state = 0):
"""Run the turing machine M on the tape T.

The tape T should be a dictionary mapping head positions to the
value on the tape at that position. Valid values on the tape are 0
and 1. Empty positions have the value 0. The initial head position
is 0.

The turing machine M should be a sequence of state pairs. The state
of the machine is used as an index into that sequence and thus
should be in range(len(M)). Each state pair is a pair of
(write_symbol, head_direction, next_state) triples, one for each of
the possible values on the tape at the current head position. The
initial state is given by the optional parameter initial_state. If
the next state is None, the machine stops. The direction may be
either -1 or 1 meaning left and right respectively. The function
does not enforce this limitation but with other values the machine
is not a turing machine anymore.

The return value is T.
"""
[x for L in [[[initial_state, 0]]]
for state, pos in L
if state is not None
and (L.append([M[state][T.get(pos, 0)][2],
pos + M[state][T.get(pos, 0)][1]])
or T.__setitem__(pos, M[state][T.get(pos, 0)][0]))]
return T



For an example, lets take the one from wikipedia's article on turing
machines:


The following Turing machine has an alphabet {'0', '1'}, with 0
being the blank symbol. It expects a series of 1's on the tape, with
the head initially on the leftmost 1, and doubles the 1's with a 0
in between, i.e., "111" becomes "1110111". The set of states is {s1,
s2, s3, s4, s5} and the start state is s1. The action table is as
follows.

Old Read Wr. New Old Read Wr. New
St. Sym. Sym. Mv. St. St. Sym. Sym. Mv. St.
- - - - - - - - - - - - - - - - - - - - - - - -
s1 1 -> 0 R s2 s4 1 -> 1 L s4
s2 1 -> 1 R s2 s4 0 -> 0 L s5
s2 0 -> 0 R s3 s5 1 -> 1 L s5
s3 0 -> 1 L s4 s5 0 -> 1 R s1
s3 1 -> 1 R s3


The listcomp_turing call with a tape containing "11" would be

listcomp_turing([((0, +1, None), (0, +1, 1)),
((0, +1, 2), (1, +1, 1)),
((1, -1, 3), (1, +1, 2)),
((0, -1, 4), (1, -1, 3)),
((1, +1, 0), (1, -1, 4))],
{0:1, 1:1})

which produces a result tape of

{0: 1, 1: 1, 2: 0, 3: 1, 4: 1}


Bernhard
 
T

Timo Virkkala

Xah said:
is it possible to write python code without any indentation?

1) Why in the name of Xah Lee would you even want to?
2) If you need to ask questions this simple, are you sure you are the right
person to write tutorials?
3) Do you even read the replies you get?
 
J

Jeremy Bowers

[x for L in [[[initial_state, 0]]]
for state, pos in L
if state is not None
and (L.append([M[state][T.get(pos, 0)][2],
pos + M[state][T.get(pos, 0)][1]])
or T.__setitem__(pos, M[state][T.get(pos, 0)][0]))]
return T

I stand corrected!

Thanks for posting it; I wasn't going to ask anyone to produce one, but if
you had one lying around, that's great.

Nice job!
 
S

Steve Holden

Timo said:
1) Why in the name of Xah Lee would you even want to?
2) If you need to ask questions this simple, are you sure you are the
right person to write tutorials?
3) Do you even read the replies you get?
Surely by now it's obvious that Xah Lee is an output-only device. Please
do not feed the troll.

regards
Steve
 
M

Michael Spencer

Bernhard Herzog wrote:
.....
a Turing Machine in one line plus assignments - nice! Turns out that pypy is more
verbose than strictly necessary ;-)
....


BTW, I realized that it is indeed possible for a LC to maintain its own state
without being passed an external mutable. The trick is to use itertools.repeat
to return the same mutable object on each iteration.

So, here's factorial in one line:
# state refers to list of state history - it is initialized to [1]
# on any iteration, the previous state is in state[-1]
# the expression also uses the trick of list.append() => None
# to both update the state, and return the last state
>>> [state.append(state[-1] * symbol) or state[-1]
.... for symbol, state in it.izip(range(1,10),it.repeat([1]))
.... ]
[1, 2, 6, 24, 120, 720, 5040, 40320, 362880]
Now, who was claiming that 'reduce' was opaque?

Michael ;-)
 

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,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top