An oddity in list comparison and element assignment

  • Thread starter michael.f.ellis
  • Start date
S

Slawomir Nowaczyk

#> I believe that 'is' tests equality of reference, such that
#>
#> >>> a = range(1,3)
#> >>> b = range(1,3)
#> >>> a is b
#> False
#>
#> The 'is' operator tells you whether a and b refer to the same object.
#> What I've been discussing is whether == should test for "structural"
#> equality so that a and b remain equivalent under parallel mutations
#> (and also under single mutations to common references)

What does "parallel mutations" mean? In particular, what should be the
results of each of the following three comparisons:

x, y, z = [1],[1],[1]
a, b = [x,y], [y,z]
c, d = [[1],[1]], [[1],[1]]
a == b
c == d
a[0].remove(1)
b[0].remove(1)
a == b

So, do I understand correctly that you would like first comparison
(a==b) to return "False" and second comparison (c==d) to return
"True"?

--
Best wishes,
Slawomir Nowaczyk
( (e-mail address removed) )

Living on Earth may be expensive, but it includes
an annual free trip around the Sun.
 
A

Alex Martelli

Hi Alex,
With all due respect to your well-deserved standing in the Python
community, I'm not convinced that equality shouldn't imply invariance
under identical operations.

So, why aren't you satisfying my request? Provide a simple concrete
definition of what your idea of equality WOULD behave like. I notice
that your lack of response stands out like a sore thumb -- all you're
providing is a set of constraints you desire and a collection of
illfounded analogies and handwaving. Traditional mathematics does not
support the concept of "change", nor the distinction between equality
and identity; the "real world" has no way to define what modifications
are "identical" except by their effects (if the results differ, either
the original equality was ill-posited or the modifications were not
"identical"). But the real world DOES have the concept of "performing
exactly the same sequence of operational steps", and, by THAT definition
of "equal modifications", then your assertion:
make identical modifications to the engines of two identical
automobiles, I expect the difference in performance to be identical.

is ill-founded -- or, rather, your *expectation* may be ill-founded.

Take two systems of any significant complexity that are similar enough
to be called "identical" by ALL observers (because trying to ascertain
the differences, if any, would inevitably perturb the systems
irretrievably by Heisenberg's effect -- i.e., there are no OBSERVABLE
differences, which by Occam's Razor requires you to posit the systems
are equal, because you cannot prove otherwise -- and entities must not
be multiplied beyond necessity, so supposing that "observably equal"
systems are indeed equal is Occam-compliant).

Now, perform "identical" (ditto) modifications: in the real world, due
to quantum effects, there WILL be sub-observable differences in what
you're doing to the first one and to the second one. If the systems are
unstable to start with, they may well amplify those differences to
observable proportions -- and there you are: the effect of the "equal"
change on "equal" system may easily become observably unequal.
Philosophically, you may classify this as an "observation" of both
systems, which reasoning backwards lead you to posit that either the
systems were NOT equal to start with or the modifications weren't...
that is, IF you also posit determinism, which, as well we know, is an
unwarrantedly strong hypothesis for systems in which the differences at
quantum level matter. Feel free to follow Einstein (and diverse
light-years away from the last few decades of physics) in positing that
there MUST exist "hidden variables" (unobservable except maybe in
destructive, irreversible ways) explaining the difference -- I'll stick
with the mainstream of physics and claim your expectation was badly
founded to start with.

I can debate epistemology with the best, but this is not really the
proper forum for this -- starting with the crucial distinction, what it
means, in mathematics OR in the real world, to state that two systems
are "equal but NOT identical"? In the end, such debates tend to prove
rather futile and unproductive, however.

In the world of programming languages, we cut through the chase by
requesting *operational* (Brouwer-ian, mathematically speaking)
definitions. Provide the *operational* definition of how you WANT
equality checking to work, contrast it with my simple two-lines one, and
THEN we can have a meaningful debate of which one is the correct one to
use in the core of a programming language that has the (blessing and
curse of) mutable data objects...


Alex
 
A

Alex Martelli

I agree with Alex that checking for this type of inequality is not a
trivial programming exercise. It requires (at least) a parallel

