Does Python 'enable' poke and hope programming?


C

CM

(My subject line is meant to be tongue and cheek inflammatory)

I've been thinking about why programming for me often feels like ice skating uphill. I think part of the problem, maybe the biggest part, is what nowstrikes me as a Very Bad Habit, which is "poke and hope" (trial and error)programming (of several names this page provided, I kind of like that one):

http://en.wikipedia.org/wiki/Programming_by_permutation

It seems that if I can make a change to the code and then immediately test it by running the Python interpreter and finding out, in a few seconds, if it worked, I am going to be *much* more likely to use this trial-and-error approach than if I had to use a compiled language, since compiling takes solong. E.g. "Oh, that doesn't work? Maybe if I add this...no. OK, what about if I increment that? No...OK, wait, maybe this...AH! That worked." (obviously it is not quite that uninformed all the time).

Instead, with a compiled language, because of the pain of having to wait for the newest version to compile, one would be encouraged to get the mechanism of how something works *clear* and robustly represented in one's mind (or on scrap paper/notes document) prior to testing through compiling and running.

Basically this amounts to: with an interpreted language (so of course thisis not really just about Python--I just think in terms of Python), it's easier to be mentally lazy. But, ironically, being lazy winds up creating *way* more work ultimately, since one winds up programming in this terribly inefficient way, and progress proceeds at an, at times, evolutionary (slow!)pace.

And of course I am not really blaming it on Python or any interpreted language; I am blaming it fully on my own lame habits and attitude.

I'm sick of this in my own work, and want to avoid this trap as much as I can from now on.

Thoughts?
 
Ad

Advertisements

N

Neil Cerutti

http://en.wikipedia.org/wiki/Programming_by_permutation

It seems that if I can make a change to the code and then
immediately test it by running the Python interpreter and
finding out, in a few seconds, if it worked, I am going to be
*much* more likely to use this trial-and-error approach than if
I had to use a compiled language, since compiling takes so
long. E.g. "Oh, that doesn't work? Maybe if I add this...no.
OK, what about if I increment that? No...OK, wait, maybe
this...AH! That worked." (obviously it is not quite that
uninformed all the time).

Instead, with a compiled language, because of the pain of
having to wait for the newest version to compile, one would be
encouraged to get the mechanism of how something works *clear*
and robustly represented in one's mind (or on scrap paper/notes
document) prior to testing through compiling and running.

With a big project running all tests for a Python program could
be just as time consuming. If I were using a compiler for my
programs compiling would still be virtually instantaneous.
I'm sick of this in my own work, and want to avoid this trap as
much as I can from now on.

When I "know", for example. that it's an off-by-one error, I'm
pretty guilty of just making the change and re-running the test.
I think it's cool! If my test sucks, then I wasted my time, of
course.

As I said, I disagree that the speed of using an interpreter is
the main issue. Changing certain things, even big things, in a
Python program is often much easier than changing something in ,
say, a C program, due to Duck-Typing and dynamic typing. So
experimentation is easier thanks to more maleable code.
 
C

Chris Angelico

It seems that if I can make a change to the code and then immediately test it by running the Python interpreter and finding out, in a few seconds, if it worked, I am going to be *much* more likely to use this trial-and-error approach than if I had to use a compiled language, since compiling takes so long. E.g. "Oh, that doesn't work? Maybe if I add this...no. OK, whatabout if I increment that? No...OK, wait, maybe this...AH! That worked."(obviously it is not quite that uninformed all the time).


I would say that, often, that's a fine way to do things. With two very
similar languages I work with (Python and Pike), there's a slight
difference in the interpretation of a range subscript:

Pike v7.8 release 700 running Hilfe v3.5 (Incremental Pike Frontend)
"Hello, world!"[..5]; (1) Result: "Hello,"
"Hello, world!"[5..];
(2) Result: ", world!"

Python 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:55:48) [MSC v.1600
32 bit (Intel)] on win32
"Hello, world!"[:5] 'Hello'
"Hello, world!"[5:]
', world!'

Python counts the boundaries between characters, Pike counts the
characters themselves. So using the same number on different sides of
the colon yields the exact same string in Python, but in Pike, both
strings contain the indexed character. Both ways make sense, and the
easiest way to make sure I haven't mucked something up - in either
language - is to try it.

