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

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

Expand Messages
  • Shlomi Fish
    ... I see. Well, you can tell what a reference is by how it is used. - [], - {}, - ... one can pass non-scalar variables (@array, %hash, etc.) to functions by
    Message 1 of 3 , Jul 13, 2009
    • 0 Attachment
      On Monday 13 July 2009 15:12:16 Tal Einat wrote:
      > On Mon, Jul 13, 2009 at 12:57 PM, Shlomi Fish wrote:
      > > On Monday 13 July 2009 12:00:23 Tal Einat wrote:
      > >> > 1. Syntax as an Indicative of What the Language is Doing:
      > >> > ---------------------------------------------------------
      > >> > I said I happen to like it because the extra characters convey
      > >> > meaning.
      > >>
      > >> Perl has very few built-in types; I recall numbers, strings, arrays,
      > >> hashes and functions. When you need to use anything else you are
      > >> forced to use references, which are indistinguishable from numbers and
      > >> require "casting" their targets' values back to their actual type.
      > >
      > > References are not numbers. They are different types of scalars. You can
      > > tell them apart using perldoc -f ref . You may be able to add a reference
      > > to a number, without a lot of meaning, or perform other arithmetic
      > > operations, but it's not encouraged.
      >
      > My point here was that because references are scalars like numbers and
      > strings, and references are used quite often, knowing that something
      > is a scalar means that it is either a "simple" scalar (number, string,
      > undef) or a reference (which can point to anything), so it isn't
      > obvious what type of underlying data it represents. My experience with
      > Perl found me using references very often, which made the sigils less
      > informative and more of a burden.

      I see. Well, you can tell what a reference is by how it is used. ->[], ->{}, -
      >(), ->method() , etc. are all different. It will be better in Perl 6, where
      one can pass non-scalar variables (@array, %hash, etc.) to functions by
      reference, as well as call methods on them directly. Hopefully, we'll see some
      of this in perl 5 too.

      >
      > >> In Python every class defines its own
      > >> comparison methods (if relevant), which Python uses when evaluating
      > >> "==" and friends. I can use "==" and ">=" and ">" to compare various
      > >> types of containers, such as lists, sets, tuples and dicts, and these
      > >> comparisons are simple and obvious. Besides making the code clean and
      > >> readable, things like this make learning Python less tedious.
      > >
      > > Can I also overload the meaning of these for my own containers? This may
      > > cause unexpected results. This is also the case for Perl with
      > > overloading.
      >
      > Yes, you can. However, doing so for non-trivial comparisons is highly
      > discouraged.
      >
      > The main point is that the comparison operators simply work for all of
      > the built-in classes as well as those in the standard library.
      > Normally you doesn't really have to think about such issues at all
      > since the normal comparison operators just do what you would expect.
      >

      I see.

      > >> > 4. Hiding Code
      > >>
      > >> Usually you just don't want someone to have your original version of
      > >> the code, so they don't copy/paste and develop their own product based
      > >> on your code.
      > >
      > > Well, Richard M. Stallman and other free software zealots will disagree
      > > with you on this. ;-) Even Python itself is distributed along with the
      > > original version of the code, so other people can copy/paste and develop
      > > their own product based on the code. Its licence even permits changing
      > > the licence of the code, including making it proprietary.
      >
      > I should have added "excluding open-source software" or something
      > before that... :)
      >

      My point was that even if you are distributing non-FOSS software (which is
      within your rights), you should still not depend on hiding your source code
      (especially in language that don't easily allow it) as a way of protecting it.
      Like I said, it's fig-leaf protection at best.

      > >> For this purpose obfuscation and/or compiling to
      > >> byte-code are enough.
      > >
      > > You may be right. However, I was under the impression that my
      > > conversation partner wanted even better protection.
      >
      > That is hard to achieve with any language! There are many decompilers
      > for C/C++ which do a pretty good job even on highly optimized code,
      > not just Java.

      Really? I'm surprised that the C/C++ decompilers are so advanced. I expected
      the current state of the art to be less than that.

      > The only way to ensure someone doesn't know what your
      > software is doing is to not have the software run on his computer.
      >

      Right.

      > >> (Obligatory: Writing in Perl is all the obfuscation one would ever need
      > >> ;)
      > >
      > > That's an old joke and was never particularly funny or true.
      >
      > Actually I was trying to have a serious conversation, and just
      > mentioned the usual trolling with a wink to show that I'm not like
      > that. No hard feelings I hope?
      >

      No, none. But next time try to be more explicit, or alternatively not throw
      oil into the fire at all.

      Regards,

      Shlomi Fish


      > - Tal
      > _______________________________________________
      > Python-il mailing list
      > Python-il@...
      > http://hamakor.org.il/cgi-bin/mailman/listinfo/python-il

      --
      -----------------------------------------------------------------
      Shlomi Fish http://www.shlomifish.org/
      Stop Using MSIE - http://www.shlomifish.org/no-ie/

      God gave us two eyes and ten fingers so we will type five times as much as we
      read.
    • 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 2 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 3 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.