I'm not asking for ANY programming: I'm asking for a *straightforward
operational definition*. If the concept which you hanker after is NOT
subject to a straightforward operational definition, then I would rule
out that said concept could POSSIBLY be "natural".
Alternatively, it might make sense to disallow == for containers by
raising a TypeError although that would eliminate a largely useful
feature.

This may be the best example I've ever seen of Emerson's well-known
quote about foolish consistency -- except that I don't think this
behavior would be "consistent" (either wisely or foolishly) with
anything except a vague handwaving set of constraints whose
"naturalness" (assuming it's unfeasible to provide a good and
straightforward operational definition) is out of the question.


Alex
 
A

Alex Martelli

Slawomir Nowaczyk said:
#> I believe that 'is' tests equality of reference, such that
#>
#> >>> a = range(1,3)
#> >>> b = range(1,3)
#> >>> a is b
#> False
#>
#> The 'is' operator tells you whether a and b refer to the same object.
#> What I've been discussing is whether == should test for "structural"
#> equality so that a and b remain equivalent under parallel mutations
#> (and also under single mutations to common references)

What does "parallel mutations" mean? In particular, what should be the
results of each of the following three comparisons:

x, y, z = [1],[1],[1]
a, b = [x,y], [y,z]
c, d = [[1],[1]], [[1],[1]]
a == b
c == d
a[0].remove(1)
b[0].remove(1)
a == b

So, do I understand correctly that you would like first comparison
(a==b) to return "False" and second comparison (c==d) to return
"True"?

I sure hope not, since, e.g.:

ridiculous = c[0]

is not a "mutation" (so equality should still hold, right?), and then it
becomes weird to claim that

ridiculous.append('bah, humbug!')

is a "nonparallel mutation to" c and/or d.

In fact, I'm starting to wonder if by Michaels' requirement ANY
non-*IDENTICAL* containers (with non-identical mutable items) could EVER
be deemed "equal". If he's arguing that "==" should mean exactly the
same as "is", that's even crazier than I had gauged so far.

But of course, since Michaels still refuses to provide simple,
straightforward operational definitions of what it IS that he wants, all
of this remains vague and ill-defined. See *WHY* it's so important to
provide precision rather than just the handwaving he's given so far?


Alex
 
A

Alex Martelli

Slawomir Nowaczyk said:
#> Scott David Daniels wrote:
#> > Would you say that envelope containing five $100 bills is equal to
#> > an envelope containing five $100 bills with different serial numbers?

#> Yes (unless I was testing the assertion that the second envelope did
#> not contain counterfeits of the first)

So, what if Bank of America later decided that bills with serial
numbers containing "7" are no longer valid?

Then Wachowia would no doubt be happy to take my business away from
BoA;-).

I suspect you believe BoA is some kind of "official" body -- it isn't,
just like Deutschebank is not one in Germany (rather, Bundesbank is).