ChrisA
 
D

Dave Angel

CM wrote:

what now strikes me as a Very Bad Habit, which is "poke and hope"
(trial and error) programming (of several names this page provided, I kind of like that one):

I recall when a "compile" took up to two days, before we got the punched
paper tape to begin testing. If we wanted to "poke", it was done in
hex.

Once we got a local assembler/linker up and working, and
(incremental) turnarounds were under 5 minutes, we thought we were in
heaven. But the discipline of having to think it through was very good
for us, in the long run.
 
S

Sam Whitehead

I find myself doing this a lot with libraries whose documentation encourages an understanding based on intuition, rather than one based on formal concepts. When doing more 'pure' stuff with mostly the standard library, not somuch.

Most imperative languages let their users get kind of loose with data design, but I don't feel like Python is especially bad in this regard. Mostly I feel like it depends on how well the programmer understands the software they're working with. And that sense, Python tries to help by encouraging readability.

In a sense, you could see almost all computer programming as "poke and hope", though. The variation lies in the size of the poke and the uncertainty of the hope.
 
V

Vito De Tullio

CM said:
Basically this amounts to: with an interpreted language (so of course
this is not really just about Python--I just think in terms of Python),
it's easier to be mentally lazy. But, ironically, being lazy winds up
creating *way* more work ultimately, since one winds up programming in
this terribly inefficient way, and progress proceeds at an, at times,
evolutionary (slow!) pace.

you have found repl are cool :D
 
Ad

Advertisements

W

Wayne Werner

(My subject line is meant to be tongue and cheek inflammatory)

I've been thinking about why programming for me often feels like ice skating uphill. I think part of the problem, maybe the biggest part, is what now strikes me as a Very Bad Habit, which is "poke and hope" (trial and error) programming (of several names this page provided, I kind of like that one):

http://en.wikipedia.org/wiki/Programming_by_permutation

It seems that if I can make a change to the code and then immediately test it by running the Python interpreter and finding out, in a few seconds, if it worked, I am going to be *much* more likely to use this trial-and-error approach than if I had to use a compiled language, since compiling takes so long. E.g. "Oh, that doesn't work? Maybe if I add this...no. OK, what about if I increment that? No...OK, wait, maybe this...AH! That worked." (obviously it is not quite that uninformed all the time).

Instead, with a compiled language, because of the pain of having to wait for the newest version to compile, one would be encouraged to get the mechanism of how something works *clear* and robustly represented in one's mind (or on scrap paper/notes document) prior to testing through compiling and running.

Basically this amounts to: with an interpreted language (so of course this is not really just about Python--I just think in terms of Python), it's easier to be mentally lazy. But, ironically, being lazy winds up creating *way* more work ultimately, since one winds up programming in this terribly inefficient way, and progress proceeds at an, at times, evolutionary (slow!) pace.

And of course I am not really blaming it on Python or any interpreted language; I am blaming it fully on my own lame habits and attitude.

I'm sick of this in my own work, and want to avoid this trap as much as I can from now on.

Thoughts?


I see that many others have had thoughts already - but rather than take the
time to read their responses and either find out that they said the same thing
(oops, sorry!) or become influenced by their arguments, I feel like I should
respond to this with a clean slate.


I don't think that Python enables the "poke and hope" style programming (I like
the name!) any more than a compiled language does - if you're doing it right.

Example: My brother had a kid in his C++ class that would go about randomly
flipping >, <, <=, >= signs until he got the behavior that he wanted. There was
no mental effort of thinking about the problem or applying the scientific
method - i.e. form a hypothesis, test the hypothesis, check results. My
experience is that people who go throughout their programming careers without
this attitude will do it whether it requires several seconds (or minutes) of
compile time or not. Whether or not it's a conscious choice I don't know - at
least in your case you seem to desire to make a conscious choice in the
direction of "wait a minute, this is a stupid way to program".

Though "poke and hope" is headed in the right direction, I think it's a bit
naive and misses the very essential nature of the better (best?) method -
formulation of a /real/ hypothesis. For instance "I think my program will work"
is a hypothesis of exactly the same quality of, "When I turn on my water
faucet, it will rain." Of course the smaller the application, the more valid
the original hypothesis. For instance, the "poke and hope" programmer might
write this program:

x = 3
if x > 3:
print "x is less than 3"
else:
print "x is greater than 3"

And then of course make the weak hypothesis "if I change my > to < then maybe
my program will work" - or "if I change my x to 5 then maybe my program will
work".


The problem is that these are really just random guesses - flips of the coin
that eventually might produce a correct result - but only because of the
monkeys[1].

What you really want is to actually understand cause and effect at a more
fundamental level (in programming) than what you may currently enjoy. And this
is in fact something that, while makes it easier for the "poke and hope", also
provides a much more enjoyable laboratory experience for the initiated. And
when you combine that with the REPL (interactive interpreter) you get an
embarassingly powerful laboratory in which to experiment to your heart's
delight.

For instance, say you want to really understand the previous example. You could
do something like so:
True


And *this* type of "poke and hope" *is* actually valuable. This is where
understanding is formed, and high-quality developers are forged. At your
fingertips you begin to see "A hah! so *that's what this does!" You are free to
explore and play and understand the rules of the system. And you can build on
the previous experiments:

... print("Hello?") #single space indentation for the interpeter
...... print('True?')
...
True?... print('x > 3')
...
x > 3... print('x < 3')
x < 3


With this understanding you can then say something like, "If I write a program
that checks to see `if x < 3` then print 'x < 3', and `if x > 3` print 'x > 3'
and `if x == 3` then print out 'x is 3', that should do those things correctly"
- which you then test by writing the (again naive) program:


x = 5
if x > 3:
print('x > 3')
if x < 3:
print('x < 3')
if x == 3:
print('x is 3!')


This is still not the ideal program - obviously you can use elif/else - but
the style of the program is beside the point. We really care about the thought
process that went into (ultimately) developing the correct solution.
Experimentation is OK - that's how we learn. But we need to direct our
experiments and /use what we learned/ when formulating our hypothesis. when
this happens we evolve beyond the "poke and hope" into the inquisitive,
intelligent programmers that we all should be. Not merely fumbling around in
the dark, flailing for the correct answers, but finding a problem and apply our
understanding of the way the world (maybe just the digital world of 1's and
0's) works to create the solution. The solution that works[2].


At least that's my 2¢
-W

[1]: You know, the ones with typewriters.
[2]: Turns out there are several values for 'works'. If the computer is the
only one that sees it, then 'produces the correct solution' is the most
important. But if you have people coming 'round to
change/update/extend/enhance, the obviously a system that's easier to maintain
is a worthwhile trade-off. After all, people are the more valuble resource -
computers just help us make better use of it.
 
C

CM

Wayne, thanks for your thoughts.

I am all for the scientific method--in understanding the natural world, which doesn't come with a manual. But Python is an artificial system designedby mere people (as well as Guido), and, as such, does have a manual. Ideally, there should be very little need for experimentation and "hypotheses".That said, yes, when learning the language a little experimentation alongthe way is fine, and error messages Python throws back to you or unexpected results can and should be a form of real time instruction.

But what I meant is that if one is writing a program, there is a way to **know**--without experimentation--what a particular set of code is going to do. This is often cognitively demanding work, but it is possible. And my point is that it is, in the end, far more efficient to be disciplined and dothat work rather than try to take shortcuts by simply trying a few things until one of them works.

In sum: experimentation is for when you don't know what you're doing and there is no manual; but, after the initial learning time, you *should* know what you're doing and you should have the manual handy, and therefore the time for experimentation is largely over.
 
C

Chris Angelico

In sum: experimentation is for when you don't know what you're doing andthere is no manual; but, after the initial learning time, you *should* know what you're doing and you should have the manual handy, and therefore thetime for experimentation is largely over.


Yet with fast turnaround interactive languages, the interpreter IS
part of the manual. Keeping IDLE (I prefer it to command-line Python
on Windows, as the latter lacks GNU readline ergo no tab completion
etc) handy is at least as useful as keeping the manual up.

ChrisA
 
Ad

Advertisements

E

Ethan Furman

But what I meant is that if one is writing a program, there is a way
to **know**--without experimentation--what a particular set of code
is going to do.

Even when you /know/, experimenting is still good for two other purposes:

- check that what you know is so

- check that the interpreter behaves consistently with the docs

But yes, I otherwise agree with you.
 

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

Top