Experiences/guidance on teaching Python as a first programming language

Paul Smith paul at mad-scientist.net
Wed Dec 18 04:49:43 CET 2013


On Wed, 2013-12-18 at 01:33 +0000, Steven D'Aprano wrote:
> And "What does 'implementation-specific undefined behaviour' actually 
> mean in practice?", another common question when dealing with C.

Only asked by people who haven't had it explained.  There's "undefined
behavior", and there's "implementation-specific behavior", but it is
impossible to have "implementation-specific undefined behavior".

And, the definitions are simple to understand: "undefined behavior"
means that if your program invokes it, there is no definition of what
will happen.  This is buggy code.

"Implementation-specific" behavior means that the standard requires the
implementation to do some well-defined thing, but the standard does not
define exactly what it must be.  You can go look up what your
implementation will do in its documentation (the standard requires that
it be documented), but you can't assume the same thing will happen in
another implementation.  This is non-portable code.

It's a very rare language indeed that has no undefined or
implementation-specific behaviors.  Python gets to "cheat" by having one
reference implementation.  Every time you've had to go try something out
in the Python interpreter because the documentation didn't provide the
details you needed, that WAS implementation-specific behavior.

> > You never have to wonder what the
> > lifetime of an object is, 
> 
> Since C isn't object oriented, the lifetime of objects in C is, um, any 
> number you like. "The lifetime of objects in <some language with no 
> objects> is ONE MILLION YEARS!!!" is as good as any other vacuously true 
> statement.

The implication that only an "object oriented" language could have a
concept of object lifetimes is false.  Another, less hyperbolic way of
saying this is that in C, the lifetime of objects is _exactly as long as
you specify_.  Heap objects come into existence when you explicitly
create them, and they go out of existence when you explicitly destroy
them.  If you don't destroy them, they never go away.  If you destroy
them more than once, that's undefined behavior.  Stack objects are even
simpler.

> > or be mystified by which of the 7 signatures
> > of Foo.foo() are going to get called, 
> 
> Is that even possible in C? If Foo is a struct, and Foo.foo a member, I 
> don't think C has first-class functions and so Foo.foo can't be callable.

Of course that's valid C.  It's true that C doesn't have first-class
functions, but it supports invoking functions through pointers and you
can store functions in data members, pass functions as arguments, and
return functions from other functions, so Foo.foo can certainly be
callable.

~$ cat /tmp/foo.c
#include <stdio.h>

struct Foo {
    void (*foo)();
};

void foobar(void) { printf("foobar\n"); }

int main()
{
    struct Foo Foo = { foobar };
    Foo.foo();
    return 0;
}

$ gcc -Wall -o /tmp/foo /tmp/foo.c

$ /tmp/foo
foobar





More information about the Python-list mailing list