Just to share some tidbits (about which, as an Italian now living
between San Francisco and San Jose, I'm sort of proud of...!-)...:

Bank of America is a private bank, founded in San Francisco more than
100 years ago by an Italian-American guy (Amadeo Giannini, born in San
Jose, CA, but to Italian-born parents) as "Bank of Italy", then renamed
in 1930 in part because the Italian State bank "Banca d'Italia"
objected. It rose to prominence right after the SF earthquake of 100
years ago, by opening and staffing a temporary branch to ensure
depositors could access their money when they most needed it, while most
other banks were staying closed.

In other word, *if* you assume equality must be preserved by future
modifications, than no two different (modifiable) objects can ever be
really equal.

Yes, apart from the (slight and understandable!) mistake about BoA's
role, this is an excellent example. Here, a global change (to the rule
about what banknotes are "equal" to each other, by making some of them
invalid and thus unequal to others) perturbs Michaels' desired "strong
equality definition" -- to preserve it, equality must degenerate to
identity. A Python example would be a change to the default encoding
(not officially supported but achievable through a reload(sys), hint;-)
which could easily make a bytestring equal, or not, to a Unicode string!


Alex
 
M

Maric Michaud

Le Vendredi 02 Juin 2006 00:12, (e-mail address removed) a écrit :
I believe that 'is' tests equality of reference, such that


False

The 'is' operator tells you whether a and b refer to the same object.

Yeah ! That's it. And you proposed a definition of identity :
for all operator op, op(a) = op(b) => a = b
This is of poor use in real life where two thing are never identical, just
comparable.
What I've been discussing is whether == should test for "structural"
equality so that a and b remain equivalent under parallel mutations
(and also under single mutations to common references)

So you wanted a comparison opertor of twto sequence dafined like this :

seq1 == seq2 => for all e in seq1, seq2[seq1.index(e) *is* e

!!! this would not be very useful nor consistent I guess and prefer the one
used in python :

seq1 == seq2 => for all e in seq1, seq2[seq1.index(e) == e

--
_____________

Maric Michaud
_____________

Aristote - www.aristote.info
3 place des tapis
69004 Lyon
Tel: +33 426 880 097
 
S

Slawomir Nowaczyk

#> > What does "parallel mutations" mean? In particular, what should be the
#> > results of each of the following three comparisons:
#> >
#> > x, y, z = [1],[1],[1]
#> > a, b = [x,y], [y,z]
#> > c, d = [[1],[1]], [[1],[1]]
#> > a == b
#> > c == d
#> > a[0].remove(1)
#> > b[0].remove(1)
#> > a == b
#> >
#> > So, do I understand correctly that you would like first comparison
#> > (a==b) to return "False" and second comparison (c==d) to return
#> > "True"?
#>
#> I sure hope not,

So do I, but that's how I understood Michaels' words...

#> In fact, I'm starting to wonder if by Michaels' requirement ANY
#> non-*IDENTICAL* containers (with non-identical mutable items) could
#> EVER be deemed "equal". If he's arguing that "==" should mean
#> exactly the same as "is", that's even crazier than I had gauged so
#> far.

I think he explicitly said that "is" doesn't fulfill his requirements
either... but then, I am not sure as I do not understand what his
requirements actually are (they seem to make some sense for immutable
objects, but how should they generalise to mutable stuff I have no
idea).

PS. Thanks for explanation about Bank of America: I had no clue how it
works in realty, it just had a good name ;)

--
Best wishes,
Slawomir Nowaczyk
( (e-mail address removed) )

Java is clearly an example of a MOP (money-oriented programming)
-- Alexander Stepanov
 
A

Aahz

Just to share some tidbits (about which, as an Italian now living
between San Francisco and San Jose, I'm sort of proud of...!-)...:

Bank of America is a private bank, founded in San Francisco more than
100 years ago by an Italian-American guy (Amadeo Giannini, born in San
Jose, CA, but to Italian-born parents) as "Bank of Italy", then renamed
in 1930 in part because the Italian State bank "Banca d'Italia"
objected. It rose to prominence right after the SF earthquake of 100
years ago, by opening and staffing a temporary branch to ensure
depositors could access their money when they most needed it, while most
other banks were staying closed.

Except, of course, that BofA doesn't exist anymore. Oh, the *name*
does, but what's now called BofA is simply the current name of the bank
that acquired BofA.
 
T

Terry Reedy

Aahz said:
Except, of course, that BofA doesn't exist anymore. Oh, the *name*
does, but what's now called BofA is simply the current name of the bank
that acquired BofA.

In Pythonese, they performed

SomeBank.extend(BofA)
BofA = SomeBank
del SomeBank

so that id(BofA) is now what id(SomeBank) was, not what was id(the BofA I
grew up with). The name was definitely part of of the acquisition value.

;-)

OT, but not completely irrelevant to a discussion of names, ids, and
values.

Terry Jan Reedy
 
T

Terry Hancock

Alex said:
Then Wachowia would no doubt be happy to take my business away from
BoA;-).

I suspect you believe BoA is some kind of "official" body -- it
isn't, just like Deutschebank is not one in Germany (rather,
Bundesbank is).

Yeah, it's a funny mistake, but what he meant, is what if the
US Treasury Department declared bills with serial numbers
containing "7" invalid. That would indeed complete the analogy.

And it's a sharp example -- because money is conceived of as
fungible, one $100 is as good as another, so two $100 bills
compare as equal, whether they are equal or not.

Of course, the counter argument is that it's not unlike counting
a reflection of a $100 bill as another $100 and concluding that
you have $200 (you need two mirrors to double your money,
technically ;-)).

I don't think there's any way to make it "more logical" -- it's
going to break somewhere no matter what assumption you
make, so you just have to learn what's really going on in order
to avoid confusion.

