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:
> 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
> 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"
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
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
> > 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.
> > 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 = 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
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.
> > 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.
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