Instead of deciding between Python or Lisp for a programming intro course...What about an intro course that uses *BOTH*? Good idea?

Chris Angelico rosuav at gmail.com
Wed May 13 00:54:59 EDT 2015


On Wed, May 13, 2015 at 11:14 AM, Steven D'Aprano
<steve+comp.lang.python at pearwood.info> wrote:
> On Wed, 13 May 2015 02:05 am, Chris Angelico wrote:
>
>> So if you're writing a library function, it probably shouldn't use
>> print()... but your application is most welcome to. You usually know
>> which one you're writing at any given time.
>
> You might be, but beginners are not.

I meant the generic "you" there. A beginner may well not know whether
to use / or //, whether it's better to use a list or a dict, etc etc
etc. That's what instructors are for. Make the distinction that
library functions shouldn't use print but application code can, and
then examples like this...

> I'm not sure I accept Rustom's fix for the problem (I think that his cure is
> worse than the disease), but it is *hard* to get some beginners to use
> return instead of print:
>
> def add_twice(x, y):
>     """Add twice y to x."""
>     print x + 2*y
>
>
> sort of thing.

... can be answered simply by explaining that "add_twice" ought to be
written as a library function rather than an application. It's the
exact same answer as this:

def find_all_whatevers(base_dir):
    whatevers = []
    os.chdir(base_dir)
    for fn in os.listdir():
        if fn is a whatever: whatevers.append(fn)
        if fn is a directory: whatevers.extend(find_all_whatevers(fn))
    return whatevers

The working directory belongs to the application, not to a library
function, so this shouldn't use os.chdir(), even though it does spare
you the effort of string manipulation. (Of course, a real-world
version of this should use os.walk(), but that's a complete rewrite.)

The precise boundary between reusable functions and the actual
application isn't always easy to draw, and there'll be times when you
refactor something across that line. That's not a problem. There are
still plenty of cases that are clear enough to use for explanation.

> Personally, I think that banning print is only useful if you wish to
> encourage cargo-cult programming:
>
> "Don't use print!"
> "Why not?"
> "My CS lecture said not to use it! I dunno, maybe it has a virus or
> something."

Agreed. There are VERY few features which should be utterly and
totally banned, and they're usually kept only for backward
compatibility with a time when people didn't know how dangerous they
were. In Python, the only one I can think of is Py2's input(), which
should be treated as XKCD 292 treats GOTO. (If you really *do* want to
take a string from the user and immediately eval it, just write it as
"eval(raw_input())" so everyone knows.) C has gets(), which is
similarly dangerous and has a similarly straight-forward replacement.
PHP has register_globals (or did until recently - it took a long time
to go from "default is on, we recommend you turn it off" through
"default is off, we recommend you don't turn it on" to finally "bad
feature is removed"). Beyond those, there's not much that doesn't have
at least _some_ reason for existing.

> I'd rather give them exercises designed to show (rather than tell) the
> differences between printing a result and returning a result, and how they
> effect re-usability of software components and function chaining. Using a
> procedural language is *perfect* for that, since you can highlight the
> differences:
>
> function foo(n:int): int;
>   begin
>     foo := n+1;
>   end;
>
> procedure foo(n:int);
>   begin
>     writeln(n+1);
>   end;

Yep. I'd also use clear function/procedure names to make it more
visible, and probably tie this in with loops to show how you can print
more than one thing but can only return one. (Generators are a more
advanced topic.) A few examples go a long way.

ChrisA



More information about the Python-list mailing list