Cheers,
Terry
 
T

Terry Hancock

Alex said:
to be called "identical" by ALL observers (because trying to
ascertain the differences, if any, would inevitably perturb the
systems irretrievably by Heisenberg's effect

Not to detract from your point, but the "Heisenberg effect", if
you mean the "Heisenberg uncertainty principle" is much more
fundamental (and quantumly "spooky") than this.

You are merely talking about the observer disturbing the system
by the process of observation, which is a common problem, but
has nothing to do with Heisenberg, and AFAIK, doesn't really
have a name. It's a normal application of classical physics.

I'm sorry to nitpick, it's just that it's one of those misconceptions
that never wants to die, like thinking that gravity is caused by
magnetism or the Earth's rotation, or that you can "get too close
and be 'sucked in' by a strong gravity field", or that things are
"weightless" in orbit, because they're "too far from the Earth's
gravity".

Cheers,
Terry
 
M

michael.f.ellis

Perhaps a little background to my original post will defuse some of the
controversy. While working during an airline flight, I ran into an
unexpected outcome from using the * replication operator to initialize
an array of lists. When I modified a single element of the array an
entire column changed. Having no reference books or internet access
available, I tried to understand what was going on by creating some
small arrays on the command line to see if there was a difference
between explicit initialization and initialization with range() and the
* operator.

The arrays looked identical when printed and a == b returned True. Yet
the arrays were clearly not equivalent because mutating the
corresponding elements produced different outcomes. I put the problem
aside until the next day when I looked at it some more and and created
the example script I posted. Just as I was about to hit the Send
button, I realized that the * operator must have been creating
references instead of copies. And then I appended the now much debated
opinion that == should have detected the difference.

(As an aside, may I point out that Python In A Nutshell states on page
46 "The result of S*n or n*S is the concatenation of n copies of S". It
might be well to put a warning in a future edition that this is not
strictly the case.)

My viewpoint is that of a working professional software consultant.
I'm essentially a pragmatist with no strong 'religious' views about
languages and methodologies. As I noted in an earlier reply, I don't
realistically expect Python to change the behavior of the == operator.
I do think that a problem arose when it was adopted from C and extended
to allow comparison of containers. In C, you can use it to compare
integers, floats, and pointers and everyone understands that p==q does
not imply *p == *q. Moreover, compilers issue warnings about
comparisons between different types.

Basically, I'm looking for simple diagnostic tools that make it easy to
understand what's really going on when code produces an unexpected
result. A 'strengthened equivalence' operator, to use your terminology
would have been useful to me.

As to constructing pseudocode for such an operator, I've appended a
working script below. The counterexamples and questions from Slawomir,
Maric, and Jim were really useful in sharpening my thinking about the
matter. I'm sure there are many ways to break it. For example, tuples
have no index method, so one would have to be written. Still, I hope it
will serve to move the discussion beyond terms like 'crazy' and
'handwaving' and 'ill-founded'. I haven't used such perjoratives in
any of my posts and would appreciate the same courtesy.

Cheers,
Mike

'''
StrongEquality -- a first cut at the definition proposed by M. Ellis.
Author: Michael F. Ellis, Ellis & Grant, Inc.
'''

def indices(item,seq):
'''Utility function that returns a list of indices where item occurs
in seq'''
result=[]
for i in xrange(len(seq)):
try:
result.append(i+seq[i:].index(item))
except ValueError:
return result

def StrongEquality(a,b):
'''True if a and b are numerically and "structurally" equal'''
if a is b: return True
if a != b: return False
## At this point we know a and b have the same length and
## evaluate numerically equivalent. We now need to figure out
## whether there are any references to identical objects in
non-corresponding
## positions of a & b (per Slawomir's example). We also need to
inspect
## a and b for non-matching patterns of identical references (per
my example)
ida=[] ; idb=[]
for i in xrange(len(a)):
if a is b:
continue
if isinstance(a, (int, float, str)) and isinstance(b,
(int, float, str)):
continue ## we already know they're numerically
equal

