in reply to Converting Python to Perl and back again

Converting between Python and Perl is not easily done by simple subsitutions, as there are some strong differences between how Python variables and Perl variables work :

  1. A Python tuple is immutable - you can't change any part of it - this makes it hard(er) to represent a tuple in Perl with the same semantics (I think of a tied Array as a solution)
  2. Python dictionaries take tuples (and not strings) as keys - this makes Perl hashes hard to use for that area, as you have to find a way to encode any tuple to a string and back (I think of URLencoding the tuples and a special marker for the different elements of the tuple)
  3. Python knows no explicit references, in fact, everything in Python is a reference - this is not that bad, as Perl also dosen't know complex data structures without references, but in Perl, those references are explicit
  4. Python can easily do deep comparision of data, where with Perl you will have to manually recurse through the data - this makes some algorithms nastier to read under Perl

perl -MHTTP::Daemon -MHTTP::Response -MLWP::Simple -e ' ; # The $d = new HTTP::Daemon and fork and getprint $d->url and exit;#spider ($c = $d->accept())->get_request(); $c->send_response( new #in the HTTP::Response(200,$_,$_,qq(Just another Perl hacker\n))); ' # web

Replies are listed 'Best First'.
Re: Converting Python to Perl and back again
by Abigail-II (Bishop) on Apr 04, 2003 at 08:47 UTC
    Actually, Perl hashes take lists as keys too. This is essential for Regexp::Common's API. Behind the scene, Perl joins the list using $; as the join string to turn the list into a string.

    Abigail

      I know, but to make this work in a general fashion when converting Python code to Perl code, you need to make sure that no list element can stringify to something containing $; - it's possible but not quite simple (that's what I wanted to say when I mentioned URLencoding). Of course simply storing a (stringified) reference to a static array (which implements a tuple) would also work, but then you're on the way of reimplementing Python in Perl - a slippery slope.
      For general consumption, there also is Hash::MultiKey, which allows one to use (general) lists (or rather, references to those) as hash keys, presumably in the same way, by storing a stringified list reference as the hash key.

      perl -MHTTP::Daemon -MHTTP::Response -MLWP::Simple -e ' ; # The $d = new HTTP::Daemon and fork and getprint $d->url and exit;#spider ($c = $d->accept())->get_request(); $c->send_response( new #in the HTTP::Response(200,$_,$_,qq(Just another Perl hacker\n))); ' # web
Re: Re: Converting Python to Perl and back again
by Anonymous Monk on Apr 04, 2003 at 06:51 UTC

    Good points. With regard to number 4, is there an alternative in Perl for something such as

    a = [1, 2, 3] b = [1, 2, 4] if (a < b): print "a is less than b"

    Or would I end up recursing through the array, comparing each element individually?

    I should note that I've never found this useful, so I won't hold it against Perl if it doesn't have this feature :).

      There is no straightforward way in Perl, no. The way I go in Perl is most of the time using the is_deeply method from Test::More, but you end up doing the recursion manually. In Python, I've used this thing a lot in reporting sorted arrays - it's very convenient, but this is impossible under the current Perl due to the way sort works. Once could override sort to do the Right Thing whenever it encounters two arrays of references and no block is passed to it, but I don't know at what cost - and most code dosen't use that anyway.

      perl -MHTTP::Daemon -MHTTP::Response -MLWP::Simple -e ' ; # The $d = new HTTP::Daemon and fork and getprint $d->url and exit;#spider ($c = $d->accept())->get_request(); $c->send_response( new #in the HTTP::Response(200,$_,$_,qq(Just another Perl hacker\n))); ' # web

      Actualy, there is a way, though it's somwhat odd. Instead of using lists, use version-strings. In recent (>5.6, IIRC) versions of perl, v1.2.3 eq chr(1).chr(2).chr(3) (the v is optional if there are more then two elements, but be warned that there is a (fairly large) size limit on the elements), so what you're doing there is equivlent to

      $a = v1.2.3; $b = v1.2.4; if ($a lt $b) { print "a is less than b"; }


      Warning: Unless otherwise stated, code is untested. Do not use without understanding. Code is posted in the hopes it is useful, but without warranty. All copyrights are relinquished into the public domain unless otherwise stated. I am not an angel. I am capable of error, and err on a fairly regular basis. If I made a mistake, please let me know (such as by replying to this node).

Re: Re: Converting Python to Perl and back again
by bradb (Sexton) on Apr 05, 2003 at 01:35 UTC
    2. Python dictionaries take tuples (and not strings) as keys - this makes Perl hashes hard to use for that area, as you have to find a way to encode any tuple to a string and back (I think of URLencoding the tuples and a special marker for the different elements of the tuple)

    Well, no. :)

    The values of dictionary keys in Python can be any immutable object, including strings and tuples that contain no mutable elements (e.g. a tuple that contains a list as one of its elements could not be a key).

    As yet another challenge to add to the list; sigils. $foo, @foo and %foo semantics can't be represented in Python.

    Python has built-in support for iterators and generators; Perl does not. There's no reasonable conversion path for these semantics.

    Python classes can inherit from built-in types. The complications of munging this into some funky tie-fu aren't worth the return on investment (especially when you consider that Python's built-ins are a lot different from Perl's built-ins).

    The best way to convert Python to Perl and Perl to Python is to contribute to the development of Parrot because there are far too many issues to make it reasonable to truly "convert" one to the other.

    It's like trying to "convert" a BMW M5 into a Ferrari 360 Modena. I'll let you decide which is which. :)