PyWart: The problem with "print"

R

Russ P.

This comment shows me that you don't understand the difference between

names, objects, and variables. May sound like a minor quibble, but

there're actually major differences between binding names to objects

(which is what python does) and variables (which is what languages like

C have). It's very clear Rick does not have an understanding of this

either.

My comment shows you nothing about what I understand about names, objects, and variables. You have chosen to question my understanding apparently because my point bothered you but you don't have a good reply. Then you link mewith Rick for good measure. That's two ad hominems in three sentences.
 
M

Michael Torrie

My comment shows you nothing about what I understand about names,
objects, and variables.

Yes that probably is true.
You have chosen to question my understanding apparently because my
point bothered you but you don't have a good reply. Then you link me
with Rick for good measure. That's two ad hominems in three
sentences.

Your statement didn't bother me. I just felt, perhaps erroneously, that
such a comment needs clarification. We get into trouble in python when
we get caught up in treating python names exactly like variables and
blame it on the lack of static typing. In uni we looked at various
means of dealing with the name covering/hiding issue including renaming
or requiring that each binding be a unique name (meaning the second x =
"hello word" statement would be a runtime error). Anyway, I got a bit
distracted by your example of using the same name twice with different
objects when the real issue that can cause pain is function call
parameter expectation.

My apologies for linking you to Rick. You're right that was an
ad-hominem attack, though I didn't intend that!
 
S

Steven D'Aprano

So Python would have been a better choice? Yeah, right.

Putting issues of efficiency aside, yes, it probably would have. Had the
programmers not been so sure that the compiler was protecting them from
bugs, a misplaced hope if there ever was one, they might have written
some tests and noticed that their simulated rocket launch ended up going
boom instead of into orbit.

I'm referring to the first test flight of the Ariane 5, which failed due
to a software bug. There was no actual satellite on this flight. The
failure Mark refers to was due to a leak in coolant pipes, which of
course is a hardware problem and cannot be blamed on the software.

http://en.wikipedia.org/wiki/Ariane_5#Notable_launches


If you know
anything about that rocket mishap, you should know that Ada was not the
source of the problem. Ada won't keep airplane wings from breaking
either, by the way. It's not magic.

Again, referring to the infamous 64-bit float to 16-bit integer bug, Ada
may not have been the *source* of the problem, but neither did it prevent
it.

What prevents bugs is the skill of the people writing the code, not the
compiler. Compile-time static type checking is merely a tool, which has
costs and benefits. It is ludicrous to think that any one single tool, or
the lack of that tool, will make all the difference between working code
and non-working code.

Static type-checking is no better, or worse, for "critical code" than
dynamic type-checking. One language chooses to deal with some errors at
compile-time, others deal with them at run-time. Either way, the
programmer has to deal with them in some way.

A static type system forces you to deal with a limited subset of errors,
"type errors", in one way only: by removing any execution paths in the
software which would assign data of type X to a variable of type Y. For
reasons of machine efficiency, that is often a good was to deal with such
errors. But a dynamic type system makes different trade-offs.

And of course, type errors are such a vanishingly small subset of all the
possible errors that might be made that, frankly, the difference in code
quality between those with static typing and those without is essentially
indistinguishable. There's no evidence that code written in static typed
languages is less buggy than code written in dynamic languages.
 
S

Steven D'Aprano

I'm not an Ada guy, but Ada advocates claim that it reduces development
time by half in the long run compared to C and C++ due to reduced
debugging time and simpler maintenance.

They may be right. Far too many people think that C and C++ are "best of
breed" in static languages. They aren't.

Then again, I think Java people make a similar claim.

Java people would take credit for the sun coming up if they could :)

As for Python, my experience with it is that, as
your application grows, you start getting confused about what the
argument types are or are supposed to be.

Whereas people never get confused about the arguments in static typed
languages?

The only difference is whether the compiler tells you that you've passed
the wrong type, or your unit test tells you that you've passed the wrong
type. What, you don't have unit tests? Then how do you know that the code
does the right thing when passed data of the right type? Adding an extra
couple of unit tests is not that big a burden.

Of course, if there was a way to automate that, why wouldn't you take
advantage of it? Python currently has no standard way of doing such
automated type tests, and probably won't ever get one. A static typed
language gives you those tests for free, but in many languages at the
cost that you probably end up spending more time fighting to satisfy the
compiler than you save by not writing unit tests.
 
C

Chris Angelico

Whereas people never get confused about the arguments in static typed
languages?

The only difference is whether the compiler tells you that you've passed
the wrong type, or your unit test tells you that you've passed the wrong
type. What, you don't have unit tests? Then how do you know that the code
does the right thing when passed data of the right type? Adding an extra
couple of unit tests is not that big a burden.

The valid type(s) for an argument can be divided into two categories:
Those the compiler can check for, and those the compiler can't check
for. Some languages have more in the first category than others, but
what compiler can prove that a string is an
HTML-special-characters-escaped string? In a very few languages, the
compiler can insist that an integer be between 7 and 30, but there'll
always be some things you can't demonstrate with a function signature.