ida.append(id(a))
idb.append(id(b))
## We know that ida[n] is not idb[n] for all n because we
omitted all
## cases where a is b. Therefore Slawomir's example is
detected if
## any id appears in both lists.
for n in ida:
if n in idb: return False
## Next we test for my example. I'm sure this can be coded
more
## more elegantly ...
for j in xrange(len(ida)):
if indices(ida[j],ida) != indices(idb[j],idb): return
False
## Lastly, recurse ...
if not StrongEquality(a,b): return False

return True

if __name__=='__main__':
## Rudimentary test cases
assert StrongEquality(1,1)
assert not StrongEquality(0,1)

## Slawomir's example
x, y, z = [1],[1],[1]
a, b = [x,y], [y,z]
c, d = [[1],[1]], [[1],[1]]
assert StrongEquality(c,d)
assert a == b
assert not StrongEquality(a,b)

## My example
a =[[[1,2],[1,2]],[[1,2],[1,2]]]
b = [[range(1,3)]*2]*2
assert a==b
assert not StrongEquality(a,b)

print "All tests ok."
 
T

Terry Reedy

(As an aside, may I point out that Python In A Nutshell states on page
46 "The result of S*n or n*S is the concatenation of n copies of S".

It would be more exact to say that S*n is [] extended with S n times,
which makes it clear that 0*S == S*0 == [] and which avoids the apparently
misleading word 'copy'. I presume the C implementation is the equivalent
of

def __mul__(inlist, times):
result = []
for i in range(times):
result.extend(inlist)
return result

Or one could say that the result *is the same as* (not *is*) the
concatenation of n *shallow* copies of S. 'Shallow' means that each copy
of S would have the same *content* (at the id level) as S, so that the
result would contain the content of S n times, which is to say, when len(S)
== 1, n slots with each slot bound to the *identical* content of S.

When the content is immutable, the identicaliy does not matter. When it
*is* mutable, it does.
It might be well to put a warning in a future edition that this is not
strictly the case.)

Did you mean anything else by 'not strictly the case'?

Terry Jan Reedy
 
A

Alex Martelli

(As an aside, may I point out that Python In A Nutshell states on page
46 "The result of S*n or n*S is the concatenation of n copies of S". It
might be well to put a warning in a future edition that this is not
strictly the case.)

Can you give me an example where, say, for a sequence S,

x = S * 3

is not structurally the same as

x = copy.copy(S) + copy.copy(S) + copy.copy(S)

....? That is, where the "* 3" on a sequence is NOT the concatenation of
three copies (ordinary copies, of course!) of that sequence? I don't
think you can... and I can't repeatedly explain or point to the
distinction between normal, ordinary, shallow copies on one side, and
"deep copies" on the other, every single time in which that distinction
MIGHT be relevant (because some reader might not be aware of it); such
endless repetition would bloat the Nutshell totally away from its role
as a CONCISE desktop reference, and seriously hamper its usefulness
(particularly by DESTROYING any trace of usefulness for anybody who's
finally *GOT* this crucial bit, but not just in that way).

languages and methodologies. As I noted in an earlier reply, I don't
realistically expect Python to change the behavior of the == operator.

Then you might have avoided trying to convince anybody, or even trying
to IMPLY, that in an ideal version of Python == *SHOULD* behave your way
-- Python's semantics *ARE* entirely up for rediscussion at the moment,
with an eye on the future "Python 3000" release, so this is one of the
very rare periods of the history of the language where backwards
incompatibility of a potential change is _NOT_ a blocking point.

By asserting that your version of == would be "more natural", and trying
to defend that assertion by vague handwaving references to maths and
"real world", you managed to entirely shift MY mindstate (and possibly
that of several other discussants) into one of total and absolute
opposition to the proposal -- having by now spent considerable time and
energy pondering and debating the issue, I am now entirely convinced
that a language with such an == operator instead of Python's current one
would be such a total, unadulterated disaster that I would refuse to use
that language, no matter what other "good" features it might present to
me. I've walked away from great jobs, just because they would have
required me to use some technology I just could not stand, more than
once already in my life: and this IS how strongly (and negatively) I
feel about your claim that, for built-in ==, your semantics would be in
any way preferable to Python's.

By managing to thus focus my mindset (and make me spend my energy and
time) in opposition to your claims of "more natural", you have at least
managed to ensure that I will not now lend any scrap of help or support
to your debugging needs. If you were as pragmatic as you claim to be,
this kind of consideration WOULD have weighed highly in your choices.

