{"id":82,"date":"2007-06-08T04:03:05","date_gmt":"2007-06-08T08:03:05","guid":{"rendered":"http:\/\/www.phildev.net\/phil\/newblog\/?p=82"},"modified":"2007-06-08T04:03:05","modified_gmt":"2007-06-08T08:03:05","slug":"","status":"publish","type":"post","link":"https:\/\/www.phildev.net\/phil\/blog\/?p=82","title":{"rendered":"A Perl guy&#8217;s honest look at Python"},"content":{"rendered":"<p>As some of you may know, I&#8217;m a huge perl person. I&#8217;ve written a lot of it, and I know it very well. That&#8217;s not to say there aren&#8217;t people who know it better than I do, but I know it well.<\/p>\n<p>Now, while I&#8217;m a big Perl fan, it&#8217;s worth noting I&#8217;m well aware of Perl&#8217;s flaws: a poor OO model, poor (or some might argue non-existent) exception handling, and some very dangerous implicitness to name a few.<\/p>\n<p>So, recently, I decided to give both Ruby and Python a shot. Now, I&#8217;ve looked at python a few times &#8211; but the whole whitespace-means-stuff thing really turned me off. Explicit blocking is a good thing. As such, I never really looked far enough past that to give it a fair chance. So I decided it was time to give python a fair shot.<\/p>\n<p>After playing with it for a while and writing a few small scripts and then rewriting them, I found the following really disheartening things. But just to make sure I wasn&#8217;t just expecting python to act like Perl, I ran them by a friend of mine who&#8217;s a big python guy, and he admitted not being thrilled with these aspects of the language either.<\/p>\n<p>So here you are &#8211; a day in Python from a Perl guy.<\/p>\n<p><strong>The string&#8217;s split function uses regexes but doesn&#8217;t support them<\/strong><\/p>\n<p>If I have a string object and I call it&#8217;s split() method with no argument, it automatically splits on the regex <code>\\s+<\/code>. However, the method only takes strings as parameters. Which means you can&#8217;t even pass in <code>\\s+<\/code> as an argument. OK, well you can, but only if you want to match the literal string &#8216;\\s+&#8217;. So, this code:<\/p>\n<pre>\nfoo = 'b     a      r'\nprint foo.split()\n<\/pre>\n<p>returns the expected 3-element array <code>['b', 'a', 'r']<\/code>, but this code:<\/p>\n<pre>\nfoo = 'b     a      r'\nprint foo.split('\\s+')\n<\/pre>\n<p>returns the single-element array <code>['b     a      r']<\/code>. Doing <code>foo.split(\/\\s+\/)<\/code> as a ruby-coder might try is a syntax error and <code>foo.split(\\s+)<\/code> is as well. But alas, we look through python.org\/docs to find &#8211; aha! there&#8217;s a regex class! Sadly, you cannot pass a regex object to string&#8217;s split() method. This code&#8217;s last line is a syntax error:<\/p>\n<pre>\nimport re\np = re.compile('\\s+')\nfoo = 'b    a     r'\nprint foo.split(p)\n<\/pre>\n<p>I get, <code>TypeError: expected a character buffer object<\/code>. The way to actually do this is completely counter-intuitive, you can&#8217;t use the string&#8217;s split() method, you must use the regex&#8217;s split() method, and pass the string in:<\/p>\n<pre>\nimport re\np = re.compile('\\s+')\nfoo = 'b    a    r'\nprint p.split(foo)\n<\/pre>\n<p>This code will return the desired 3-element array <code>['b', 'a', 'r']<\/code>. So, why wouldn&#8217;t the string function do a type-check on it&#8217;s parameter so you can pass in a regex object?<\/p>\n<p>Or better yet, why can&#8217;t the <em>re<\/em> class extend or overload the string class&#8217;s split() method to type-check and use its own method if it&#8217;s a regex or the original method if its a string? There&#8217;s several ways to make this intuitive or consistent, but none of them appear to be implemented as far as I can tell.<\/p>\n<p><strong>What happened to constructors?<\/strong><\/p>\n<p>Speaking of regexes, it seems cumbersome to require the programmer to call the compile() method when creating a regex object. When instantiating a regex object, clearly I want to make a regex, so why doesn&#8217;t the constructor take the string and &#8220;compile&#8221; the regex? It&#8217;s not clear to me that this concept even exists in python. That would be a shame.<\/p>\n<p><strong>I am OO, I&#8217;m not OO, I am OO, I&#8217;m not OO&#8230;<\/strong><\/p>\n<p>Python touts itself has having done OO better than Perl (this isn&#8217;t hard), and as being an OO language at its core instead of as a bolt-on. So if I have a string that contains simply an integer, one would expect some method to get an int object out of it. For example, if I have <code>foo = \"1\"<\/code> and want to do a mathematical operation on it (add 4 and get 5 as a result), one would expect something like <code>foo.int()<\/code> or <code>foo.atoi()<\/code> or <code>foo.toint()<\/code> to exist. Instead there are global functions. <em>Global functions<\/em>? In an <em>object-oriented language<\/em>? Yup, this is the code you&#8217;d be looking for:<\/p>\n<pre>\nfoo = \"1\"\nbar = int(foo)\nprint bar + 5\n<\/pre>\n<p>A global function to <em>cast<\/em> to another type. Yeah, that&#8217;s OO. By the way, there&#8217;s no OO method for doing addition either (while I find those ugly, it would at least be consistent). There&#8217;s objects and types and global functions and in most cases things are objects, but not in others. This is a Perl problem Python was trying to get away from.<\/p>\n<p><strong>Poor interpreter errors<\/strong><\/p>\n<p>One of the great things about interpreted languages is that an interpreter is around at run-time and as such, has more data and can hopefully provide better error messages. There are far less of those fun cryptic compiler and linker errors. So, I&#8217;d expect python to be able to tell me something simple like &#8220;you forgot to declare a variable.&#8221; Take this code:<\/p>\n<pre>\nfor x in range(10):\nhash['foo'] = 'bar'\n<\/pre>\n<p>Not very useful code, but easy enough to read. There&#8217;s a problem though &#8211; I haven&#8217;t declared the dictionary (that&#8217;s a hash or an associative array for those of you not familiar with python nomenclature) variable <code>hash<\/code> when I attempt to assign to its <code>foo<\/code> index. But instead python tells me I have a type mis-match:<\/p>\n<pre>\nTraceback (most recent call last):\nFile \"&lt;stdin&gt;\", line 2, in ?\nTypeError: object does not support item assignment\n<\/pre>\n<p>That&#8217;s not a type error; that&#8217;s an undeclared variable! This code works fine:<\/p>\n<pre>\nhash = {}\nfor x in range(10):\nhash['foo'] = 'bar'\n<\/pre>\n<p>It&#8217;s perfectly reasonable to require variables be declared, but then your interpreter should be able to error when they&#8217;re not!<\/p>\n<p>None of these are show-stopping. None of them are evil. But it&#8217;s a large number of fairly annoying things to hit within your first half-hour with a language and not find some really good explanation within the first day. No language is perfect; and Python seems to have a lot of strengths. I&#8217;m continuing to play with it and with Ruby; we&#8217;ll see how it goes.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>As some of you may know, I&#8217;m a huge perl person. I&#8217;ve written a lot of it, and I know it very well. That&#8217;s not to say there aren&#8217;t people who know it better than I do, but I know it well. Now, while I&#8217;m a big Perl fan, it&#8217;s worth noting I&#8217;m well aware [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[5],"tags":[],"_links":{"self":[{"href":"https:\/\/www.phildev.net\/phil\/blog\/index.php?rest_route=\/wp\/v2\/posts\/82"}],"collection":[{"href":"https:\/\/www.phildev.net\/phil\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.phildev.net\/phil\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.phildev.net\/phil\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.phildev.net\/phil\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=82"}],"version-history":[{"count":0,"href":"https:\/\/www.phildev.net\/phil\/blog\/index.php?rest_route=\/wp\/v2\/posts\/82\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.phildev.net\/phil\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=82"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.phildev.net\/phil\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=82"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.phildev.net\/phil\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=82"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}