Loading ...
Sorry, an error occurred while loading the content.

Re: [Python-il] Perl Vs. Python on Various Points

Expand Messages
  • Beni Cherniavsky
    ... If sigils just conveyed variable types, you could achieve the same effect with Hungarian notation: listS.add(scalarH) No, sigils have a deeper function -
    Message 1 of 3 , Jul 13, 2009
    • 0 Attachment
      On Mon, Jul 13, 2009 at 11:10, Shlomi Fish<shlomif@...> wrote:
      >
      > 1. Syntax as an Indicative of What the Language is Doing:
      > ---------------------------------------------------------
      >
      > He said he didn't like Perl syntax like "push @$array_ref, $val;" because
      > of the sigils. I said I happen to like it because the extra characters
      > convey meaning. By looking at this code I know that $array_ref is an array
      > reference, that it is being treated as an array and that one appends a
      > single ("scalar") value to it. On the other if I see code like this:
      >
      > <<<<<
      > s.add(h)
      >>>>>>
      >
      > It's harder for me to know what's going on without running the program. For
      > all I know s and h could be almost anything. The sigils convey meaning.
      >
      If sigils just conveyed variable types, you could achieve the same
      effect with Hungarian notation:

      listS.add(scalarH)

      No, sigils have a deeper function - they (together with other parts of
      perl syntax) assign types to the whole syntax tree - not just the
      leaves but all nodes!

      1. They convey the type of operators: "$listref1 = $listref2" is 0-deep copy
      while "@list1 = @list2" is 1-deep-copy.

      2. They imply coercion operators on type boundaries: "$listlen = @list".

      So it's not about adding extra characters for readability. Adding
      characters in one place increases information densitiy in other
      places.

      As others mentioned, the downside is that sigils don't scale to custom
      types - all references are syntactically the same.

      > 2. Comparison Operators:
      > ------------------------
      >
      > Later on the discussion diverted to comparison operators. Now python only
      > has "==" and friends for comparison (at least as far as I know) while Perl 5
      > has both ==/!=/>/etc. and eq/ne/gt/etc. The first ones are intended for
      > numeric comparison and the latter ones for string comparison.
      >
      > I argued that by looking at code with such comparisons, I can tell what kind
      > of comparison the programmmer intended the comparison to be. Part of the
      > reason for the fact that Perl 5 has both types of comparison is that it
      > does not have separate data types for strings and for numbers, but this is
      > not the only reason.
      >
      Same about "($s1 . $s2) x 10" vs. "($n1 + $n2) * 10".
      Again, it's not just about knowing the type from the look of the code.
      In python, one should always coerce numbers/strings to their intended
      type; given that, == always does the right thing.
      What separate operators allow in perl, is to have the coercions
      *implied*, thus increasing code density.

      ...
      > So Python's == does a deep comparison of complex data structures and returned
      > that x and y where equivalent despite the fact that they aren't the same
      > physical reference.
      ...
      > For deep comparison we have CPAN modules like
      > http://search.cpan.org/dist/Test-Differences/ , or can use the more limited
      > is_deeply() functionationality of Test::More.
      >
      That's very bad - basic features of nested structures like printing
      (Data::Dumper) and comparison must be easily accesible.
      That's why Perl now has the new ~~ "smart match" operator.
      Not having nested data printing is *unspeakably* bad when using an
      interactive prompt, which is why Perl's debugger does have an "x"
      command.

      > I personally feel that it's impossible to have "one-comparison-fits-all"
      > because for two pieces of data, there may be several ways that we would like
      > to compare them.
      >
      Some lisps have 4 (equal, eql, eq, =) or more. But most of that cruft
      is just optimization.
      All modern languages concluded that you need just 2: deep by-value
      comparison (overloadable by type), and shallow identity check.
      And the shallow identity check is rare enough that maybe it doesn't
      even deserve an operator.
      (BTW, in lisp operators are cheap - the are regular functions - which
      might explain why they felt OK with having so many.)

      > 3. Circular References:
      > -----------------------
      > After the discussion on comparison, the conversation diverted to
      > discussing circular references. My partner for the conversation was
      > surprised to learn that Python has them:
      ...
      Ha? Every non-purely-functional language with references has them.
      Or did you mean that Python detects them when dumping values?

      It was important to not blow your terminal if you dumps one, and to
      make garbage collection (mostly) work on them, but the rest of mess is
      left for you to untangle.

      > Now what happens if we try to compare two equivalent circular data strctures:
      ...
      > So CPython is not very smart about it, and throws an ugly expection.
      >
      I've never heard of a single language that *is* very smart about them!
      There is no easy, or even single, way to compare circular structures.
      Nor is there much use.

      > Obviously x[0] = x data structures are neither too common or useful, but
      > circular references are useful for such data structures and OO patterns
      > as trees with parent pointers, doubly-linked lists or graphs.
      >
      Back-references are a common cause of accidental circles, but
      Sure, but these are not normally part of the object's "value" that
      participates in comparison.
      If they are, go back to the drawing board :).

      Graphs are the only structure that is meaningfully symmetric.
      There are many ways to define graphs, so it's left to libraries to handle them.

      > I asked
      > the people on Freenode #python about it and they told me that "python has had
      > a cycle collector since 2.0" and I was told that this cycle collector does
      > not make object destruction unpredictable.
      >
      Fine print: python collects cycles but not immediately; cycles that
      contain objects with __del__ finalizers are not collected.

      > perl 5 still doesn't have something like that and when I consulted #perl
      > about it they said that http://xrl.us/be233e is a start towards a cycle
      > collection for objects.
      >
      Note how many years Perl and Python lived without it.
      => "You Ain't Gonna Need It" until proven otherwise.
      Rule of thumb: you do need it when you find yourself using weakrefs.

      --
      Beni <cben@...>
    • Shlomi Fish
      ... I guess you re right. I still find that using sigils help me understand what the code does. ... Well, I haven t found deep comparison very useful so far,
      Message 2 of 3 , Jul 14, 2009
      • 0 Attachment
        On Monday 13 July 2009 16:57:39 Beni Cherniavsky wrote:
        > On Mon, Jul 13, 2009 at 11:10, Shlomi Fish<shlomif@...> wrote:
        > > 1. Syntax as an Indicative of What the Language is Doing:
        > > ---------------------------------------------------------
        > >
        > > He said he didn't like Perl syntax like "push @$array_ref, $val;" because
        > > of the sigils. I said I happen to like it because the extra characters
        > > convey meaning. By looking at this code I know that $array_ref is an
        > > array reference, that it is being treated as an array and that one
        > > appends a single ("scalar") value to it. On the other if I see code like
        > > this:
        > >
        > > <<<<<
        > > s.add(h)
        > >
        > >
        > > It's harder for me to know what's going on without running the program.
        > > For all I know s and h could be almost anything. The sigils convey
        > > meaning.
        >
        > If sigils just conveyed variable types, you could achieve the same
        > effect with Hungarian notation:
        >
        > listS.add(scalarH)
        >
        > No, sigils have a deeper function - they (together with other parts of
        > perl syntax) assign types to the whole syntax tree - not just the
        > leaves but all nodes!
        >
        > 1. They convey the type of operators: "$listref1 = $listref2" is 0-deep
        > copy while "@list1 = @list2" is 1-deep-copy.
        >
        > 2. They imply coercion operators on type boundaries: "$listlen = @list".
        >
        > So it's not about adding extra characters for readability. Adding
        > characters in one place increases information densitiy in other
        > places.
        >
        > As others mentioned, the downside is that sigils don't scale to custom
        > types - all references are syntactically the same.
        >

        I guess you're right. I still find that using sigils help me understand what
        the code does.


        > > 2. Comparison Operators:
        > > ------------------------
        > >
        > > Later on the discussion diverted to comparison operators. Now python only
        > > has "==" and friends for comparison (at least as far as I know) while
        > > Perl 5 has both ==/!=/>/etc. and eq/ne/gt/etc. The first ones are
        > > intended for numeric comparison and the latter ones for string
        > > comparison.
        > >
        > > I argued that by looking at code with such comparisons, I can tell what
        > > kind of comparison the programmmer intended the comparison to be. Part of
        > > the reason for the fact that Perl 5 has both types of comparison is that
        > > it does not have separate data types for strings and for numbers, but
        > > this is not the only reason.
        >
        > Same about "($s1 . $s2) x 10" vs. "($n1 + $n2) * 10".
        > Again, it's not just about knowing the type from the look of the code.
        > In python, one should always coerce numbers/strings to their intended
        > type; given that, == always does the right thing.
        > What separate operators allow in perl, is to have the coercions
        > *implied*, thus increasing code density.
        >
        > ...
        >
        > > So Python's == does a deep comparison of complex data structures and
        > > returned that x and y where equivalent despite the fact that they aren't
        > > the same physical reference.
        >
        > ...
        >
        > > For deep comparison we have CPAN modules like
        > > http://search.cpan.org/dist/Test-Differences/ , or can use the more
        > > limited is_deeply() functionationality of Test::More.
        >
        > That's very bad - basic features of nested structures like printing
        > (Data::Dumper) and comparison must be easily accesible.
        > That's why Perl now has the new ~~ "smart match" operator.
        > Not having nested data printing is *unspeakably* bad when using an
        > interactive prompt, which is why Perl's debugger does have an "x"
        > command.

        Well, I haven't found deep comparison very useful so far, except in testing,
        where I have is_deeply() or the better Test::Differences. Personally, if I
        have a complex data structure and want to compare it to another complex data
        structure - how will this comparison be done and what can I learn from it in
        my code?

        Data::Dumper has been part of the Perl core for a long time (it can mostly
        implemented completely in user-land, though), and Perl programmers make
        extensive use of it. There are many other modules for handling nested data
        structures on CPAN and in the core, like Storable, which is useful for
        serialisation and deserialisation or http://search.cpan.org/dist/Data-DPath/ .

        >
        > > I personally feel that it's impossible to have "one-comparison-fits-all"
        > > because for two pieces of data, there may be several ways that we would
        > > like to compare them.
        >
        > Some lisps have 4 (equal, eql, eq, =) or more. But most of that cruft
        > is just optimization.

        Yes, it's hard for me to recall which is which. I think (=) is numeric and
        (eq) is if it's the same referent. Isn't (equal) a deep comparison?

        > All modern languages concluded that you need just 2: deep by-value
        > comparison (overloadable by type), and shallow identity check.

        Well, arguably the Perl 5 distinction of == and eq is because strings and
        numbers are inter-changeable.

        > And the shallow identity check is rare enough that maybe it doesn't
        > even deserve an operator.
        > (BTW, in lisp operators are cheap - the are regular functions - which
        > might explain why they felt OK with having so many.)
        >

        Not all Lisp operators can be implemented as regular functions. Examples for
        this are (or) and (and). These might still be able to be implemented as
        macros.

        > > 3. Circular References:
        > > -----------------------
        > > After the discussion on comparison, the conversation diverted to
        > > discussing circular references. My partner for the conversation was
        > > surprised to learn that Python has them:
        >
        > ...
        > Ha? Every non-purely-functional language with references has them.
        > Or did you mean that Python detects them when dumping values?
        >

        No, that they exist in the first place. He was surprised to learn that they
        are at all possible in Python, as he didn't use them.

        > It was important to not blow your terminal if you dumps one, and to
        > make garbage collection (mostly) work on them, but the rest of mess is
        > left for you to untangle.

        Yes.

        >
        > > Now what happens if we try to compare two equivalent circular data
        > > strctures:
        >
        > ...
        >
        > > So CPython is not very smart about it, and throws an ugly expection.
        >
        > I've never heard of a single language that *is* very smart about them!
        > There is no easy, or even single, way to compare circular structures.
        > Nor is there much use.

        Well, one option I can think of is to detect a cycle within the nesting path
        of each variable being compared, and if so, see if it's equivalent to the one
        in the other side, and deal with it. In any case, throwing an exception in
        this case is not very desirable because saying a_ref == b_ref is innocent
        enough. But I suppose the edge case of a circular reference is not critical
        enough to warrant special treatment.

        >
        > > Obviously x[0] = x data structures are neither too common or useful, but
        > > circular references are useful for such data structures and OO patterns
        > > as trees with parent pointers, doubly-linked lists or graphs.
        >
        > Back-references are a common cause of accidental circles, but
        > Sure, but these are not normally part of the object's "value" that
        > participates in comparison.
        > If they are, go back to the drawing board :).
        >
        > Graphs are the only structure that is meaningfully symmetric.
        > There are many ways to define graphs, so it's left to libraries to handle
        > them.

        I don't understand these two paragraphs.

        >
        > > I asked
        > > the people on Freenode #python about it and they told me that "python has
        > > had a cycle collector since 2.0" and I was told that this cycle collector
        > > does not make object destruction unpredictable.
        >
        > Fine print: python collects cycles but not immediately; cycles that
        > contain objects with __del__ finalizers are not collected.

        Ah.

        >
        > > perl 5 still doesn't have something like that and when I consulted #perl
        > > about it they said that http://xrl.us/be233e is a start towards a cycle
        > > collection for objects.
        >
        > Note how many years Perl and Python lived without it.
        > => "You Ain't Gonna Need It" until proven otherwise.
        > Rule of thumb: you do need it when you find yourself using weakrefs.

        Regards,

        Shlomi Fish

        --
        -----------------------------------------------------------------
        Shlomi Fish http://www.shlomifish.org/
        My Aphorisms - http://www.shlomifish.org/humour.html

        God gave us two eyes and ten fingers so we will type five times as much as we
        read.
      Your message has been successfully submitted and would be delivered to recipients shortly.