I.ie., if you had WANTED to attract any such support and help, a
completely different attitude than that "most natural" claim would have
been ENORMOUSLY more productive -- and your continuing attempts to
debate that issue aren't helping AT ALL either:
I do think that a problem arose when it was adopted from C and extended
to allow comparison of containers. In C, you can use it to compare
integers, floats, and pointers and everyone understands that p==q does
not imply *p == *q.

If that is so, then everyone is utterly, totally, entirely, horribly
*WRONG*, because, in C, p==q ***DOES*** imply *p == *q (whenever p --
and by consequence q, given equality -- may legitimately be
dereferenced: p == q == 0 does not imply anything about *p and/or *q,
which may produce random results, crash the process, or whatever -- of
course).

You no doubt meant to say something entirely different from what you
ACTUALLY said, but I respectfully suggest you spare your breath rather
than keep trying to defend an indefensible position.

I do NOT agree, and I cannot imagine any state of the world that would
get me to agree, with your claim that "a problem arose" by allowing
equality comparison of containers in Python (many other languages allow
such comparisons, BTW; I would consider it a horrible wart if a language
claiming to be "higher level" did NOT). That you're "supporting" (HA!)
your absurd claim with an equally absurd (and obviously, wholly false,
unfounded, and misplaced) claim about C pointers doesn't "help", of
course, but even perfectly accurate claims about C (or machine code, or
Cobol, or RPG...) would be pretty much uninteresting and irrelevant.
Moreover, compilers issue warnings about
comparisons between different types.

Some do, some don't, depending on the case -- e.g., I do not believe
that even with -Wall (or the equivalent setting) any C compiler whines
about EQUALITY comparisons of signed and unsigned integers (as well they
shouldn't, of course)!

And, just as of course, this umpteenth side-path you're introducing has
really nothing to do with the case, since when you're comparing two
lists-containing-lists which are equal by Python's rules but according
to your original claims about what's "more natural" ``should not'' be,
you ARE anyway comparing object of equal types.
Basically, I'm looking for simple diagnostic tools that make it easy to
understand what's really going on when code produces an unexpected
result. A 'strengthened equivalence' operator, to use your terminology
would have been useful to me.

A *FUNCTION* performing such checks in a debugging and diagnostics
package would have been -- and if you hadn't pushed me to spend so much
time and energy defending Python's design choices against your claims
that other choices would be "more natural", you might have gotten help
and support in developing it. But you chose to make ill-founded claims
of "more natural", and therefore you got a flamewar instead: your
choice.
will serve to move the discussion beyond terms like 'crazy' and
'handwaving' and 'ill-founded'. I haven't used such perjoratives in
any of my posts and would appreciate the same courtesy.

You claimed that Python's semantics are "contrary to one of my
fundamental expectations", "an oddity", resulting only (you said in your
second post) from a "performance and memory optimization", and tried to
justify this severe criticism of Python by vague (i..e, "handwaving")
appeals to analogies with "maths" and "the real world".

I do not believe that such scathing criticism had any sound foundations,
nor that calling it "ill-founded" is anything but a fittingly accurate
description: and a language where the == operator DID satisfy the
constraints you claimed to desire for *THE EQUALITY OPERATOR ITSELF* (as
opposed to, for some helper/checker function in a separate module for
checking and debugging) would be a crazy one indeed. If my opinions
that, I believe, accurately reflect the facts of the case, sound
"pejorative" to you, well, that's not a matter of choice of words on my
part, as much as of your choice of what to express in the first place.

Take your recent claim that in C "everyone understands that p==q does
not imply *p == *q"; which of the many ("pejorative") adjectives I
tagged your assertion with do you think are inaccurate or inappropriate?
I called it wrong, absurd, false, unfounded, and misplaced, and seasoned
the mix with a choice of adverbs including "utterly" and "horribly". It
appears to me that each of these adjectives and adverbs is appropriate
and accurate (though it's repetitious on my part to use them all, that
repetition does convey the intensity of my opinions in the matter).