That said, though, I do like being able to make at least *some*
declaration there. It helps catch certain types of error.

ChrisA
 
R

Russ P.

The valid type(s) for an argument can be divided into two categories:

Those the compiler can check for, and those the compiler can't check

for. Some languages have more in the first category than others, but

what compiler can prove that a string is an

HTML-special-characters-escaped string? In a very few languages, the

compiler can insist that an integer be between 7 and 30, but there'll

always be some things you can't demonstrate with a function signature.



That said, though, I do like being able to make at least *some*

declaration there. It helps catch certain types of error.

I recall reading a few years ago that Guido was thinking about adding optional type annotations. I don't know if that went anywhere or not, but I thought it was a good idea. Eventually I got tired of waiting, and I realized that I just wanted a statically typed language, so I started using one.

Steven's view on static vs. dynamic typing are interesting, but I think they are "out of the mainstream," for whatever that's worth. Does that mean heis wrong? I don't know. But I do know that statically typed code just seems to me to fit together tighter and more solidly. Maybe it's a liberal/conservative thing. Do liberals tend to favor dynamic typing?
 
I

Ian Kelly

I recall reading a few years ago that Guido was thinking about adding optional type annotations. I don't know if that went anywhere or not, but I thought it was a good idea. Eventually I got tired of waiting, and I realizedthat I just wanted a statically typed language, so I started using one.

Python 3 has support for arbitrary function argument annotations. The
language itself ascribes no special meaning to it, so it's up to the
user to add a type-checker (or whatever else they might want to use it
for).
 
S

Steven D'Aprano

The valid type(s) for an argument can be divided into two categories:
Those the compiler can check for, and those the compiler can't check
for. Some languages have more in the first category than others, but
what compiler can prove that a string is an
HTML-special-characters-escaped string? In a very few languages, the
compiler can insist that an integer be between 7 and 30, but there'll
always be some things you can't demonstrate with a function signature.

That said, though, I do like being able to make at least *some*
declaration there. It helps catch certain types of error.

*shrug*

I don't terribly miss type declarations. Function argument declarations
are a bit simpler in Pascal, compared to Python:


Function Add(A, B : Integer) : Integer;
Begin
Add := A + B;
End;


versus


def add(a, b):
if not (isinstance(a, int) and isinstance(b, int)):
raise TypeError
return a + b


but not that much simpler. And while Python can trivially support
multiple types, Pascal cannot. (Some other static typed languages may.)

Whatever benefit there is in declaring the type of a function is lost due
to the inability to duck-type or program to an interface. There's no type
that says "any object with a 'next' method", for example. And having to
declare local variables is a PITA with little benefit.

Give me a language with type inference, and a nice, easy way to keep duck-
typing, and I'll reconsider. But until then, I don't believe the benefit
of static types comes even close to paying for the extra effort.
 
C

Chris Angelico

Whatever benefit there is in declaring the type of a function is lost due
to the inability to duck-type or program to an interface. There's no type
that says "any object with a 'next' method", for example. And having to
declare local variables is a PITA with little benefit.

Give me a language with type inference, and a nice, easy way to keep duck-
typing, and I'll reconsider. But until then, I don't believe the benefit
of static types comes even close to paying for the extra effort.

Here are some classic ways to do the multiple-types-accepted option.

//C++ style: overloading
int max(int a,int b) {return a>b ? a : b;}
float max(float a,float b) {return a>b ? a : b;}
//C++ also lets you go for templates, but leave that aside

//Pike style: piped types
int|float max(int|float a,int|float b) {return a>b ? a : b;}
//This lets you write one lot of code but doesn't let
//you declare that both args must be the same type

# Python style: accept anything, then (maybe) check
def max(a,b): return a if a>b else b
//Pike does this too:
mixed max(mixed a,mixed b) {return a>b ? a : b;}
/* So does C, but only with pointers: */
void *max(void *a,void *b) {... uhh, this is nontrivial actually ...}

For the "accept any object that has a next() method" sorts of rules, I
don't know of any really viable system that does that usefully. The
concept of implementing interfaces in Java comes close, but the class
author has to declare that it's implementing some named interface. In
theory there could be something that deduces the validity from the
given structure, but I'm not aware of any language that does this. But
it would let you do stuff like this (prototyped in Python):

class Integers:
def __init__(self): self.value=0
def next(self):
self.value+=1
return self.value

interface Iterable:
next(self)

def grab_three_values(Iterable iter):
return iter.next(),iter.next(),iter.next()

With a language that checks these sorts of things at compile time,
it's not a big deal to test. With something fully dynamic like Python,
it's probably not worth the effort. But maybe checks like this could
be useful to something like Coverity.

ChrisA
 
S

Serhiy Storchaka

06.06.13 12:45, Chris Angelico напиÑав(ла):
For the "accept any object that has a next() method" sorts of rules, I
don't know of any really viable system that does that usefully. The
concept of implementing interfaces in Java comes close, but the class
author has to declare that it's implementing some named interface. In
theory there could be something that deduces the validity from the
given structure, but I'm not aware of any language that does this.

Go?
 
R

rusi


