Perl is worse! (was: Python is Wierd!)

Gareth McCaughan Gareth.McCaughan at pobox.com
Fri Jul 28 14:50:27 EDT 2000


Steve Lamb wrote:

> a = None
> list(a)
> a = 1 
> list(a)
> a = 123
> list(a)
> a = "abc"
> list(a)
> 
> To me all of those could be converted into lists yet only the last one is.
> Why do I say that?  

Because you'd like not to distinguish between a single object
and a list containing only that object. I think that's a mistake.
If you want to turn 1 into a single-element list, you can do
it in the simplest way imaginable: [1]. That's *building*
a list, not *converting* to one, though; and the distinction
matters.

But, I hear you cry, it doesn't matter. We shouldn't distinguish.
1 is 1 and all alone and ever more shall be so, and it's the same
thing as "1" and (1,) and "one" and "I" and "un" and {{}} and ...
er, sorry, I got a little carried away. Anyway, I don't agree
with you. What's "foo" + "bar"? What's "1" + "2"? What's 1 + 2?
I claim there are Obviously Right answers to the first and
third of those questions, and there's no way to answer the
question in the middle that will be consistent with both.
Perl says that "foo"+"bar" isn't legal; you have to use a
completely different operation for string concatenation. I
don't like that. Still less do I like the fact that in Perl
"foo" == "bar". When you're comparing objects, you need to
know when you write the comparison code whether they're
numbers or strings. And how do you compare arrays? Um.

Implicit coercions save you some keystrokes. You don't
have to say "int()" or "float()" or whatever. Perhaps that
would matter to me if my coding speed were limited by my
typing speed: but it isn't. Especially not for non-trivial
programs in Perl. It's limited by my ability to keep stuff
in my head. Python is much easier to read fluently than
Perl is, and that means I don't have to remember so much
or think so hard just to understand what a fragment of
code does; and that means I code much faster in Python
than I do in Perl.

(And, before you ask: I knew Perl before I knew Python.
I've used it a lot. I'm not basing my arguments on
having known Python for years, tried out Perl once,
and found it hard. And I still use Perl in preference
to Python for some text-manipulation tasks.)

Let's go back to those examples for a minute. What do you
want list("123") to be? ["123"] or ["1", "2", "3"]? If the
former, then you're losing sight of the fact that a string
is *obviously* a string of characters. If the latter, then
you're saying that you want 123 <-> "123" but [123] <-> ["1", "2", "3"].
Ouch.

>     None could be converted into an empty list.  None is nothing.  I fail to
> see how you can't populate a list with a single nothing.

So do you want [None] or []? Heck, 0 is nothing too; why
not say that 123+None = 123, too? I suppose list(0) should
yield [] rather than [0], since 0 is nothing and nothing
is an empty list.

And a ham sandwich is better than eternal happiness,
because nothing is better than eternal happiness and
a ham sandwich is better than nothing. I prefer my
programming languages *not* to encourage puns like
this.

>     1 is a single value.  I fail to see why that cannot be converted to [1]
> which is allowed, btw. 
> a = [1]
> a

That isn't a conversion. It's building a list. There are
important differences; for instance, [x] is always a 1-element
list containing only x. There's no way to make that true of
list(x), since e.g. we obviously must have list(x) == x when
x is already a list. (If you think that list(x) should always
be a 1-element list containing x, then I conclude that you've
just misunderstood the name; the function you want is already
available, and it's written [x].)

>     "abc" could either be a single value or a sequence.  It is converted
> as ["a", "b", "c"].  Of course, the same /could/ be said for the above.
> However, let's play around with this one since it is the only one that
> works somewhat as expected in conversion.

On the contrary, the others all work *exactly* as I expect,
and strings are the ones that are a little counterintuitive.

> a = "abc"
> a
> a = list(a)
> a = str(a)
> a
> 
>     a is now "['a', 'b', 'c']".  Which means we split a string up when
> converting to list but don't concatinate on the way back.

list() and str() were never meant to be inverses. list() is
for converting arbitrary sequences into lists. str() is for
producing string representations of arbitrary objects.

>     How did I run across this?  Because I wanted to create an empty name each
> time a class instance is created.  Since I was building the class I didn't
> know if I was going to use a list or a str.  I figure I could just set it
> to None and then manipulate it later.  Nope.  Couldn't even convert it even
> though the conversion seems quite straightforward to me.  None into any
> structure should yield and empty of that structure.  We can have empty
> strings, tuples, lists and directories.

None doesn't mean "empty object". It means "no object". There's
a big difference, whether or not you care to recognise it. As
big as the difference between "no bottles" and "an empty bottle",
which is insignificant only if all you care about is the beer. :-)

>                                          Funny thing, though.  I can do this
> and it works just fine:
> 
> a = None
> a = ""
> 
>     Amazing, that.  Automagical conversion from None to an emptry string on
> the assignment operator.  Actually, we both know, and correct me as I may be
> wrong, that it is really reassigning the data space a is pointing to.

Seems like a very strange way of putting it, but yes.
I don't see any reason why you should think it's "amazing"
or "automagical", still less "conversion".

>     However, if we want to create the namespace with nothing we cannot
> because we cannot convert it for later use.  Thus, we are back to
> declaring variables except this time we're doing it with automagical
> (implicit) means instead of explicit.

What on earth do you mean? The following isn't illegal at all.

    class Foo:
      def __init__(self):
        self.name = None
      def rename(self, name):
        self.name = name
      def __str__(self):
        return "<Foo: %s>" % self.name

    a = Foo()
    a.rename("wombat")
    print a

    b = Foo()
    b.rename([1,2,3])
    print b

This will print
    <Foo: wombat>
    <Foo: [1,2,3]>

What's your problem?

>     I just don't understand how people can advocate for types and the
> restrictions they impose while, on the other hand, embracing a language that
> is free enough to shoot yourself in the foot by reassigning None.

It's pretty hard to reassign None by accident.

It's pretty easy to say "print 'yes!' if ($a == $b);"
and forget that $a and $b might be strings.

I shoot myself in the foot a *lot* less with Python than
I ever have with Perl.

-- 
Gareth McCaughan  Gareth.McCaughan at pobox.com
sig under construction



More information about the Python-list mailing list