This is a factual issue where it's easy to defend strongly held opinions
(which may be checked against "facts"); in matters of "should" (what
semantics "should" a certain language construct HAVE, in order to be
most natural, simplest, and most useful -- quite apart from any issues
of optimization) such ease is, alas, not given... but the fact that
veryfying clashing opinons about what "should" be the case is way harder
than opinions easily checkable against "facts", does not mean that the
"should"'s (which are even more important, potentially, in their effect
on future language design!) are any less important -- on the contrary.


I do not believe I am going to follow this thread any more; I wish you
best of luck in your future endeavors -- and, if you can get back to
being the pragmatist that you claim to be, perhaps in the future you may
chose to express your debugging needs and desiderata in ways that
dispose the experts on some give technology to help and support you,
rather than to fight against the damage which, they opine, it would
cause to the future of that technology if certain ("crazy") suggestions
were to be part of it.


Alex
 
A

Alex Martelli

Terry Reedy said:
(As an aside, may I point out that Python In A Nutshell states on page
46 "The result of S*n or n*S is the concatenation of n copies of S".

It would be more exact to say that S*n is [] extended with S n times,
which makes it clear that 0*S == S*0 == [] and which avoids the apparently
misleading word 'copy'. I presume the C implementation is the equivalent

Considering that the very next (and final) sentence in that same
paragraph is "If n is zero or less than zero, the result is an empty
sequence of the same type as S", I don't think there's anything
misleading in the quoted sentence. Moreover, since the paragraph is
about sequences, not just lists, it *WOULD* be horribly wrong to use the
phrasing you suggest: "bah!"*3 is NOT a list, it's EXACTLY the
concatenation of three copies of that string -- no more, no less.
Or one could say that the result *is the same as* (not *is*) the

I find this distinction, in this context, to be empty padding, with zero
added value on ANY plane -- including the plane of "pedantry";-).
concatenation of n *shallow* copies of S. 'Shallow' means that each copy

I do not think it would be good to introduce the concept of "shallow" at
a point in the text which is talking about ALL sequences -- including
ones, such as strings, for which it just does not apply.

But, thanks for the suggestions, anyway!


Alex
 
A

anton.vredegoor

Alex Martelli wrote:

[snip]

Can somebody please shut down this bot? I think it's running out of
control. It seems to be unable to understand that "don't be evil" might
be good when you're small (at least it's not very bad) but that it
becomes distinctly evil when you're big.

What is good when you're big? I really don't know and I think there's
even not many other people who do. But simply forbidding things that are
not precisely definable -the way mathematicians have been doing before
physicists shook them out of it- seems to do more harm than good.

In my opinion it looks like there is a path from rigid rule adherence to
slowly accepting more doubt and inconsistencies -because we're all
adults here- and this has something to do with letting go of things like
childish adherence to static typing and confusion between equality and
identity.

Let me qualify that last paragraph before anyone concludes I have become
disfunctional too and will lead everyone to their destruction.

There seem to always be certain unclear parts in a programming language
and people are constantly trying out new structures in order to map some
new territory. I remember sets, generators and metaclasses. Only after
people noticing problems (don't modify the thing you're iterating over)
ways are found to solve them (you can if you put everything back just at
the right moment) and finally these ways are condensed into officially
endorsed coding practices. Now we're struggling with immutability and
sequences. They're not a problem if you know what you're doing, but what
exactly is it that those who know what they're doing do? It indicates
that maybe it's the birth of a new language construct.

But why should it stop there? I expect a certain openness and
willingness to discuss controversial matters from a community even if it
were only to educate newcomers. But it might be the case that such
willingness to accept doubt, without it turning into actively seeking it
-that seems to be foolish, but who am I to judge even that- is what
makes it possible to develop higher language and cognitive structures.

Anton

'even if it means turning into lisp before moving on'
 
A

Alex Martelli

Alex Martelli wrote:

[snip]

Can somebody please shut down this bot? I think it's running out of

Much as you might love for somebody to "shut me down", that
(unfortunately, no doubt, from your viewpoint) is quite unlikely to
happen. Although "making predictions is always difficult, especially
about the future", the most likely course of events is that I shall
continue for a while to survive, probably in tolerable health.

BTW, and for your information: in modern Western society, publically
wishing for some adversary's death is often considered somewhat uncouth
and rude, except perhaps in times of war or similar extremities. Being
aware of such social niceties and conventions may help: even were I to
wish that somebody crushed you underfoot like the worm you are, I would
avoid expressing such a wish in public, and likely in private too.