In many Indian languages there is a saying: A poor dancer blames the
crooked floor. [Yeah… sounds tame in English] -- which is probably
what Steven is saying.

However in defence of the crooked floor… <wink>

When I taught C at the university in the early 90s[1], every third/
fourth compile+run of the kids would result in 'segmentation fault' if
they were lucky enough to be on unix, and OS crashes if they were on
DOS.
At first I would rail at the kids for not doing due diligence. Over
time I came to the conclusion that if a system is designed in such a
way that everyone is wrong, then its the system that is wrong and not
everyone.

When we switched from to python (via Scheme and a haskell-
predecessor), I dont remember ever getting a segmentation fault.

[Well once RR gave some Wx code that I tried and python core dumped.
Whether this speaks for RR or Wx or a dangerous combo...]

So yes, elegant programming languages are not proof against inelegant
programmers.
Nevertheless, programming languages can be made in a way that makes
certain class of errors harder/easier to make.

Joel Spolsky moans that:
Java is not, generally, a hard enough programming language that it can
be used to discriminate between great programmers and mediocre
programmers.
http://www.joelonsoftware.com/articles/ThePerilsofJavaSchools.html

And Paul Graham is even more provocative:
Java programmers are not as smart as python programmers
http://www.paulgraham.com/gh.html

[1] Prompted a paper in the 90s, with some modernizing modifications
http://blog.languager.org/2013/02/c-in-education-and-software-engineering.html
 
C

Chris Angelico

When we switched from to python (via Scheme and a haskell-
predecessor), I dont remember ever getting a segmentation fault.


Oh, it's easy to segfault Python.

import sys
sys.setrecursionlimit(999999999)
def foo(): foo()
foo()

:)

ChrisA
 
R

Robert Kern

For the "accept any object that has a next() method" sorts of rules, I
don't know of any really viable system that does that usefully. The
concept of implementing interfaces in Java comes close, but the class
author has to declare that it's implementing some named interface. In
theory there could be something that deduces the validity from the
given structure, but I'm not aware of any language that does this. But
it would let you do stuff like this (prototyped in Python):

class Integers:
def __init__(self): self.value=0
def next(self):
self.value+=1
return self.value

interface Iterable:
next(self)

def grab_three_values(Iterable iter):
return iter.next(),iter.next(),iter.next()

With a language that checks these sorts of things at compile time,
it's not a big deal to test. With something fully dynamic like Python,
it's probably not worth the effort. But maybe checks like this could
be useful to something like Coverity.

As Serhiy notes, Go does this, almost exactly as you wrote it (modulo syntax).

http://golang.org/doc/effective_go.html#interfaces_and_types

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco
 
R

rusi

Oh, it's easy to segfault Python.

import sys
sys.setrecursionlimit(999999999)
def foo(): foo()
foo()

:)

ChrisA

And so you are hereby anointed into the august company of RR!!
 
C

Chris Angelico

As Serhiy notes, Go does this, almost exactly as you wrote it (modulo
syntax).

http://golang.org/doc/effective_go.html#interfaces_and_types

Thanks (and thanks for actually providing a link). Many years ago I
came to the conclusion that anything I could conceive in language
design has already been done somewhere :)

Anyway, regardless of your language, there's always some criteria that
can't be coded. Suppose the valid input for a function were "integers
whose square roots are integers but whose cube roots are not". You
won't easily get compile-time checking of that.

ChrisA
 
C

Chris Angelico

And so you are hereby anointed into the august company of RR!!

Eh? No, I'm just adept at breaking stuff... I could probably segfault
a 100Mbit switch if I tried (or just got careless).

ChrisA
 
R

Rick Johnson

Frankly, I don't think the language much matters. It's all
down to the skill of the programmers and testers. Ada
wasn't the source of the problem unless Ada has a bug in
it... which is going to be true of pretty much any
language. Maybe Python would be a better choice, maybe
not; but let me tell you this, if the choice of language
means the difference between testable in three months and
testable code in three years, I'm going for the former.

Yes EVEN IF life or property hangs in the balance, the only important decision is how much work YOU will be required to do -- Chris, why i am not amazed by this bombastic display of selfishness?
 
C

Chris Angelico

Yes EVEN IF life or property hangs in the balance, the only important decision is how much work YOU will be required to do -- Chris, why i am not amazed by this bombastic display of selfishness?

I would like to say that you're not amazed because you're intelligent
enough to understand what I was saying, but I'm not sure it'd be true.

Let me spell it out for you.

* Deadlines are real things. They make a very audible "whooosh" as they go past.
* If the time frame for developing this is five years, then in five
years, the code must either be shipped or scrapped.
* Taking three years to get to a testable codebase allows two years to test.
* Taking three months to get testable allows over four years to test.

Would you say that doubling the testing period is a good thing or a bad thing?

ChrisA
 
R

Robert Kern

Anyway, regardless of your language, there's always some criteria that
can't be coded. Suppose the valid input for a function were "integers
whose square roots are integers but whose cube roots are not". You
won't easily get compile-time checking of that.

Say that on a Haskell list, and they'll take it as a challenge. :)

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco
 

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,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top