Alex
 
A

anton.vredegoor

Alex said:
Much as you might love for somebody to "shut me down", that
(unfortunately, no doubt, from your viewpoint) is quite unlikely to
happen. Although "making predictions is always difficult, especially
about the future", the most likely course of events is that I shall
continue for a while to survive, probably in tolerable health.

You've got that completely wrong. I was not trying to kill you but I was
trying to revive you. A process that is not evolving is dead. Stopping
it frees up valuable resources that enable it to become alive again.

Anton

'being alive is being mutable'
 
M

michael.f.ellis

Hey Alex, lighten up! Python is a programming language -- not your
family, religion, or civil rights.
Cheers,
Mike
 
T

Terry Reedy

Alex, in responding to this sentence lifted out of context by Michael, I am
responding more to him and his claim of 'not strictly the case' than to
you. What I wrote is also more a draft of a paragraph for a book of mine
(of no competition to yours) than a suggestion for a future edition of your
book.
It would be more exact to say that S*n is [] extended with S n times,

A**b is often explained as 'A multiplied by itself b times' or some such.
It is more exact to say it is '1 multiplied by A b times'
which makes it clear that 0*S == S*0 == []

which makes it clear that A**0, including 0**0, is 1.

Given the number of people, including Michael, who have posted puzzlement
based on their confusion as to what does and does not get copied, I don't
think it unfair to call 'copy' 'apparently misleading. My intention in
this phrase is to suggest that one who misunderstands 'copy' in this
context will be mislead while one who understands just what is copied and
what is not copied will not.

The point of my code snippet was to explain/illustrate what is copied.
While it will (obviously) only executive as Python code for lists, I
believe the algorithm is generic if the initial assignment and list.extend
method are suitably interpreted.

Of course, I presume that in the CPython code, the actual initialization is
more like (length one blank value) * (n*len(S)) followed by n slice
assignments, but the Python code for this would still be list specific and
would also be more complex, without much aiding comprehension of the
result.

Strings are a somewhat special case since the characters in the string are
not wrapped as Python objects unless and until extracted from the string.
So one cannot as easily talk about the object(s) contained in the sequence.
Considering that the very next (and final) sentence in that same
paragraph is "If n is zero or less than zero, the result is an empty
sequence of the same type as S", I don't think there's anything
misleading in the quoted sentence.

In its original context, with respect to that issue, no. But as I said, I
was responding to Michael's removed-from-context quotation and his claim
about the need for a warning. I wonder if you read down to the end, where
I asked him whether I had missed anything he might find fault with, before
you responded.
Moreover, since the paragraph is about sequences, not just lists,

This *thread* is about repetition of lists, and in particular, a list of
one (or more) lists, and the consequences of the mutability of the inner
lists, and that is the context in which I wrote.
it *WOULD* be horribly wrong to use the phrasing you suggest:

In a generic context, [] would obviously have to be replaced by 'null
sequence of the type of S', which in many cases is type(S)(). And 'extend'
would have to be interpreted generically, as something the interpreter
would do behind the scenes in type(S). __new__, although as I said before,
I don't think that is exactly what it does do.
"bah!"*3 is NOT a list,
Duh.,

it's EXACTLY the
concatenation of three copies of that string -- no more, no less.

Depends what one means by 'copy'. See below for your alternate wording.
I find this distinction, in this context, to be empty padding, with zero
added value on ANY plane -- including the plane of "pedantry";-).

Perhaps you should tone down the overwrought emotionalism and take a look
in a mirror. In *your* response to Michael you made the *same*
distinction:

I agree that adding 'structurally' makes the 'padding' even better.
I do not think it would be good to introduce the concept of "shallow" at
a point in the text which is talking about ALL sequences -- including
ones, such as strings, for which it just does not apply.

Again, I was not suggesting that you do so. Adding 'shallow' was
intentially pedantic for Michael's 'benefit'. To be clear, I was *NOT*
supporting his warning suggestion.
But, thanks for the suggestions, anyway!

We both have the goal of expaining Python better so beginners hit fewer
bumps on the road.

Terry Jan Reedy
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,297
Messages
2,571,536
Members
48,283
Latest member
SherriP988

Latest Threads

Top