Re: why () is () and [] is [] work in other way?

2012-05-01 Thread Albert van der Horst
In article 7xvckq4c2j@ruckus.brouhaha.com,
Paul Rubin  no.email@nospam.invalid wrote:
Kiuhnm kiuhnm03.4t.yahoo.it writes:
 I can't think of a single case where 'is' is ill-defined.

If I can't predict the output of

print (20+30 is 30+20)  # check whether addition is commutative
print (20*30 is 30*20)  # check whether multiplication is commutative

by just reading the language definition and the code, I'd have to say
is is ill-defined.

The output depends whether the compiler is clever enough to realise
that the outcome of the expressions is the same, such that only
one object needs to be created.

What is ill here is the users understanding of when it is appropriate
to use is. Asking about identity of temporary objects fully
under control of the compiler is just sick.


Groetjes Albert

--
-- 
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert@spearc.xs4all.nl =n http://home.hccnet.nl/a.w.m.van.der.horst

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-29 Thread Kiuhnm

On 4/28/2012 16:18, Adam Skutt wrote:

On Apr 28, 7:26 am, Kiuhnmkiuhnm03.4t.yahoo.it  wrote:

On 4/27/2012 19:15, Adam Skutt wrote:

On Apr 27, 11:01 am, Kiuhnmkiuhnm03.4t.yahoo.itwrote:

The abstraction is this:
- There are primitives and objects.
- Primitives are not objects. The converse is also true.
- Primitives can become objects (boxing).
- Two primitives x and y are equal iff x == y.
- Two objects x and y are equal iff x.equals(y).
- Two objects are the same object iff x == y.
- If x is a primitive, then y = x is a deep copy.
- If x is an object, then y = x is a shallow copy.
- ...



This is not an abstraction at all, but merely a poor explanation of
how things work in Java.  Your last statement is totally incorrect, as
no copying of the object occurs whatsoever.  The reference is merely
reseated to refer to the new object. If you're going to chide me for
ignoring the difference between the reference and the referent object,
then you shouldn't ignore it either, especially in the one case where
it actually matters!  If we try to extend this to other languages,
then it breaks down completely.


With shallow copy I meant exactly that. I didn't think that my using the
term with a more general meaning would cause such a reaction.


It has a very strict, well-defined meaning in these contexts,
especially in languages such as C++.


In C++ it's called memberwise copy (see the C++ spec), which is not 
equivalent to Java's shallow copy, thanks to copy constructors.



So you're saying that I said that Primitive constructs are references.
Right...


No, still wrong.


You said:
You have the first statement backwards.  References are a primitive
construct, not the other way around.
The other way around is Primitive construct are references, but I 
never said that.



 What I said is correct, References are a form of
primitive construct.  In C, an int is a primitive but not a
reference.  An int* is a pointer (reference), and is also
(essentially) a primitive.


I never said it isn't.


  While true, it's still a bad way
to think about what's going on.  It breaks down once we add C++ /
Pascal reference types to the mix, for example.


?


Assignment to a C++ reference (T) effects the underlying object, not
the reference itself.  A reference can never be reseated once it is
bound to an object.  Comparing equality on two references directly is
the same as comparing two values (it calls operator==).  Comparing
identity requires doing (x ==y), like one would do with a value.
However, unlike a value, the object is not destroyed when the
reference goes out of scope.  Most importantly, references to base
classes do not slice derived class objects, so virtual calls work
correctly through references.

As a result, normally the right way to think about a value is as a
temporary name for an object and not worry about any of the details
about how the language makes it work.


If you add C++ references to Java, the abstraction breaks down too, so I 
don't see your point.



Equality or equivalence is a relation which is:
- reflexive
- symmetric
- transitive
Everything else... is something else. Call it semi-equality,
tricky-equality or whatever, but not equality, please.



Sure, but then it's illegal to allow the usage of '==' with floating
point numbers, which will never have these properties in any usable
implementation[1].


???



The operator == is called the equality operator.  Floating-point
numbers don't really obey those properties in any meaningful fashion.


I say they do. Any counter-examples?


The result is that portions of your view contradict others.  Either we
must give '==' a different name, meaning what you consider equality is
irrelevant, or we must use method names like 'equals', which you find
objectionable.


If anything, you have that backwards.  Look at Python: all variables
in Python have pointer semantics, not value semantics.



When everything is white, the word white becomes redundant.
So the fact that everything in Python have reference semantics means
that we can't stop thinking about value and reference semantics.



Nope. The behavior of variables is absolutely essential to writing
correct programs.  If I write a program in Python that treats
variables as if they were values, it will be incorrect.


You misunderstood what I said. You wouldn't treat variables as if they
were values because you wouldn't even know what that means and that
that's even a possibility.


Well, one hopes that is true.  I think we have a misunderstanding over
language: you said value and reference semantics when you really
meant value vs. reference semantics.


Ok.


I've never heard an old C programmer talk about value semantics and
reference semantics. When everything is a value, your world is pretty
simple.


Except if that were true, the comp.lang.c FAQ wouldn't have this
question and answer: http://c-faq.com/ptrs/passbyref.html, and several
others.


That's why I said an /old/ C programmer.


Much as 

Re: why () is () and [] is [] work in other way?

2012-04-29 Thread John Nagle

On 4/28/2012 4:47 AM, Kiuhnm wrote:

On 4/27/2012 17:39, Adam Skutt wrote:

On Apr 27, 8:07 am, Kiuhnmkiuhnm03.4t.yahoo.it wrote:

Useful... maybe, conceptually sound... no.
Conceptually, NaN is the class of all elements which are not numbers,
therefore NaN = NaN.


NaN isn't really the class of all elements which aren't numbers. NaN
is the result of a few specific IEEE 754 operations that cannot be
computed, like 0/0, and for which there's no other reasonable
substitute (e.g., infinity) for practical applications .

In the real world, if we were doing the math with pen and paper, we'd
stop as soon as we hit such an error. Equality is simply not defined
for the operations that can produce NaN, because we don't know to
perform those computations. So no, it doesn't conceptually follow
that NaN = NaN, what conceptually follows is the operation is
undefined because NaN causes a halt.


Mathematics is more than arithmetics with real numbers. We can use FP
too (we actually do that!). We can say that NaN = NaN but that's just an
exception we're willing to make. We shouldn't say that the equivalence
relation rules shouldn't be followed just because *sometimes* we break
them.


This is what programming languages ought to do if NaN is compared to
anything other than a (floating-point) number: disallow the operation
in the first place or toss an exception.


   If you do a signaling floating point comparison on IEEE floating
point numbers, you do get an exception.  On some FPUs, though,
signaling operations are slower.  On superscalar CPUs, exact
floating point exceptions are tough to implement.  They are
done right on x86 machines, mostly for backwards compatibility.
This requires an elaborate retirement unit to unwind the
state of the CPU after a floating point exception.  DEC Alphas
didn't have that; SPARC and MIPS machines varied by model.
ARM machines in their better modes do have that.
Most game console FPUs do not have a full IEEE implementation.

   Proper language support for floating point exceptions varies
with the platform.  Microsoft C++ on Windows does support
getting it right.  (I had to deal with this once in a physics
engine, where an overflow or a NaN merely indicated that a
shorter time step was required.)  But even there, it's
an OS exception, like a signal, not a language-level
exception.  Other than Ada, which requires it, few
languages handle such exceptions as language level
exceptions.


John Nagle
--
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-28 Thread Kiuhnm

On 4/27/2012 19:15, Adam Skutt wrote:

On Apr 27, 11:01 am, Kiuhnmkiuhnm03.4t.yahoo.it  wrote:

On 4/27/2012 1:57, Adam Skutt wrote:

On Apr 26, 6:34 pm, Kiuhnmkiuhnm03.4t.yahoo.itwrote:

If you

understand that your 'a' is not really an object but a reference to it,
everything becomes clear and you see that '==' always do the same thing.



Yes, object identity is implemented almost? everywhere by comparing
the value of two pointers (references)[1]. I've already said I'm not
really sure how else one would go about implementing it.



You might tell me that that's just an implementation detail, but when an
implementation detail is easier to understand and makes more sense than
the whole abstraction which is built upon it, something is seriously wrong.



I'm not sure what abstraction is being built here.  I think you have
me confused for someone else, possibly Steven.


The abstraction is this:
- There are primitives and objects.
- Primitives are not objects. The converse is also true.
- Primitives can become objects (boxing).
- Two primitives x and y are equal iff x == y.
- Two objects x and y are equal iff x.equals(y).
- Two objects are the same object iff x == y.
- If x is a primitive, then y = x is a deep copy.
- If x is an object, then y = x is a shallow copy.
- ...



This is not an abstraction at all, but merely a poor explanation of
how things work in Java.  Your last statement is totally incorrect, as
no copying of the object occurs whatsoever.  The reference is merely
reseated to refer to the new object. If you're going to chide me for
ignoring the difference between the reference and the referent object,
then you shouldn't ignore it either, especially in the one case where
it actually matters!  If we try to extend this to other languages,
then it breaks down completely.


With shallow copy I meant exactly that. I didn't think that my using the 
term with a more general meaning would cause such a reaction.

I don't agree on the other things you said, of course.




The truth:
- Primitives can be references.
- Two primitives are equal iff x == y.
- Operator '.' automatically derefences references.



You have the first statement backwards.  References are a primitive
construct, not the other way around.


So you're saying that I said that Primitive constructs are references. 
Right...



 While true, it's still a bad way
to think about what's going on.  It breaks down once we add C++ /
Pascal reference types to the mix, for example.


?


It's better to think about variables (names) and just recognize that
not all variables have the same semantics.  It avoids details that are
irrelevant to writing actual programs and remains consistent.


Maybe in your opinion. As I said, I don't agree with you.


Equality or equivalence is a relation which is:
- reflexive
- symmetric
- transitive
Everything else... is something else. Call it semi-equality,
tricky-equality or whatever, but not equality, please.


Sure, but then it's illegal to allow the usage of '==' with floating
point numbers, which will never have these properties in any usable
implementation[1].


???


 So we're back to what started this tangent, and we
end up needing 'equals()' methods on our classes to distinguish
between the different forms of equality.  That's precisely what you
want to avoid.

Or we can just accept that '==' doesn't always possess those
properties, which is what essentially every programming language does,
and call it (value) equality.  As long as we don't cross incompatible
meanings, it's hard to believe that this isn't the right thing to do.




If anything, you have that backwards.  Look at Python: all variables
in Python have pointer semantics, not value semantics.


When everything is white, the word white becomes redundant.
So the fact that everything in Python have reference semantics means
that we can't stop thinking about value and reference semantics.


Nope. The behavior of variables is absolutely essential to writing
correct programs.  If I write a program in Python that treats
variables as if they were values, it will be incorrect.


You misunderstood what I said. You wouldn't treat variables as if they 
were values because you wouldn't even know what that means and that 
that's even a possibility.
I've never heard an old C programmer talk about value semantics and 
reference semantics. When everything is a value, your world is pretty 
simple.



  In imperative
languages, pointers have greater utility over value types because not
all types can obey the rules for value types.  For example, I don't
know how to give value semantics to something like a I/O object (e.g,
file, C++ fstream, C FILE), since I don't know how to create
independent copies.


By defining a copy constructor.


Then write me a working one.  I'll wait. To save yourself some time,
you can start with std::fstream.


Will you pay me for my time?

Your problem is that you think that copy semantics requires real 
copying. I really don't 

Re: why () is () and [] is [] work in other way?

2012-04-28 Thread Chris Angelico
On Sat, Apr 28, 2012 at 9:26 PM, Kiuhnm
kiuhnm03.4t.yahoo...@mail.python.org wrote:
 Your problem is that you think that copy semantics requires real copying. I
 really don't see any technical difficulty in virtualizing the all thing.

Copy semantics without real copying is an optimization that a
program should never need to be aware of. For instance, you could have
two 16GB strings share their buffers to avoid having to use 32GB of
memory; but to demonstrate copy semantics, they would need to
copy-on-write in some fashion. There's duplicate state but shared
memory. The trouble with duplicating state of a std::fstream is that
it's roughly impossible. You could perhaps simulate it with read-only
file access, but when you write, somehow it has to affect the disk,
and that means either you copy the file (but keep the same file name)
or have both of them affect the same file (meaning we're on Borg
semantics, not copying).

ChrisA
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-28 Thread Kiuhnm

On 4/27/2012 17:39, Adam Skutt wrote:

On Apr 27, 8:07 am, Kiuhnmkiuhnm03.4t.yahoo.it  wrote:

Useful... maybe, conceptually sound... no.
Conceptually, NaN is the class of all elements which are not numbers,
therefore NaN = NaN.


NaN isn't really the class of all elements which aren't numbers.  NaN
is the result of a few specific IEEE 754 operations that cannot be
computed, like 0/0, and for which there's no other reasonable
substitute (e.g., infinity) for practical applications .

In the real world, if we were doing the math with pen and paper, we'd
stop as soon as we hit such an error. Equality is simply not defined
for the operations that can produce NaN, because we don't know to
perform those computations.  So no, it doesn't conceptually follow
that NaN = NaN, what conceptually follows is the operation is
undefined because NaN causes a halt.


Mathematics is more than arithmetics with real numbers. We can use FP 
too (we actually do that!). We can say that NaN = NaN but that's just an 
exception we're willing to make. We shouldn't say that the equivalence 
relation rules shouldn't be followed just because *sometimes* we break them.



This is what programming languages ought to do if NaN is compared to
anything other than a (floating-point) number: disallow the operation
in the first place or toss an exception.  Any code that tries such an
operation has a logic error and must be fixed.

However, when comparing NaN against floating point numbers, I don't
see why NaN == NaN returning false is any less conceptually correct
than any other possible result.  NaN's very existence implicitly
declares that we're now making up the rules as we go along, so we
might as well pick the simplest set of functional rules.

Plus, floating point numbers violate our expectations of equality
anyway, frequently in  surprising ways.  0.1 + 0.1 + 0.1 == 0.3 is
true with pen and paper, but likely false on your computer.


Maybe wrong expectations of equality, since 0.1 (the real number) is 
/not/ a floating point.
Don't confuse the representation of floating points with the floating 
point themselves.



 It's even
potentially possible to compare two floating point variables twice and
get different results each time[1]!


We should look at the specification and not the single implementations.


 As such, we'd have this problem
with defining equality even if NaN didn't exist.  We must treat
floating-point numbers as a special case in order to write useful
working programs.  This includes defining equality in a way that's
different from what works for nearly every other data type.

Adam

[1] Due to register spilling causing intermediate rounding.  This
could happen with the x87 FPU since the registers were 80-bits wide
but values were stored in RAM as 64-bits.  This behavior is less
common now, but hardly impossible.


Kiuhnm
--
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-28 Thread Adam Skutt
On Apr 28, 7:26 am, Kiuhnm kiuhnm03.4t.yahoo.it wrote:
 On 4/27/2012 19:15, Adam Skutt wrote:
  On Apr 27, 11:01 am, Kiuhnmkiuhnm03.4t.yahoo.it  wrote:
  The abstraction is this:
  - There are primitives and objects.
  - Primitives are not objects. The converse is also true.
  - Primitives can become objects (boxing).
  - Two primitives x and y are equal iff x == y.
  - Two objects x and y are equal iff x.equals(y).
  - Two objects are the same object iff x == y.
  - If x is a primitive, then y = x is a deep copy.
  - If x is an object, then y = x is a shallow copy.
  - ...

  This is not an abstraction at all, but merely a poor explanation of
  how things work in Java.  Your last statement is totally incorrect, as
  no copying of the object occurs whatsoever.  The reference is merely
  reseated to refer to the new object. If you're going to chide me for
  ignoring the difference between the reference and the referent object,
  then you shouldn't ignore it either, especially in the one case where
  it actually matters!  If we try to extend this to other languages,
  then it breaks down completely.

 With shallow copy I meant exactly that. I didn't think that my using the
 term with a more general meaning would cause such a reaction.

It has a very strict, well-defined meaning in these contexts,
especially in languages such as C++.


 So you're saying that I said that Primitive constructs are references.
 Right...

No, still wrong.  What I said is correct, References are a form of
primitive construct.  In C, an int is a primitive but not a
reference.  An int* is a pointer (reference), and is also
(essentially) a primitive.


   While true, it's still a bad way
  to think about what's going on.  It breaks down once we add C++ /
  Pascal reference types to the mix, for example.

 ?

Assignment to a C++ reference (T) effects the underlying object, not
the reference itself.  A reference can never be reseated once it is
bound to an object.  Comparing equality on two references directly is
the same as comparing two values (it calls operator==).  Comparing
identity requires doing (x == y), like one would do with a value.
However, unlike a value, the object is not destroyed when the
reference goes out of scope.  Most importantly, references to base
classes do not slice derived class objects, so virtual calls work
correctly through references.

As a result, normally the right way to think about a value is as a
temporary name for an object and not worry about any of the details
about how the language makes it work.


  Equality or equivalence is a relation which is:
  - reflexive
  - symmetric
  - transitive
  Everything else... is something else. Call it semi-equality,
  tricky-equality or whatever, but not equality, please.

  Sure, but then it's illegal to allow the usage of '==' with floating
  point numbers, which will never have these properties in any usable
  implementation[1].

 ???


The operator == is called the equality operator.  Floating-point
numbers don't really obey those properties in any meaningful fashion.
The result is that portions of your view contradict others.  Either we
must give '==' a different name, meaning what you consider equality is
irrelevant, or we must use method names like 'equals', which you find
objectionable.

  If anything, you have that backwards.  Look at Python: all variables
  in Python have pointer semantics, not value semantics.

  When everything is white, the word white becomes redundant.
  So the fact that everything in Python have reference semantics means
  that we can't stop thinking about value and reference semantics.

  Nope. The behavior of variables is absolutely essential to writing
  correct programs.  If I write a program in Python that treats
  variables as if they were values, it will be incorrect.

 You misunderstood what I said. You wouldn't treat variables as if they
 were values because you wouldn't even know what that means and that
 that's even a possibility.

Well, one hopes that is true.  I think we have a misunderstanding over
language: you said value and reference semantics when you really
meant value vs. reference semantics.

 I've never heard an old C programmer talk about value semantics and
 reference semantics. When everything is a value, your world is pretty
 simple.

Except if that were true, the comp.lang.c FAQ wouldn't have this
question and answer: http://c-faq.com/ptrs/passbyref.html, and several
others.

Much as you may not like it, most code doesn't care about a pointer's
value, doesn't need to know anything about it, and would just as soon
pretend that it doesn't exist.  All it really wants is a controlled
way to mutate objects in different scopes.  Which is precisely why
references are preferred over pointers in C++, as they're a better
expression of programmer intent, and far safe as a result.

Peaking under the covers in an attempt to simplify the definition of
'==' is silly.  As I've hopefully shown by now, it's pretty much a

Re: Python id() does not return an address [was Re: why () is () and [] is [] work in other way?]

2012-04-28 Thread OKB (not okblacke)
Adam Skutt wrote:

 You can't treat id() as an address. Did you miss my post when I
 demonstrated that Jython returns IDs generated on demand, starting
 from 1? In general, there is *no way even in principle* to go from
 a Python ID to the memory location (address) of the object with
 that ID, because in general objects *may not even have a fixed
 address*. Objects in Jython don't, because the Java virtual
 machine can move them in memory. 
 
 Yes, there is a way.  You add a function deref() to the language.

This is getting pretty absurd.  By that logic you could say With 
Python, you can end all life on earth!  You just add a function to 
the language called nuclear_winter() that remotely accesses warhead 
launch sites in the US and Russia, enters the appropriate launch codes, 
and launches the entire nuclear arsenal!

-- 
--OKB (not okblacke)
Brendan Barnwell
Do not follow where the path may lead.  Go, instead, where there is
no path, and leave a trail.
--author unknown
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-27 Thread Paul Rubin
Steven D'Aprano steve+comp.lang.pyt...@pearwood.info writes:
 I'm seeing code generated by the Haskell GHC compiler being 2-4 times 
 slower than code from the C gcc compiler, and on average using 2-3 times 
 as much memory (and as much as 7 times).

Alioth isn't such a great comparison, because on the one hand you get
very carefully tuned, unidiomatic code for each language; but on the
other, you're somewhat constrained by the benchmark specs.  Obviously C
is not much above assembler, so you can write almost-optimal programs if
you code close enough to the metal and suffer enough.  If you're talking
about coding reasonably straightforwardly, C usually does beat Haskell
(once you've debugged the core dumps...) but there are exceptions to
that.

 Feel free to find your own set of benchmarks that show the opposite. I'd 
 be interested to see under what conditions Haskell might be faster than C.

Haskell wasn't included in this multi-way comparison, but Ocaml beat C
by a significant factor at a straightforward vector arithmetic loop,
because it didn't have to pessimize around possible pointer aliasing:

  http://scienceblogs.com/goodmath/2006/11/the_c_is_efficient_language_fa.php

GHC should be able to do similar things.

Also, here's a sort of cheating Haskell example: the straightforward
Haskell Fibonacci code is slower than C, but just sprinkle in a few
parallelism keywords and run it on your quad core cpu:

  http://donsbot.wordpress.com/2007/11/29/use-those-extra-cores-and-beat-c-today

Note the Haskell code in that example is using arbitrary-precision
integers while C is using int64's.  Yes, you could beat the GHC speed by
writing a lot more C code to manage Posix threads, locks, etc., but in
Haskell two do two things in parallel you can just say par.

There is also work going on to support parallel listcomps (just like
regular ones but they run on multiple cores), and vector combinators
that offload the computation to a GPU.  Those things are quite hard to
do in plain C, though there are some specialty libraries for it.

Finally, a less-cheating example (this is from 2007 and I think things
are even better now):

http://neilmitchell.blogspot.com/2007/07/making-haskell-faster-than-c.html

Gives a Haskell word count program

   main = print . length . words = getContents

which could also be written (if the syntax looks better to you):

   main = do
 text - getContents
 print (length (words text))

The comparison C code is:

int main() {
 int i = 0;
 int c, last_space = 1, this_space;
 while ((c = getchar()) != EOF) {
  this_space = isspace(c);
  if (last_space  !this_space)
   i++;
  last_space = this_space;
 }
 printf(%i\n, i);
 return 0;
}

and GHC/Supero beats the C code by about 10% even though both use
getchar.  The blog post explains, you could speed up the C code by
writing a rather contorted version, unrolling it into two separate
loops, one for sequences of spaces and one for non-spaces, and jumping
back and forth between the loops instead of using the last_space
variable.  That is basically the code that Supero figures out how to
generate: two separate loops with transitions in the right places,
starting from very straightforward high-level input.

I'm not really good at Haskell even after fooling with it on and off for
several years now, and it certainly can't beat Python for ease-of-use
without a lot of experience.  But in the hands of experts it is
incredibly powerful.  It makes Python seem almost like a toy.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-27 Thread Adam Skutt
On Apr 26, 10:56 pm, OKB (not okblacke)
brennospamb...@nobrenspambarn.net wrote:
 Adam Skutt wrote:
  If I write a function that does a value comparison, then it should
  do value comparison on _every type that can be passed to it_,
  regardless of whether the type is a primitive or an object, whether
  it has value or reference semantics, and  regardless of how value
  comparison is actually implemented.  If I write some function:
      f(x : T, y : U) = x == y
  where T and U are some unknown types, then I want the function to
  do a value comparison for every type pairing that allows the
  function to compile.  Likewise, if I write a function that does
  identity comparison, then it logically wants to do identity
  comparison on _every type that can be passed to it_.

         What you say here makes perfect sense, but also shows that you
 really shouldn't be using Python if you want stuff to work this way.  In
 Python any value of any type can be passed to any function.  The claims
 you are making about object identity and object equality are reasonable,
 but as you show here, to really handle them requires dragging in a huge
 amount of type-system baggage.

So the check gets deferred to runtime, and the programmer may need to
explictly throw 'NotImplemented' or something like that.  Which is
what happens in Python.  Not type-checking arguments simply moves the
burden from the language to the programmer, which is a standard
consequence of moving from static to dynamic typing.

Adam
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-27 Thread Steven D'Aprano
On Thu, 26 Apr 2012 18:02:31 +0200, Kiuhnm wrote:

 On 4/26/2012 16:00, Adam Skutt wrote:
 C# and Python do have a misfeature: '==' is identity comparison only if
 operator== / __eq__ is not overloaded.  Identity comparison and value
 comparison are disjoint operations, so it's entirely inappropriate to
 combine them.
 
 They're not disjoint, in fact one almost always implies the other (*).
 Python's idea is that, by default, any object is equal to itself and
 only itself. The fact that this is equivalent to identity comparison
 is just a coincidence, from a conceptual point of view.

Define your terms: what do you mean by equal?

The complication is that equal has many meanings. Does 1/2 equal 2/4?
Well, yes, numerically, but numerical equality is not the only useful
sense of equality -- not even for mathematicians! Although the convention 
to write 1/2 = 2/4 is too strong to discard, there are areas of 
mathematics where 1/2 and 2/4 are not treated as equal regardless of 
numerical equality.

http://en.wikipedia.org/wiki/Mediant_%28mathematics%29

In Python, equal can have any meaning we like, because we can override
__eq__. For most meaningful equality comparisons, we expect that X should
always equal itself, even if it doesn't equal anything else, and so __eq__
defaulting to an identity comparison if you don't override it makes good 
sense.

Some people (e.g. the creator of Eiffel, Bertrand Meyer) argue that 
identity should *always* imply equality (reflexivity). I disagree, but 
regardless, reflexivity is *almost always* the right thing to do.

When it comes to equality, Python defaults to sensible behaviour. By 
default, any object supports equality. By default, a == a is true for 
any object a. If you want to define a non-reflexive type, you have to do 
so yourself. If you want to define a type that doesn't support equality 
at all, you have to do so yourself. But both use-cases are vanishingly 
rare, and rather troublesome to use. It would be stupid for Python to 
make them the default behaviour.

After all, Python is a tool, not a philosophy. There's no need to force 
the user to start from a blank slate and define everything from first 
principles when you can start with the common tools you normally need, 
and add or subtract from it as needed.



 (*) nan == nan is false, but, at least conceptually, a 'NotComparable'
 exception should be raised instead. That wouldn't be very useful,
 though.

NANs are comparable. By definition, NAN != x for every x. They're just 
not reflexive.


 I don't necessarily mind if the two operations have the same symbol, as
 long as there's some other way in-context to determine which operation
 is occurring.  This is the case in C and C++, for example.

 Python's way is much much cleaner.

 Nope. Automatically substituting identity equality for value equality
 is wrong.  While rare, there are legitimate reasons for the former to
 be True while the latter is False.
 
 There shouldn't be, to be fair.

I disagree. Violating reflexivity has its uses. NANs are the classic 
example.

Another example is if you redefine == to mean something other than 
equals. If your class treats == as something other than equality, there 
is no need for a==a to necessarily return True.



-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-27 Thread Robert Kern

On 4/27/12 12:07 AM, Paul Rubin wrote:

Nobodynob...@nowhere.com  writes:

All practical languages have some implementation-defined behaviour, often
far more problematic than Python's.


The usual reason for accepting implementation-defined behavior is to
enable low-level efficiency hacks written for specific machines.  C and
C++ are used for that sort of purpose, so they leave many things
implementation-defined.  Python doesn't have the same goals and should
leave less up to the implementation.  Java, Ada, Standard ML, etc.  all
try to eliminate implementation-defined behavior in the language much
more than Python does.  I don't have any idea why you consider that to
be throwing the baby out with the bath water.


I think there are two implementation-defined behaviors that are being discussed 
in this thread. One is that some immutable objects like the empty tuple may be 
interned such that all instances of them are the same object and have the same 
identity. This is allowed for efficiency reasons. CPython has used this freedom 
to good effect. The optimization is not theoretical.


The other is that identities may be reused by different objects that do no 
coexist at the same time. This is to permit implementations where the ID is the 
address of the object in memory, like CPython. But other implementations with 
different memory models (including ones where address in memory doesn't make 
any sense) may forbid reuse of IDs. This allows alternative implementations like 
Jython and IronPython.


There are specific, deliberate, practical consequences of those two 
implementation-defined behaviors. These are the babies that you would be 
throwing out.


--
Robert Kern

I have come to believe that the whole world is an enigma, a harmless enigma
 that is made terrible by our own mad attempt to interpret it as though it had
 an underlying truth.
  -- Umberto Eco

--
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-27 Thread Steven D'Aprano
On Thu, 26 Apr 2012 11:31:39 -0700, John Nagle wrote:

 I would suggest that is raise ValueError for the ambiguous cases.
 If both operands are immutable, is should raise ValueError. That's the
 case where the internal representation of immutables shows through.

You've already made this suggestion before. Unfortunately you failed to 
think it through: it would break *nearly all Python code*, and not just 
broken code. It would break code that relies on documented language 
features. It would break code that applies a standard Python idiom. I 
count at least 638 places where your suggestion would break the standard 
library.

[steve@ando ~]$ cd /usr/local/lib/python3.2/
[steve@ando python3.2]$ grep if .* is None: *.py | wc -l
638

That's an average of four breakages per module.


 If this breaks a program, it was broken anyway.  

Incorrect. Your suggestion breaks working code for no good reason.

Astonishingly, your suggestion doesn't break code that actually is broken:

def spam(arg=None):
if arg == None:
   ...

actually is broken, since it doesn't correctly test for the sentinel. You 
can break it by passing an object which compares equal to None but isn't 
actually None.


-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-27 Thread Kiuhnm

On 4/27/2012 13:09, Steven D'Aprano wrote:

On Thu, 26 Apr 2012 18:02:31 +0200, Kiuhnm wrote:


On 4/26/2012 16:00, Adam Skutt wrote:

C# and Python do have a misfeature: '==' is identity comparison only if
operator== / __eq__ is not overloaded.  Identity comparison and value
comparison are disjoint operations, so it's entirely inappropriate to
combine them.


They're not disjoint, in fact one almost always implies the other (*).
Python's idea is that, by default, any object is equal to itself and
only itself. The fact that this is equivalent to identity comparison
is just a coincidence, from a conceptual point of view.


Define your terms: what do you mean by equal?


a and b are equal iff
  a = a
  a = b = b = a
  a = b and b = c = a = c
If some of this properties are violated, we're talking of something else.

The fact that you can define '==' whatever way you want is irrelevant. I 
call that calling 'equality' something which shouldn't be regarded as 
such and making Python comply with it anyway.



The complication is that equal has many meanings. Does 1/2 equal 2/4?
Well, yes, numerically, but numerical equality is not the only useful
sense of equality -- not even for mathematicians! Although the convention
to write 1/2 = 2/4 is too strong to discard, there are areas of
mathematics where 1/2 and 2/4 are not treated as equal regardless of
numerical equality.

http://en.wikipedia.org/wiki/Mediant_%28mathematics%29

In Python, equal can have any meaning we like, because we can override
__eq__. For most meaningful equality comparisons, we expect that X should
always equal itself, even if it doesn't equal anything else, and so __eq__
defaulting to an identity comparison if you don't override it makes good
sense.

Some people (e.g. the creator of Eiffel, Bertrand Meyer) argue that
identity should *always* imply equality (reflexivity). I disagree, but
regardless, reflexivity is *almost always* the right thing to do.

When it comes to equality, Python defaults to sensible behaviour. By
default, any object supports equality. By default, a == a is true for
any object a. If you want to define a non-reflexive type, you have to do
so yourself. If you want to define a type that doesn't support equality
at all, you have to do so yourself. But both use-cases are vanishingly
rare, and rather troublesome to use. It would be stupid for Python to
make them the default behaviour.

After all, Python is a tool, not a philosophy. There's no need to force
the user to start from a blank slate and define everything from first
principles when you can start with the common tools you normally need,
and add or subtract from it as needed.




(*) nan == nan is false, but, at least conceptually, a 'NotComparable'
exception should be raised instead. That wouldn't be very useful,
though.


NANs are comparable. By definition, NAN != x for every x. They're just
not reflexive.


As I said, I know they are but I think they shouldn't, at least 
conceptually.



I don't necessarily mind if the two operations have the same symbol, as
long as there's some other way in-context to determine which operation
is occurring.  This is the case in C and C++, for example.


Python's way is much much cleaner.


Nope. Automatically substituting identity equality for value equality
is wrong.  While rare, there are legitimate reasons for the former to
be True while the latter is False.


There shouldn't be, to be fair.


I disagree. Violating reflexivity has its uses. NANs are the classic
example.


Useful... maybe, conceptually sound... no.
Conceptually, NaN is the class of all elements which are not numbers, 
therefore NaN = NaN. The conceptually correct way would be to check for 
'NaN' explicitly.



Another example is if you redefine == to mean something other than
equals. If your class treats == as something other than equality, there
is no need for a==a to necessarily return True.


Then it wouldn't be equality anymore. I can always call a cat 'dog'.

Kiuhnm
--
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-27 Thread Chris Angelico
On Fri, Apr 27, 2012 at 10:07 PM, Kiuhnm
kiuhnm03.4t.yahoo...@mail.python.org wrote:
 Conceptually, NaN is the class of all elements which are not numbers,
 therefore NaN = NaN. The conceptually correct way would be to check for
 'NaN' explicitly.

Conceptually, single-digit-numbers is the class of all elements
which are integers [0,10). Does that mean that SdN = SdN, and
therefore that 2 = 5?

ChrisA
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-27 Thread Kiuhnm

On 4/27/2012 14:07, Kiuhnm wrote:

On 4/27/2012 13:09, Steven D'Aprano wrote:

On Thu, 26 Apr 2012 18:02:31 +0200, Kiuhnm wrote:


On 4/26/2012 16:00, Adam Skutt wrote:

C# and Python do have a misfeature: '==' is identity comparison only if
operator== / __eq__ is not overloaded. Identity comparison and value
comparison are disjoint operations, so it's entirely inappropriate to
combine them.


They're not disjoint, in fact one almost always implies the other (*).
Python's idea is that, by default, any object is equal to itself and
only itself. The fact that this is equivalent to identity comparison
is just a coincidence, from a conceptual point of view.


Define your terms: what do you mean by equal?


a and b are equal iff


Nope. What I meant is that we can talk of equality whenever...


a = a
a = b = b = a
a = b and b = c = a = c
If some of this properties are violated, we're talking of something else.


Kiuhnm
--
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-27 Thread Steven D'Aprano
On Fri, 27 Apr 2012 14:17:48 +0200, Kiuhnm wrote:

 Define your terms: what do you mean by equal?

 a and b are equal iff
 
 Nope. What I meant is that we can talk of equality whenever...
 
 a = a
 a = b = b = a
 a = b and b = c = a = c
 If some of this properties are violated, we're talking of something
 else.

Sorry, that won't do it. You haven't defined equality, or given any way 
of deciding whether two entities are equal. What you have listed are 
three *properties* of equality, namely:

- reflexivity (a = a)
- symmetry (if a = b then b = a)
- transitivity (if a = b and b = c then a = c)

But those three properties apply to any equivalence relation, not just 
equality. Examples:

both are odd (of integers)
have the same birthday (of people)
is congruent to (of triangles)
is in the same tax bracket (of tax payers)
has the same length (of pieces of string)
both contain chocolate (of cakes)

For example, if we define the operator ~ to mean has the same 
genes (to be precise: the same genotype), then if Fred and Barney are 
identical twins we have:

Fred ~ Fred
Fred ~ Barney and Barney ~ Fred

Identical triplets are rare (at least among human beings), but if we 
clone Barney to get George, then we also have:

Fred ~ Barney and Barney ~ George = Fred ~ George.

So have the same genes meets all your conditions for equality, but 
isn't equality: the three brothers are very different. Fred lost his arm 
in a car crash, Barney is a hopeless alcoholic, and George is forty years 
younger than his two brothers.



-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-27 Thread Kiuhnm

On 4/27/2012 1:57, Adam Skutt wrote:

On Apr 26, 6:34 pm, Kiuhnmkiuhnm03.4t.yahoo.it  wrote:

On 4/26/2012 20:54, Adam Skutt wrote:

On Apr 26, 12:02 pm, Kiuhnmkiuhnm03.4t.yahoo.itwrote:

On 4/26/2012 16:00, Adam Skutt wrote:

On Apr 26, 9:37 am, Kiuhnmkiuhnm03.4t.yahoo.it wrote:

The fact that you think that that's differing behaviour is what makes
it a misfeature. The fact that you think that '==' can take objects as
operands confirms that Java *does* confuse programmers.



The equality operator can absolutely be used between two objects.  Try
it if you don't believe me.  It always does identity comparison when
given two objects. It can also be given two primitives, and in this
case, it does value comparison.  Despite performing different
operations with the same symbol, there's little risk of confusion
because I can trivially figure out if a variable is an object or an
primitive.


No, it can't be used between objects but only between primitives and
references (which should be regarded as primitives, by the way).


The only way to access an object is through a reference.


If you

understand that your 'a' is not really an object but a reference to it,
everything becomes clear and you see that '==' always do the same thing.


Yes, object identity is implemented almost? everywhere by comparing
the value of two pointers (references)[1]. I've already said I'm not
really sure how else one would go about implementing it.


You might tell me that that's just an implementation detail, but when an
implementation detail is easier to understand and makes more sense than
the whole abstraction which is built upon it, something is seriously wrong.


I'm not sure what abstraction is being built here.  I think you have
me confused for someone else, possibly Steven.


The abstraction is this:
- There are primitives and objects.
- Primitives are not objects. The converse is also true.
- Primitives can become objects (boxing).
- Two primitives x and y are equal iff x == y.
- Two objects x and y are equal iff x.equals(y).
- Two objects are the same object iff x == y.
- If x is a primitive, then y = x is a deep copy.
- If x is an object, then y = x is a shallow copy.
- ...

The truth:
- Primitives can be references.
- Two primitives are equal iff x == y.
- Operator '.' automatically derefences references.

So Java is just C++ plus Garbage colletion plus some automatic 
dereferencing minus a lot of other things.


On the other hand, Python regards everything as an object and that's the 
way we should go, in my opinion. Some objects are mutable and other are 
immutable. This distinction doesn't mess with references.


Therefore, modifying the behavior of 'is' would be, in my opinion, a 
huge step back.



You're missing the big picture. The two comparisons are asking
different questions:
 Value equality asks if the operands 'have the same state'
regardless of how they exist in memory.
 Identity equality asks if the two operands are the same block of
memory.

The two are distinct because not all types support both operations.

If I write a function that does a value comparison, then it should do
value comparison on _every type that can be passed to it_, regardless
of whether the type is a primitive or an object, whether it has value
or reference semantics, and  regardless of how value comparison is
actually implemented.  If I write some function:
 f(x : T, y : U) =  x == y
where T and U are some unknown types, then I want the function to do a
value comparison for every type pairing that allows the function to
compile.  Likewise, if I write a function that does identity
comparison, then it logically wants to do identity comparison on
_every type that can be passed to it_.


Value comparison and identity comparison is a terminology that I 
don't agree on.


Equality or equivalence is a relation which is:
- reflexive
- symmetric
- transitive
Everything else... is something else. Call it semi-equality, 
tricky-equality or whatever, but not equality, please.


It's only natural that Python defaults to the Identity relation which is 
the (set-)intersection of all possible equality relations.



To accomplish this, I must have a distinct way of asking each
question.  In Python we have '==' and 'is'[2]; in Java we have
'Object.equals()' and '=='; in C and C++ we distinguish by the types
of the variables being compared (T and T*).

Java gives '==' a different meaning for primitive types, but that
turns out to be OK because I can't write a function that takes both a
primitive type and a reference type at the same position.


And as a side effect some integers are primitives and other are objects.


 Yes, the
reason it does this is due to what I said above, but that doesn't have
any bearing on why we pick one operation over the other as
programmers.


The distinction between primitives and objects is unfortunate. It is as
if Java tried to get rid of pointers but never completely succeeded in
doing that.



It's the 

Re: why () is () and [] is [] work in other way?

2012-04-27 Thread Kiuhnm

On 4/27/2012 16:07, Steven D'Aprano wrote:

On Fri, 27 Apr 2012 14:17:48 +0200, Kiuhnm wrote:


Define your terms: what do you mean by equal?


a and b are equal iff


Nope. What I meant is that we can talk of equality whenever...


a = a
a = b =  b = a
a = b and b = c =  a = c
If some of this properties are violated, we're talking of something
else.


Sorry, that won't do it. You haven't defined equality, or given any way
of deciding whether two entities are equal. What you have listed are
three *properties* of equality, namely:

- reflexivity (a = a)
- symmetry (if a = b then b = a)
- transitivity (if a = b and b = c then a = c)

But those three properties apply to any equivalence relation, not just
equality. Examples:


But that's what equality is in programming languages.
You choose whatever you want. Just abide to those rules.


both are odd (of integers)
have the same birthday (of people)
is congruent to (of triangles)
is in the same tax bracket (of tax payers)
has the same length (of pieces of string)
both contain chocolate (of cakes)


I can very well define a class Z_2 where 1 and 3 are equal (both are 
odd) and equality is defined as

  x % 2 == y % 2

This is why I keep saying that asking what 'equal' means lead us nowhere.
Equality is whatever you see fit as long as you follows some rules.


For example, if we define the operator ~ to mean has the same
genes (to be precise: the same genotype), then if Fred and Barney are
identical twins we have:

Fred ~ Fred
Fred ~ Barney and Barney ~ Fred

Identical triplets are rare (at least among human beings), but if we
clone Barney to get George, then we also have:

Fred ~ Barney and Barney ~ George =  Fred ~ George.

So have the same genes meets all your conditions for equality, but
isn't equality: the three brothers are very different. Fred lost his arm
in a car crash, Barney is a hopeless alcoholic, and George is forty years
younger than his two brothers.


/You/ decide if '~' is a good definition for equality in your case.
If it isn't, then define it another way.
What I'm saying is that equality is in the eye of the beholder.
To me, in some situations, all odd numbers are the same. What's wrong 
with that?


Kiuhnm
--
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-27 Thread Adam Skutt
On Apr 27, 8:07 am, Kiuhnm kiuhnm03.4t.yahoo.it wrote:
 Useful... maybe, conceptually sound... no.
 Conceptually, NaN is the class of all elements which are not numbers,
 therefore NaN = NaN.

NaN isn't really the class of all elements which aren't numbers.  NaN
is the result of a few specific IEEE 754 operations that cannot be
computed, like 0/0, and for which there's no other reasonable
substitute (e.g., infinity) for practical applications .

In the real world, if we were doing the math with pen and paper, we'd
stop as soon as we hit such an error. Equality is simply not defined
for the operations that can produce NaN, because we don't know to
perform those computations.  So no, it doesn't conceptually follow
that NaN = NaN, what conceptually follows is the operation is
undefined because NaN causes a halt.

This is what programming languages ought to do if NaN is compared to
anything other than a (floating-point) number: disallow the operation
in the first place or toss an exception.  Any code that tries such an
operation has a logic error and must be fixed.

However, when comparing NaN against floating point numbers, I don't
see why NaN == NaN returning false is any less conceptually correct
than any other possible result.  NaN's very existence implicitly
declares that we're now making up the rules as we go along, so we
might as well pick the simplest set of functional rules.

Plus, floating point numbers violate our expectations of equality
anyway, frequently in  surprising ways.  0.1 + 0.1 + 0.1 == 0.3 is
true with pen and paper, but likely false on your computer.  It's even
potentially possible to compare two floating point variables twice and
get different results each time[1]!  As such, we'd have this problem
with defining equality even if NaN didn't exist.  We must treat
floating-point numbers as a special case in order to write useful
working programs.  This includes defining equality in a way that's
different from what works for nearly every other data type.

Adam

[1] Due to register spilling causing intermediate rounding.  This
could happen with the x87 FPU since the registers were 80-bits wide
but values were stored in RAM as 64-bits.  This behavior is less
common now, but hardly impossible.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-27 Thread Ian Kelly
On Fri, Apr 27, 2012 at 9:39 AM, Adam Skutt ask...@gmail.com wrote:
 On Apr 27, 8:07 am, Kiuhnm kiuhnm03.4t.yahoo.it wrote:
 Useful... maybe, conceptually sound... no.
 Conceptually, NaN is the class of all elements which are not numbers,
 therefore NaN = NaN.

 NaN isn't really the class of all elements which aren't numbers.  NaN
 is the result of a few specific IEEE 754 operations that cannot be
 computed, like 0/0, and for which there's no other reasonable
 substitute (e.g., infinity) for practical applications .

 In the real world, if we were doing the math with pen and paper, we'd
 stop as soon as we hit such an error. Equality is simply not defined
 for the operations that can produce NaN, because we don't know to
 perform those computations.  So no, it doesn't conceptually follow
 that NaN = NaN, what conceptually follows is the operation is
 undefined because NaN causes a halt.

 This is what programming languages ought to do if NaN is compared to
 anything other than a (floating-point) number: disallow the operation
 in the first place or toss an exception.  Any code that tries such an
 operation has a logic error and must be fixed.

NaNs do not signify errors (for instance, a NaN could result simply
from subtracting one Inf from another), and they do not necessarily
imply that the calculation should halt.  They are propagating values
indicating the lack of a concrete value, and frequently they can
reasonably be ignored.  If you need to know about a NaN immediately,
then you can trap them with fpectl.  If you don't, then you let it
propagate and check for it at the end of the calculation.  If instead
they raised exceptions by default, then we would need to wrap
virtually every floating point operation in a try-except, which would
quickly become a mess.  See also:

http://grouper.ieee.org/groups/754/faq.html#exceptions
-- 
http://mail.python.org/mailman/listinfo/python-list


Borg identity [was Re: why () is () and [] is [] work in other way?]

2012-04-27 Thread Steven D'Aprano
On Thu, 26 Apr 2012 04:42:36 -0700, Adam Skutt wrote:

 You're going to have to explain the value of an ID that's not 1:1 with
 an object's identity, for at least the object's lifecycle, for a
 programmer.  If you can't come up with a useful case, then you haven't
 said anything of merit.

I gave an example earlier, but you seem to have misunderstood it, so I'll 
give more detail.


In the Borg design pattern, every Borg instance shares state and are 
indistinguishable, with only one exception: object identity. We can 
distinguish two Borg instances by using is.

Since the whole point of the pattern is for Borg instances to be 
indistinguishable, the existence of a way to distinguish Borg instances 
is a flaw and may be undesirable. At least, it's exposing an 
implementation detail which some people argue should not be exposed.

Why should the caller care whether they are dealing with a singleton 
object or an unspecified number of Borg objects all sharing state? A 
clever interpreter could make many Borg instances appear to be a 
singleton. A really clever one could also make a singleton appear to be 
many Borg instances.

Note that this is virtually the same situation as that which John Nagle 
objects to, namely that the implementation detail of small ints being 
singletons is exposed. There is only ever one 0 instance, but potentially 
many 3579 instances.

John's argument is that Python should raise an exception if you compare 
2 is 2, or for that matter 3579 is 3579, which is foolish. If you're 
going to change the semantics of is, why not do something useful and 
ensure that 3579 is 3579 returns True regardless of whether they 
actually are the same instance or not?

That would be far more useful than raising an exception. It would 
complicate the definition of is, but perhaps that's a price people are 
willing to pay for avoiding the (trivial) confusion about object identity.

[...]
 identities. The Borg design pattern, for example, would be an excellent
 candidate for ID:identity being treated as many-to-one.
 
 How would inheritance work if I did that?

You don't inherit from Borg instances, and instances inherit from their 
class the same as any other instance.


-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-27 Thread mwilson
Adam Skutt wrote:
[ ... ]
 In the real world, if we were doing the math with pen and paper, we'd
 stop as soon as we hit such an error. Equality is simply not defined
 for the operations that can produce NaN, because we don't know to
 perform those computations.  So no, it doesn't conceptually follow
 that NaN = NaN, what conceptually follows is the operation is
 undefined because NaN causes a halt.
 
 This is what programming languages ought to do if NaN is compared to
 anything other than a (floating-point) number: disallow the operation
 in the first place or toss an exception.  Any code that tries such an
 operation has a logic error and must be fixed.

There was a time when subtracting 5 from 3 would have been a logic error.  
Your phrase if we were doing the math ... lies behind most of the history 
of math, esp. as it concerns arithmetic.  Mathematicians kept extending the 
definitions so that they wouldn't have to stop.  Feynman's _Lectures on 
Physics_, chapter 22, Algebra gives a stellar account of the whole 
process.

Mel.

-- 
http://mail.python.org/mailman/listinfo/python-list


Direct vs indirect [was Re: why () is () and [] is [] work in other way?]

2012-04-27 Thread Steven D'Aprano
On Thu, 26 Apr 2012 04:42:36 -0700, Adam Skutt wrote:

 On Apr 26, 5:10 am, Steven D'Aprano steve
 +comp.lang.pyt...@pearwood.info wrote:

 But I was actually referring to something more fundamental than that.
 The statement a is b is a *direct* statement of identity. John is my
 father. id(a) == id(b) is *indirect*: The only child of John's
 grandfather is the parent of the mother-in-law of my sister-in-law
 sort of thing. (Excuse me if I got the relationships mixed up.)
 
 Again, the fact that you somehow think this absurd family tree is
 relevant only shows you're fundamentally confused about what object
 oriented identity means.  That's rather depressing, seeing as I've given
 you a link to the definition.

Perhaps you failed to notice that this absurd family tree, as you put 
it, consists of grandparent+parent+sibling+in-law. What sort of families 
are you familiar with that this seems absurd to you?

I think you have inadvertently demonstrated the point I am clumsily 
trying to make. Even when two expressions are logically equivalent, the 
form of the expressions make a big difference to the comprehensibility of 
the text. Which would you rather read?

   for item in sequence[1:]: ...

   for item in sequence[sum(ord(c) for c in 'avocado') % 183:]: ...

The two are logically equivalent, so logically you should have no 
preference between the two, yes?

 
 In a mathematical sense, you're saying that given f(x) = x+2, using f(x)
 is somehow more direct (whatever the hell that even means)

I thought that the concept of direct and indirect statements would be 
self-evident. Let me try again.

A statement is direct in the sense I mean if it explicitly states the 
thing you intend it to state. A statement is indirect if it requires 
one or more logical steps to go from the statement, as given, to the 
conclusion intended.

Queen Elizabeth II is the ruling monarch of the United Kingdom is a 
direct statement of the fact that Queen Elizabeth II is the ruling 
monarch of the UK. (Do I really need to explain this?)

Queen Elizabeth II is the Commander-in-chief of the Canadian Armed 
Forces is an *indirect* statement of the fact that Elizabeth is the 
ruling monarch of the UK. It is indirect because it doesn't explicitly 
say that she is monarch, but the Commander-in-Chief of the Canadian Armed 
Forces is always the ruling monarch of Canada, and the ruling monarch of 
Canada is always the ruling monarch of the UK. Hence, Elizabeth being 
Commander-in-Chief necessarily implies that she is ruling monarch of the 
United Kingdom (at least until there is change to Canadian law).

a is b is a direct test of whether a is b. (Duh.)

id(a) == id(b) is an indirect test of whether a is b, since it requires 
at least three indirect steps: the knowledge of what the id() function 
does, the knowledge of what the == operator does, and the knowledge that 
equal IDs imply identity.



-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Python id() does not return an address [was Re: why () is () and [] is [] work in other way?]

2012-04-27 Thread Steven D'Aprano
On Thu, 26 Apr 2012 04:42:36 -0700, Adam Skutt wrote:

 On Apr 26, 5:10 am, Steven D'Aprano steve
 +comp.lang.pyt...@pearwood.info wrote:

 Solution to *what problem*?

 This confusion that many people have over what 'is' does, including
 yourself.

I have no confusion over what is does. The is operator returns True 
if and only if the two operands are the same object, otherwise it returns 
False.

If you think that is does something different, you are wrong.

 
  An address is an identifier: a number that I can use to access a
  value[1].

 Then by your own definition, Python's id() does not return an address,
 since you cannot use it to access a value.
 
 The fact Python lacks explicit dereferencing doesn't change the fact
 that id() returns an address.  Replace 'can' with 'could' or 'could
 potentially' or the whole phrase with 'represents' if you wish.  It's a
 rather pointless thing to quibble over.

You can't treat id() as an address. Did you miss my post when I 
demonstrated that Jython returns IDs generated on demand, starting from 
1? In general, there is *no way even in principle* to go from a Python ID 
to the memory location (address) of the object with that ID, because in 
general objects *may not even have a fixed address*. Objects in Jython 
don't, because the Java virtual machine can move them in memory.

The fact that CPython happens to use the memory address of objects, 
suitably converted to an int object, is a red-herring. It leads to 
nothing but confusion.

 
 Would you call the result of casting a C pointer to an int an address? 
 If so, you must call the result of id() an address as well-- you can't
 dereference either of them.  If not, then you need to provide an
 alternate name for the result of casting a C pointer to an int.

I don't need to do anything of the sort. It was *your* definition, not 
mine. Don't put the responsibility on me for your definition being broken.

(And for the record, in C you can cast an integer into a pointer, 
although the results are implementation-specific. There's no equivalent 
in Python.)


-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-27 Thread Adam Skutt
On Apr 27, 11:01 am, Kiuhnm kiuhnm03.4t.yahoo.it wrote:
 On 4/27/2012 1:57, Adam Skutt wrote:
  On Apr 26, 6:34 pm, Kiuhnmkiuhnm03.4t.yahoo.it  wrote:
  If you
  understand that your 'a' is not really an object but a reference to it,
  everything becomes clear and you see that '==' always do the same thing.

  Yes, object identity is implemented almost? everywhere by comparing
  the value of two pointers (references)[1]. I've already said I'm not
  really sure how else one would go about implementing it.

  You might tell me that that's just an implementation detail, but when an
  implementation detail is easier to understand and makes more sense than
  the whole abstraction which is built upon it, something is seriously wrong.

  I'm not sure what abstraction is being built here.  I think you have
  me confused for someone else, possibly Steven.

 The abstraction is this:
 - There are primitives and objects.
 - Primitives are not objects. The converse is also true.
 - Primitives can become objects (boxing).
 - Two primitives x and y are equal iff x == y.
 - Two objects x and y are equal iff x.equals(y).
 - Two objects are the same object iff x == y.
 - If x is a primitive, then y = x is a deep copy.
 - If x is an object, then y = x is a shallow copy.
 - ...


This is not an abstraction at all, but merely a poor explanation of
how things work in Java.  Your last statement is totally incorrect, as
no copying of the object occurs whatsoever.  The reference is merely
reseated to refer to the new object. If you're going to chide me for
ignoring the difference between the reference and the referent object,
then you shouldn't ignore it either, especially in the one case where
it actually matters!  If we try to extend this to other languages,
then it breaks down completely.

 The truth:
 - Primitives can be references.
 - Two primitives are equal iff x == y.
 - Operator '.' automatically derefences references.


You have the first statement backwards.  References are a primitive
construct, not the other way around.  While true, it's still a bad way
to think about what's going on.  It breaks down once we add C++ /
Pascal reference types to the mix, for example.

It's better to think about variables (names) and just recognize that
not all variables have the same semantics.  It avoids details that are
irrelevant to writing actual programs and remains consistent.

 Equality or equivalence is a relation which is:
 - reflexive
 - symmetric
 - transitive
 Everything else... is something else. Call it semi-equality,
 tricky-equality or whatever, but not equality, please.

Sure, but then it's illegal to allow the usage of '==' with floating
point numbers, which will never have these properties in any usable
implementation[1].  So we're back to what started this tangent, and we
end up needing 'equals()' methods on our classes to distinguish
between the different forms of equality.  That's precisely what you
want to avoid.

Or we can just accept that '==' doesn't always possess those
properties, which is what essentially every programming language does,
and call it (value) equality.  As long as we don't cross incompatible
meanings, it's hard to believe that this isn't the right thing to do.


  If anything, you have that backwards.  Look at Python: all variables
  in Python have pointer semantics, not value semantics.

 When everything is white, the word white becomes redundant.
 So the fact that everything in Python have reference semantics means
 that we can't stop thinking about value and reference semantics.

Nope. The behavior of variables is absolutely essential to writing
correct programs.  If I write a program in Python that treats
variables as if they were values, it will be incorrect.


   In imperative
  languages, pointers have greater utility over value types because not
  all types can obey the rules for value types.  For example, I don't
  know how to give value semantics to something like a I/O object (e.g,
  file, C++ fstream, C FILE), since I don't know how to create
  independent copies.

 By defining a copy constructor.

Then write me a working one.  I'll wait. To save yourself some time,
you can start with std::fstream.

 Python is already without pointers (*).
 A world where everyone is a lawyer is a world without lawyers (really,
 there isn't any other way we can get rid of them :) ).

 (*) By the way, some would argue that references are not pointers.

They would be completely and utterly wrong, and probably imbuing
pointers with properties they don't actually possess.  Unless you're
talking about C++ / Pascal references, which really aren't pointers
and do possess a different set of semantics (alias might be a better
term for them).

Adam

[1] Not in any fashion that's useful to the programmer, at any rate.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python id() does not return an address [was Re: why () is () and [] is [] work in other way?]

2012-04-27 Thread Temia Eszteri
Steven, your posts are leaking out of their respective thread(s). Is
this intentional?

~Temia
--
When on earth, do as the earthlings do.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Borg identity [was Re: why () is () and [] is [] work in other way?]

2012-04-27 Thread Adam Skutt
On Apr 27, 12:56 pm, Steven D'Aprano steve
+comp.lang.pyt...@pearwood.info wrote:
 On Thu, 26 Apr 2012 04:42:36 -0700, Adam Skutt wrote:
  You're going to have to explain the value of an ID that's not 1:1 with
  an object's identity, for at least the object's lifecycle, for a
  programmer.  If you can't come up with a useful case, then you haven't
  said anything of merit.

 I gave an example earlier, but you seem to have misunderstood it, so I'll
 give more detail.

 In the Borg design pattern, every Borg instance shares state and are
 indistinguishable, with only one exception: object identity. We can
 distinguish two Borg instances by using is.

 Since the whole point of the pattern is for Borg instances to be
 indistinguishable, the existence of a way to distinguish Borg instances
 is a flaw and may be undesirable. At least, it's exposing an
 implementation detail which some people argue should not be exposed.


Then people should stop with such idiocy like the Borg pattern. It's a
bad example from an even worse idea.

 Why should the caller care whether they are dealing with a singleton
 object or an unspecified number of Borg objects all sharing state? A
 clever interpreter could make many Borg instances appear to be a
 singleton. A really clever one could also make a singleton appear to be
 many Borg instances.

Trivial: to break cyclical references in a deep copy operation.

 John's argument is that Python should raise an exception if you compare
 2 is 2, or for that matter 3579 is 3579, which is foolish.

  identities. The Borg design pattern, for example, would be an excellent
  candidate for ID:identity being treated as many-to-one.

  How would inheritance work if I did that?

 You don't inherit from Borg instances, and instances inherit from their
 class the same as any other instance.

I think you misunderstood me.  Define a Borg class where somehow
identity is the same for all instances.  Inherit from that class and
add per-instance members.  Now, identity can't be the same for all
instances.  As a result, you've just violated the Liskov Substituion
Principal: code that relies on all Borg class instances having the
same identity will fail when passed an instance of the subclass.

It's impossible to combine identities and not violate LSP, unless you
forbid subclasses.  Your idea violates one of the most fundamental
tenants of object-oriented programming.  This is because object
identity is one of the fundamental consequences of object-oriented
programming.  You can't do away with it, and any attempt to do so
really just suggests that you don't understand OOP at all.

Adam
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Borg identity [was Re: why () is () and [] is [] work in other way?]

2012-04-27 Thread Chris Angelico
On Sat, Apr 28, 2012 at 3:33 AM, Adam Skutt ask...@gmail.com wrote:
 I think you misunderstood me.  Define a Borg class where somehow
 identity is the same for all instances.  Inherit from that class and
 add per-instance members.  Now, identity can't be the same for all
 instances.  As a result, you've just violated the Liskov Substituion
 Principal: code that relies on all Borg class instances having the
 same identity will fail when passed an instance of the subclass.

Why would you subclass a Borg?

ChrisA
-- 
http://mail.python.org/mailman/listinfo/python-list


Variables and values [was Re: why () is () and [] is [] work in other way?]

2012-04-27 Thread Steven D'Aprano
On Fri, 27 Apr 2012 10:15:32 -0700, Adam Skutt wrote:

 If I write a program in Python that treats variables as if they were
 values, it will be incorrect.

I'm sorry, it is unclear to me what distinction you are making between 
variables and values. Can you give simple examples of both incorrect and 
correct code demonstrating what you mean?

(I know what distinction *I* would make, but I'm not sure if it is the 
same one you are making.)


-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python id() does not return an address [was Re: why () is () and [] is [] work in other way?]

2012-04-27 Thread Adam Skutt
On Apr 27, 1:12 pm, Steven D'Aprano steve
+comp.lang.pyt...@pearwood.info wrote:
 On Thu, 26 Apr 2012 04:42:36 -0700, Adam Skutt wrote:
  On Apr 26, 5:10 am, Steven D'Aprano steve
  +comp.lang.pyt...@pearwood.info wrote:
  Solution to *what problem*?

  This confusion that many people have over what 'is' does, including
  yourself.

 I have no confusion over what is does.

False.  If you did, then you would not have suggested the difference
in True/False result between id([1,2]) == id([1, 2]) and [1, 2] is
[1, 2] matters.  You would understand that the result of an identity
test with temporary objects is meaningless, since identity is only
meaningful while the objects are alive.  That's a fundamental
mistake.

   An address is an identifier: a number that I can use to access a
   value[1].

  Then by your own definition, Python's id() does not return an address,
  since you cannot use it to access a value.

  The fact Python lacks explicit dereferencing doesn't change the fact
  that id() returns an address.  Replace 'can' with 'could' or 'could
  potentially' or the whole phrase with 'represents' if you wish.  It's a
  rather pointless thing to quibble over.

 You can't treat id() as an address. Did you miss my post when I
 demonstrated that Jython returns IDs generated on demand, starting from
 1? In general, there is *no way even in principle* to go from a Python ID
 to the memory location (address) of the object with that ID, because in
 general objects *may not even have a fixed address*. Objects in Jython
 don't, because the Java virtual machine can move them in memory.

Yes, there is a way.  You add a function deref() to the language.  In
CPython, that simply treats the passed value as a memory address and
treats it as an object, perhaps with an optional check.  In Jython,
it'd access a global table of numbers as keys with the corresponding
objects as values, and return them.  The value of id() is absolutely
an address, even in Jython. The fact the values can move about is
irrelevant.

Again, if this wasn't possible, then you couldn't implement 'is'.
Implementing 'is' requires a mechanism for comparing objects that
doesn't involve ensuring the contents of the two operands in memory is
the same.

  Would you call the result of casting a C pointer to an int an address?
  If so, you must call the result of id() an address as well-- you can't
  dereference either of them.  If not, then you need to provide an
  alternate name for the result of casting a C pointer to an int.

 I don't need to do anything of the sort.

Yes, you do, because you called such a thing an address when talking
about CPython. Even if my definition is wrong (it's not), your
definition is wrong too.

 (And for the record, in C you can cast an integer into a pointer,
 although the results are implementation-specific. There's no equivalent
 in Python.)

Yes, but the lack of that operation doesn't mean that id() doesn't
return an address.

Adam
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Borg identity [was Re: why () is () and [] is [] work in other way?]

2012-04-27 Thread Ian Kelly
On Fri, Apr 27, 2012 at 11:33 AM, Adam Skutt ask...@gmail.com wrote:
 On Apr 27, 12:56 pm, Steven D'Aprano steve
 +comp.lang.pyt...@pearwood.info wrote:
 On Thu, 26 Apr 2012 04:42:36 -0700, Adam Skutt wrote:
  You're going to have to explain the value of an ID that's not 1:1 with
  an object's identity, for at least the object's lifecycle, for a
  programmer.  If you can't come up with a useful case, then you haven't
  said anything of merit.

 I gave an example earlier, but you seem to have misunderstood it, so I'll
 give more detail.

 In the Borg design pattern, every Borg instance shares state and are
 indistinguishable, with only one exception: object identity. We can
 distinguish two Borg instances by using is.

 Since the whole point of the pattern is for Borg instances to be
 indistinguishable, the existence of a way to distinguish Borg instances
 is a flaw and may be undesirable. At least, it's exposing an
 implementation detail which some people argue should not be exposed.


 Then people should stop with such idiocy like the Borg pattern. It's a
 bad example from an even worse idea.

I would argue exactly the opposite.  One issue I have with the
Singleton pattern is that the very fact that a class is a singleton
(or a borg) is an implementation detail.  Shared identity exposes that
implementation detail, which I consider a flaw.  Borg, OTOH, actually
gets this right.

 Why should the caller care whether they are dealing with a singleton
 object or an unspecified number of Borg objects all sharing state? A
 clever interpreter could make many Borg instances appear to be a
 singleton. A really clever one could also make a singleton appear to be
 many Borg instances.

 Trivial: to break cyclical references in a deep copy operation.

The cycle will break anyway, since there are only a finite number of
instances.  You just might end up with as many copy instances as there
were original instances in the structure.  But going back to Steven's
point here, that fact should not be important to the caller.

 I think you misunderstood me.  Define a Borg class where somehow
 identity is the same for all instances.

Why?  The whole point of Borg is to share state, not identity.  If you
really want shared identity, use a Singleton.

 Inherit from that class and
 add per-instance members.  Now, identity can't be the same for all
 instances.  As a result, you've just violated the Liskov Substituion
 Principal: code that relies on all Borg class instances having the
 same identity will fail when passed an instance of the subclass.

That has nothing to do with Borg.  That has to do with having
misguidedly defined identity to be the same for all instances.  You
wouldn't do that for a regular class.  Why force it on a Borg class?
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Direct vs indirect [was Re: why () is () and [] is [] work in other way?]

2012-04-27 Thread Adam Skutt
On Apr 27, 1:06 pm, Steven D'Aprano steve
+comp.lang.pyt...@pearwood.info wrote:
 On Thu, 26 Apr 2012 04:42:36 -0700, Adam Skutt wrote:
  On Apr 26, 5:10 am, Steven D'Aprano steve
  +comp.lang.pyt...@pearwood.info wrote:
  But I was actually referring to something more fundamental than that.
  The statement a is b is a *direct* statement of identity. John is my
  father. id(a) == id(b) is *indirect*: The only child of John's
  grandfather is the parent of the mother-in-law of my sister-in-law
  sort of thing. (Excuse me if I got the relationships mixed up.)

  Again, the fact that you somehow think this absurd family tree is
  relevant only shows you're fundamentally confused about what object
  oriented identity means.  That's rather depressing, seeing as I've given
  you a link to the definition.

 Perhaps you failed to notice that this absurd family tree, as you put
 it, consists of grandparent+parent+sibling+in-law. What sort of families
 are you familiar with that this seems absurd to you?

No, I noticed, but who talks like that?  It's not remotely comparable
to the sort of difference we're talking about.


 I think you have inadvertently demonstrated the point I am clumsily
 trying to make. Even when two expressions are logically equivalent, the
 form of the expressions make a big difference to the comprehensibility of
 the text.

And if we were talking about 30, 20, 5, maybe even 2 line function
versus it's name, you might have a point. We're not talking about such
things though, and it's pretty disingenuous to pretend otherwise.
Yet, that's precisely what you did with your absurd family
relationship.

 Which would you rather read?

    for item in sequence[1:]: ...

    for item in sequence[sum(ord(c) for c in 'avocado') % 183:]: ...

 The two are logically equivalent, so logically you should have no
 preference between the two, yes?

No, they're not logically equivalent.  The first won't even execute,
as sequence is undefined.  You need two lines in the first case.

 A statement is direct in the sense I mean if it explicitly states the
 thing you intend it to state.

And in the case of the two ways to compare identity, both statements
state exactly what I intend to state.  They're synonyms.


 a is b is a direct test of whether a is b. (Duh.)

 id(a) == id(b) is an indirect test of whether a is b, since it requires
 at least three indirect steps: the knowledge of what the id() function
 does, the knowledge of what the == operator does, and the knowledge that
 equal IDs imply identity.

The problem is that using 'is' correctly requires understanding all of
those three things.

Adam
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Borg identity [was Re: why () is () and [] is [] work in other way?]

2012-04-27 Thread Ian Kelly
On Fri, Apr 27, 2012 at 11:38 AM, Chris Angelico ros...@gmail.com wrote:
 On Sat, Apr 28, 2012 at 3:33 AM, Adam Skutt ask...@gmail.com wrote:
 I think you misunderstood me.  Define a Borg class where somehow
 identity is the same for all instances.  Inherit from that class and
 add per-instance members.  Now, identity can't be the same for all
 instances.  As a result, you've just violated the Liskov Substituion
 Principal: code that relies on all Borg class instances having the
 same identity will fail when passed an instance of the subclass.

 Why would you subclass a Borg?

For the same reasons one might want to subclass a Singleton.  One of
the big advantages of Borg is that it makes this easier, and it also
allows the option of either having instances of subclasses share the
same state as instances of base classes (usually preferred, because it
preserves LSP) or of allowing each individual subclass to have its own
unique shared state.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python id() does not return an address [was Re: why () is () and [] is [] work in other way?]

2012-04-27 Thread Chris Angelico
On Sat, Apr 28, 2012 at 3:51 AM, Adam Skutt ask...@gmail.com wrote:
 Yes, there is a way.  You add a function deref() to the language.  In
 CPython, that simply treats the passed value as a memory address and
 treats it as an object, perhaps with an optional check.  In Jython,
 it'd access a global table of numbers as keys with the corresponding
 objects as values, and return them.  The value of id() is absolutely
 an address, even in Jython. The fact the values can move about is
 irrelevant.

Python already as dereferenceable addresses. Look.

def address(obj,table=[]):
for i,o in enumerate(table):
if obj is o: return i
table.append(obj)
return len(table)-1

def deref(addr):
return address.__defaults__[0][addr]

You can take the address of an object (interning it, effectively), and
later dereference it. Proves nothing.

ChrisA
-- 
http://mail.python.org/mailman/listinfo/python-list


RE: why () is () and [] is [] work in other way?

2012-04-27 Thread Prasad, Ramit
  I have spent some time searching for a bug in my code, it was due to
  different work of is with () and []:
  () is ()
  True
  [] is []
  False
 
  (Python 2.7.2+ (default, Oct  4 2011, 20:03:08)
  [GCC 4.6.1] )
 
  Is this what it should be or maybe yielding unified result is better?
  D.
 
 Congratulations, you've managed to introduce the most useless thread on
 this ng/ml that I've come across in the ten years that I've been using
 (c)Python.
 
 I've never ever thought about using this weird thing called id in my
 code, (which comes later in all the responses) so why do some people
 think it's so important?


Somewhere out there (possibly in an alternate universe) Bill Clinton is reading 
this thread and nodding vigorously about an argument around the [key]word is.



Ramit


Ramit Prasad | JPMorgan Chase Investment Bank | Currencies Technology
712 Main Street | Houston, TX 77002
work phone: 713 - 216 - 5423
This email is confidential and subject to important disclaimers and
conditions including on offers for the purchase or sale of
securities, accuracy and completeness of information, viruses,
confidentiality, legal privilege, and legal entity disclaimers,
available at http://www.jpmorgan.com/pages/disclosures/email.  
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Borg identity [was Re: why () is () and [] is [] work in other way?]

2012-04-27 Thread Steven D'Aprano
On Fri, 27 Apr 2012 10:33:34 -0700, Adam Skutt wrote:

 Why should the caller care whether they are dealing with a singleton
 object or an unspecified number of Borg objects all sharing state? A
 clever interpreter could make many Borg instances appear to be a
 singleton. A really clever one could also make a singleton appear to be
 many Borg instances.
 
 Trivial: to break cyclical references in a deep copy operation.

I asked why the *caller* should care. If the caller has to break cyclical 
references manually, the garbage collector is not doing its job.

If you're going to propose underpowered or buggy environments as an 
objection, then I'll simply respond that I'm not talking about any 
specific (underpowered or buggy) implementation, I'm talking about what 
is logically possible.


[...]
  How would inheritance work if I did that?

 You don't inherit from Borg instances, and instances inherit from their
 class the same as any other instance.
 
 I think you misunderstood me.  Define a Borg class where somehow
 identity is the same for all instances.  Inherit from that class and add
 per-instance members.

I think that if you're talking about per-instance members of a Borg 
class, you're confused as to what Borg means. Since all instances share 
state, you can't have *per-instance* data.


 Now, identity can't be the same for all
 instances.  As a result, you've just violated the Liskov Substituion
 Principal: code that relies on all Borg class instances having the same
 identity will fail when passed an instance of the subclass.

Not at all. Obviously each Borg subclass will have it's own fake 
identity. Code that requires instances of different types to be identical 
is fundamentally broken, since the mere fact that they are different 
types means they can't be identical.

I'll accept the blame for your confusion as I glossed over something 
which I thought was obvious, but clearly wasn't.

When I said that Borg instances are indistinguishable except for 
identity, I thought that was obvious that I was talking about instances 
of a single type. Mea culpa.

Clearly if x is an instance of Borg, and y is an instance of 
BorgSubclass, you can distinguish them by looking at the type. The point 
is that you shouldn't be able to distinguish instances of a single type.


 It's impossible to combine identities and not violate LSP, unless you
 forbid subclasses.  Your idea violates one of the most fundamental
 tenants of object-oriented programming.  This is because object identity
 is one of the fundamental consequences of object-oriented programming. 
 You can't do away with it, and any attempt to do so really just suggests
 that you don't understand OOP at all.

Oh please, enough of the religion of LSP.

Barbara Liskov first introduced this idea in 1987, twenty years after 
Simula 67 first appeared and thirty years after MIT researchers came up 
with the concept of object oriented programming. That's hardly 
fundamental to the concept of OOP. People have, and still do, violate LSP 
all the time.

LSP may be best practice but it's hardly essential. OOP was useful before 
LSP and it will remain useful in the face of violations.

Besides:

- In real life, subtypes often violate LSP. An electric car is a type of 
car, but it has no petrol tank. Wolf spiders have eyes, except for the 
Kauaʻi cave wolf spider, which is is a subtype of wolf spider but is 
completely eyeless.

- Subclasses in Eiffel are not necessarily subtypes and may not be 
substitutable for superclasses. If it's good enough for Eiffel, it's good 
enough for my hypothetical Borg subclasses.

You can always declare that Bertrand Meyer doesn't understand OOP at 
all too.


-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Borg identity [was Re: why () is () and [] is [] work in other way?]

2012-04-27 Thread Adam Skutt
On Apr 27, 2:40 pm, Steven D'Aprano steve
+comp.lang.pyt...@pearwood.info wrote:
 On Fri, 27 Apr 2012 10:33:34 -0700, Adam Skutt wrote:
  Why should the caller care whether they are dealing with a singleton
  object or an unspecified number of Borg objects all sharing state? A
  clever interpreter could make many Borg instances appear to be a
  singleton. A really clever one could also make a singleton appear to be
  many Borg instances.

  Trivial: to break cyclical references in a deep copy operation.

 I asked why the *caller* should care. If the caller has to break cyclical
 references manually, the garbage collector is not doing its job.

It's a necessary requirement to serialize any cyclical structure.
Garbage collection has nothing to do with it.  If I have some
structure such that A -- B -- A, I need to be able to determine that
I've seen 'A' before in order to serialize the structure to disk, or I
will never write it out successfully.

There are plenty of situations where we legitimately care whether two
pointers are the same and don't give one whit about the state of
objects they point to.  You cannot conflate the two tests, and that's
precisely what your 'give all borg instances the same identity' idea
does.

 I think that if you're talking about per-instance members of a Borg
 class, you're confused as to what Borg means.

I'm not.  I'm talking about per-instance members of a subclass of a
Borg class.  There's nothing about the Borg pattern that forbids such
behavior, which is one of the reasons it's such a terrible idea in
general.  Borg implies promises that it cannot readily keep.

 Since all instances share state, you can't have *per-instance* data.

I most certainly can do so in a subclass.  Shared state in a parent
doesn't mandate shared state in a child.

 Not at all. Obviously each Borg subclass will have it's own fake
 identity.
 When I said that Borg instances are indistinguishable except for
 identity, I thought that was obvious that I was talking about instances
 of a single type. Mea culpa.

 Clearly if x is an instance of Borg, and y is an instance of
 BorgSubclass, you can distinguish them by looking at the type. The point
 is that you shouldn't be able to distinguish instances of a single type.

No, that's not the least bit obvious nor apparent, and it still
violates LSP.  It means every function that takes a Borg as an
argument must know about every subclass in order to distinguish
between them.

The serialization function above would need to do so.  Imagine an
object x that holds a Borg object and a BorgSubclass object.  If the
serialization function keeps a list of objects it has seen before and
uses that to determine whether to write the object out, it will fail
to write out one or the other if we implemented your harebrained 'All
Borg objects have the same identity' idea.

Your idea means that 'x.borg is x.subborg' must return True.  It also
means either x.borg isn't going to be written out, or x.subborg isn't
going to be written out.  The program is broken.

If you modify your idea to ignore subtypes, than this function breaks:
def write_many(value, channel1, channel2):
channel1.write(value)
if channel2 is not channel1:
channel2.write(value)

Calling write_many(foo, x.borg, x.subborg) now gives different
behavior than write_many(foo, x.borg, x.borg).  That's probably not
what the programmer intended!

Like it or not, whether you have only one object with shared state or
infinite objects with the same shared state is not an implementation
detail.  Just because you write code that doesn't care about that fact
does not make it an implementation detail.  I can write code that
depends on that fact, and there's not a single thing you can do to
stop me.

This is why the Borg pattern is a bad idea in general, because it
encourages programmers to write code that is subtly wrong.  If you
have a Borg class, you can't ignore the fact that you have multiple
objects even if you want to do so.  You will eventually end up writing
incorrect code as a result.  Yet, many people try to do precisely
that, your idea is attempting to do precisely that!

 Oh please, enough of the religion of LSP.

 Barbara Liskov first introduced this idea in 1987, twenty years after
 Simula 67 first appeared and thirty years after MIT researchers came up
 with the concept of object oriented programming. That's hardly
 fundamental to the concept of OOP.

 People have, and still do, violate LSP all the time.

People write code with security flaws all of the time too.  This
doesn't even being to approach being an reasonable argument.  It's
completely disingenuous.  People come up with ideas and fail to
properly formalize them all of the time.  People come up with useful,
revolutionary ideas and get parts of them wrong all of the time.

If you violate LSP, then you enable interface users to write buggy
code.  Correct class hierarchies must follow it; correct interface
implementations must follow it. 

Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Chris Angelico
On Thu, Apr 26, 2012 at 3:48 PM, John Nagle na...@animats.com wrote:
   This assumes that everything is, internally, an object.  In CPython,
 that's the case, because Python is a naive interpreter and everything,
 including numbers, is boxed.  That's not true of PyPy or Shed Skin.
 So does is have to force the creation of a temporary boxed object?

Interesting point. Presumably the only types that can be unboxed are
those for which identity vs equality is pretty much immaterial, so the
question won't really matter. I'd be inclined to either have it return
False if either/both is unboxed, or else return True if both are equal
unboxed numbers, whichever is the most convenient to implement.

My opinion doesn't matter--
My opinion doesn't matter--
My opinion doesn't matter, matter, matter, matter, matter!
(WS Gilbert, Ruddigore)

ChrisA
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Steven D'Aprano
On Wed, 25 Apr 2012 22:48:33 -0700, John Nagle wrote:

 On 4/25/2012 5:01 PM, Steven D'Aprano wrote:
 On Wed, 25 Apr 2012 13:49:24 -0700, Adam Skutt wrote:

 Though, maybe it's better to use a different keyword than 'is' though,
 due to the plain English
 connotations of the term; I like 'sameobj' personally, for whatever
 little it matters.  Really, I think taking away the 'is' operator
 altogether is better, so the only way to test identity is:
  id(x) == id(y)

 Four reasons why that's a bad idea:

 1) The is operator is fast, because it can be implemented directly by
 the interpreter as a simple pointer comparison (or equivalent).
 
 This assumes that everything is, internally, an object.

No it doesn't. It assumes that everything provides the external interface 
of an object. Internally, the implementation could be anything you like, 
so long as it simulates an object when observed from Python.


-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Steven D'Aprano
On Wed, 25 Apr 2012 20:50:21 -0700, Adam Skutt wrote:

 On Apr 25, 8:01 pm, Steven D'Aprano steve
 +comp.lang.pyt...@pearwood.info wrote:
 On Wed, 25 Apr 2012 13:49:24 -0700, Adam Skutt wrote:
  Though, maybe it's better to use a different keyword than 'is'
  though, due to the plain English
  connotations of the term; I like 'sameobj' personally, for whatever
  little it matters.  Really, I think taking away the 'is' operator
  altogether is better, so the only way to test identity is:
      id(x) == id(y)

 Four reasons why that's a bad idea:

 1) The is operator is fast, because it can be implemented directly by
 the interpreter as a simple pointer comparison (or equivalent). The
 id() idiom is slow, because it involves two global lookups and an
 equality comparison. Inside a tight loop, that can make a big
 difference in speed.
 
 The runtime can optimize the two operations to be equivalent, since they
 are logically equivalent operations.  If you removed 'is', there's
 little reason to believe it would do otherwise.

I'm afraid you are mistaken there. *By design*, Python allows shadowing 
and monkey-patching of built-ins. (Although not quite to the same degree 
as Ruby, and thank goodness!)

Given the language semantics of Python, id(a) == id(b) is NOT 
equivalent to a is b since the built-in id() function can be shadowed 
by some other function at runtime, but the is operator cannot be.

An extremely clever optimizing implementation like PyPy may be able to 
recognise at runtime that the built-in id() is being called, but that 
doesn't change the fact that PyPy MUST support this code in order to 
claim to be a Python compiler:

id = lambda x: 999
id(None) == id(spam)  # returns True

If your runtime doesn't allow that, it isn't Python.


 2) The is operator always has the exact same semantics and cannot be
 overridden. The id() function can be monkey-patched.


 I can't see how that's useful at all.  Identity is a fundamental
 property of an object; hence retrieval of it must be a language
 operation.  The fact Python chooses to do otherwise is unfortunate, but
 also irrelevant to my position.

It's useful for the same reason that shadowing any other builtin is 
useful. id() isn't special enough to complicate the simple, and 
effective, execution model just to satisfy philosophers.


 3) The is idiom semantics is direct: a is b directly tests the
 thing you want to test, namely whether a is b. The id() idiom is
 indirect: id(a) == id(b) only indirectly tests whether a is b.
 
 The two expressions are logically equivalent, so I don't see how this
 matters, nor how it is true.

They are not *logically* equivalent. First you have to define what you 
mean by identity, then you have to define what you mean by an ID, and 
then you have to decide whether or not to enforce the rule that identity 
and IDs are 1:1 or not, and if so, under what circumstances. My library 
card ID may, by coincidence, match your drivers licence ID. Doesn't mean 
we're the same person. Entities may share identities, or may have many 
identities. The Borg design pattern, for example, would be an excellent 
candidate for ID:identity being treated as many-to-one.

Even if you decide that treating IDs as 1:1 is the only thing that makes 
sense in your philosophy, in practice that does not hold for Python. IDs 
may be reused by Python. There are circumstances where different objects 
get the same ID. Hence, comparing IDs is not equivalent to identity 
testing.

But I was actually referring to something more fundamental than that. The 
statement a is b is a *direct* statement of identity. John is my 
father. id(a) == id(b) is *indirect*: The only child of John's 
grandfather is the parent of the mother-in-law of my sister-in-law sort 
of thing. (Excuse me if I got the relationships mixed up.)


 4) The id() idiom already breaks if you replace names a, b with
 expressions:

  id([1,2]) == id([3,4])
 True
 
 It's not broken at all.  

It is broken in the sense that id(a) == id(b) is to be treated as 
equivalent to a is b. The above example demonstrates that you CANNOT 
treat them as equivalent.


[...]
 The other solution is to do what Java and C# do: banish id() entirely

Solution to *what problem*?

I do not believe that there is a problem here that needs to be solved. 
Both id() and is are perfectly fine for what they do.


 But that's absolutely wrong. id(x) returns an ID, not an address. It
 just
 happens that, as an accident of implementation, the CPython interpreter
 uses the object address as an ID, because objects can't move. That's
 not the case for all implementations. In Jython, objects can move and
 the address is not static, and so IDs are assigned on demand starting
 with 1:

 steve@runes:~$ jython
 Jython 2.5.1+ (Release_2_5_1, Aug 4 2010, 07:18:19) [OpenJDK Client VM
 (Sun Microsystems Inc.)] on java1.6.0_18 Type help, copyright,
 credits or license for more information. id(42) 1
  id(Hello World!)
 2
  id(None)

 3


 

Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Adam Skutt
On Apr 26, 5:10 am, Steven D'Aprano steve
+comp.lang.pyt...@pearwood.info wrote:
 On Wed, 25 Apr 2012 20:50:21 -0700, Adam Skutt wrote:
  On Apr 25, 8:01 pm, Steven D'Aprano steve
  +comp.lang.pyt...@pearwood.info wrote:
  On Wed, 25 Apr 2012 13:49:24 -0700, Adam Skutt wrote:
   Though, maybe it's better to use a different keyword than 'is'
   though, due to the plain English
   connotations of the term; I like 'sameobj' personally, for whatever
   little it matters.  Really, I think taking away the 'is' operator
   altogether is better, so the only way to test identity is:
       id(x) == id(y)

  Four reasons why that's a bad idea:

  1) The is operator is fast, because it can be implemented directly by
  the interpreter as a simple pointer comparison (or equivalent). The
  id() idiom is slow, because it involves two global lookups and an
  equality comparison. Inside a tight loop, that can make a big
  difference in speed.

  The runtime can optimize the two operations to be equivalent, since they
  are logically equivalent operations.  If you removed 'is', there's
  little reason to believe it would do otherwise.

 I'm afraid you are mistaken there. *By design*, Python allows shadowing
 and monkey-patching of built-ins. (Although not quite to the same degree
 as Ruby, and thank goodness!)

Yes, I understand that. You still haven't explained why this behavior
is correct in this particular situation.  Arguing from the position
of, What Python does must be correct isn't a valid tactic, I'm
afraid.

 It's useful for the same reason that shadowing any other builtin is
 useful. id() isn't special enough to complicate the simple, and
 effective, execution model just to satisfy philosophers.

If overriding id() is useful, then overriding 'is' must be useful
too.  Python is still broken. Unless you can prove the two operations
shouldn't be logically equivalent (and you don't), you can't
meaningfully argue for different semantics for them.  You still end up
with a broken language either way.

 They are not *logically* equivalent. First you have to define what you
 mean by identity, then you have to define what you mean by an ID, and
 then you have to decide whether or not to enforce the rule that identity
 and IDs are 1:1 or not, and if so, under what circumstances.

You're going to have to explain the value of an ID that's not 1:1
with an object's identity, for at least the object's lifecycle, for a
programmer.  If you can't come up with a useful case, then you haven't
said anything of merit.

Plainly, to show they're not logically equivalent, you need to explain
why the guarantee provided by id() is improper.  Then, you need to
generalize it to all programming languages.  Python's concept of
identity is not unique nor special.  It uses the exact same rules as C+
+, C#, Java, and many other languages.

 My library
 card ID may, by coincidence, match your drivers licence ID. Doesn't mean
 we're the same person.

I don't know why you even remotely think this is relevant.  All it
does is further demonstrate that you don't understand the object-
oriented concept of identity at all.  Comparing library IDs and
drivers license IDs is an improper operation.  Languages that can have
multiple IDs, possibly overlapping, /do/ disallow such idiocy.

 identities. The Borg design pattern, for example, would be an excellent
 candidate for ID:identity being treated as many-to-one.

How would inheritance work if I did that?

 Even if you decide that treating IDs as 1:1 is the only thing that makes
 sense in your philosophy, in practice that does not hold for Python. IDs
 may be reused by Python.

They may be reused in all languages I can think of.  They're only
unique for the lifetime of the object, because that's all we need as
programmers.

 There are circumstances where different objects
 get the same ID. Hence, comparing IDs is not equivalent to identity
 testing.

Two objects only get the same ID if one of the objects is dead. The
results of such an comparison are obviously meaningless.  Some
runtimes even try very hard to prevent you from doing such silly
things.


 But I was actually referring to something more fundamental than that. The
 statement a is b is a *direct* statement of identity. John is my
 father. id(a) == id(b) is *indirect*: The only child of John's
 grandfather is the parent of the mother-in-law of my sister-in-law sort
 of thing. (Excuse me if I got the relationships mixed up.)

Again, the fact that you somehow think this absurd family tree is
relevant only shows you're fundamentally confused about what object
oriented identity means.  That's rather depressing, seeing as I've
given you a link to the definition.

In a mathematical sense, you're saying that given f(x) = x+2, using
f(x) is somehow more direct (whatever the hell that even means) than
using 'x+2'.  That's just not true.  We freely and openly interchange
them all the time doing mathematics.  Programming is no different.

 It is broken in the 

Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Adam Skutt
On Apr 26, 1:48 am, John Nagle na...@animats.com wrote:
 On 4/25/2012 5:01 PM, Steven D'Aprano wrote:

  On Wed, 25 Apr 2012 13:49:24 -0700, Adam Skutt wrote:

  Though, maybe it's better to use a different keyword than 'is' though,
  due to the plain English
  connotations of the term; I like 'sameobj' personally, for whatever
  little it matters.  Really, I think taking away the 'is' operator
  altogether is better, so the only way to test identity is:
       id(x) == id(y)

  Four reasons why that's a bad idea:

  1) The is operator is fast, because it can be implemented directly by
  the interpreter as a simple pointer comparison (or equivalent).

     This assumes that everything is, internally, an object.  In CPython,
 that's the case, because Python is a naive interpreter and everything,
 including numbers, is boxed.  That's not true of PyPy or Shed Skin.
 So does is have to force the creation of a temporary boxed object?

That's what C# does AFAIK.  Java defines '==' as value comparison for
primitives and '==' as identity comparison for objects, but I don't
exactly know how one would do that in Python.

Adam
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Chris Angelico
On Thu, Apr 26, 2012 at 9:42 PM, Adam Skutt ask...@gmail.com wrote:
 Would you call the result of casting a C pointer to an int an
 address?  If so, you must call the result of id() an address as well--
 you can't dereference either of them.  If not, then you need to
 provide an alternate name for the result of casting a C pointer to an
 int.

It's an address. You can cast it back to pointer and then dereference
it. But you're talking about C, which is portable assembly language.
When I write C code, I expect to be able to shoot myself in the foot
in numerous ways. With Python, you have to actually work at it a bit,
like:

len = str

Okay, that wasn't very hard, but still, it's not like dereferencing an
uninitialized pointer!

But all this is predicated on a few things:

1) The CPU addresses memory by numbers of a certain size.
2) The C declaration int *ptr represents an address
3) The C declaration (int)ptr turns that address into an integer
that's big enough to store it

Assuming #3 to be correct is a major cause of trouble, but let's
suppose for the moment that it is. What we have is a direct 1:1
relationship between pointers, integers, and object identities. The
fact is, though, that Python does not ever guarantee this.

Side point: In Python 2, id() returns an int, not a long. Is it
possible to be running Python on a 64-bit machine with a 32-bit int
type? And if so, what does CPython do? Return the address modulo 4G?
Because that could result in collisions.

ChrisA
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Robert Kern

On 4/26/12 12:56 PM, Chris Angelico wrote:


Side point: In Python 2, id() returns an int, not a long. Is it
possible to be running Python on a 64-bit machine with a 32-bit int
type?


Yes. Win64 has 64-bit pointers and 32-bit C longs (and thus 32-bit Python ints).


And if so, what does CPython do? Return the address modulo 4G?


It returns a Python long.

Python 2.7.3 (default, Apr 10 2012, 23:24:47) [MSC v.1500 64 bit (AMD64)] on 
win32
Type help, copyright, credits or license for more information.
 import sys
 sys.maxint
2147483647
 id('Hello')
30521584L

--
Robert Kern

I have come to believe that the whole world is an enigma, a harmless enigma
 that is made terrible by our own mad attempt to interpret it as though it had
 an underlying truth.
  -- Umberto Eco

--
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Kiuhnm

On 4/26/2012 2:01, Steven D'Aprano wrote:

On Wed, 25 Apr 2012 13:49:24 -0700, Adam Skutt wrote:


Though, maybe it's better to use a different keyword than 'is' though,
due to the plain English
connotations of the term; I like 'sameobj' personally, for whatever
little it matters.  Really, I think taking away the 'is' operator
altogether is better, so the only way to test identity is:
 id(x) == id(y)


Four reasons why that's a bad idea:

1) The is operator is fast, because it can be implemented directly by
the interpreter as a simple pointer comparison (or equivalent). The id()
idiom is slow, because it involves two global lookups and an equality
comparison. Inside a tight loop, that can make a big difference in speed.

2) The is operator always has the exact same semantics and cannot be
overridden. The id() function can be monkey-patched.

3) The is idiom semantics is direct: a is b directly tests the thing
you want to test, namely whether a is b. The id() idiom is indirect:
id(a) == id(b) only indirectly tests whether a is b.

4) The id() idiom already breaks if you replace names a, b with
expressions:


id([1,2]) == id([3,4])

True


You forgot one:
5) It would be a pain to write (and read)
 if id(my_obj) == id(None)
   and so anyone would come up with his/her own same_as(), 
identical_to(), same_inst() and so on...


Kiuhnm
--
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Chris Angelico
On Thu, Apr 26, 2012 at 10:12 PM, Robert Kern robert.k...@gmail.com wrote:
 Yes. Win64 has 64-bit pointers and 32-bit C longs (and thus 32-bit Python
 ints).

 It returns a Python long.

Ah, that solves that one. Definite improvement in Python 3 with the
merging of the two types, though. Machine integers are simply a
performance optimization for small values.

ChrisA
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Arnaud Delobelle
On 26 April 2012 12:42, Adam Skutt ask...@gmail.com wrote:
 On Apr 26, 5:10 am, Steven D'Aprano steve
 +comp.lang.pyt...@pearwood.info wrote:
 On Wed, 25 Apr 2012 20:50:21 -0700, Adam Skutt wrote:
  On Apr 25, 8:01 pm, Steven D'Aprano steve
  +comp.lang.pyt...@pearwood.info wrote:
  On Wed, 25 Apr 2012 13:49:24 -0700, Adam Skutt wrote:
  [Sterile pedantry]
  [More sterile pedantry]
  [Yet more sterile pedantry]
 [And more]
 [Record breaking levels of sterile pedantry]

Please stop!  Steven, I've learnt a lot from your posts on this list
over the years, but too often you spoil it with your compulsion to
have the last word on every argument you get involved in at any cost.
Some arguments aren't worth winning...

-- 
Arnaud
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Kiuhnm

On 4/26/2012 13:45, Adam Skutt wrote:

On Apr 26, 1:48 am, John Naglena...@animats.com  wrote:

On 4/25/2012 5:01 PM, Steven D'Aprano wrote:


On Wed, 25 Apr 2012 13:49:24 -0700, Adam Skutt wrote:



Though, maybe it's better to use a different keyword than 'is' though,
due to the plain English
connotations of the term; I like 'sameobj' personally, for whatever
little it matters.  Really, I think taking away the 'is' operator
altogether is better, so the only way to test identity is:
  id(x) == id(y)



Four reasons why that's a bad idea:



1) The is operator is fast, because it can be implemented directly by
the interpreter as a simple pointer comparison (or equivalent).


 This assumes that everything is, internally, an object.  In CPython,
that's the case, because Python is a naive interpreter and everything,
including numbers, is boxed.  That's not true of PyPy or Shed Skin.
So does is have to force the creation of a temporary boxed object?


That's what C# does AFAIK.  Java defines '==' as value comparison for
primitives and '==' as identity comparison for objects, but I don't
exactly know how one would do that in Python.


Why should we take from Java one of its worst misfeatures and disfigure 
Python for life?
a==b compares references while a.equals(b) compares values. Really??? 
Come on...

Python's way is much much cleaner.

Kiuhnm
--
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread rusi
On Apr 26, 4:42 pm, Adam Skutt ask...@gmail.com wrote:

 In a mathematical sense, you're saying that given f(x) = x+2, using
 f(x) is somehow more direct (whatever the hell that even means) than
 using 'x+2'.  That's just not true.  We freely and openly interchange
 them all the time doing mathematics.  Programming is no different.

If f(x) and x+2 are freely interchangeable then you have referential
transparency, a property that only purely functional languages have.
In python:
 a = [1,2]
 m1 = [a, a]
 m2 = [[1,2],[1,2]]

may make m1 and m2 seem like the same until you assign to m1[0][0].
eg One would not be able to distinguish m1 and m2 in Haskell.

On the whole I whole-heartedly agree that  'a is b' be replaced by
id(a) == id(b), with id itself replaced by something more obviously
implementational like addrof.

The reasons are fundamental:  The word 'is' is arguably the primal
existential verb.  Whereas 'is' in python is merely a leakage of
implementation up to the programmer level:
http://www.joelonsoftware.com/articles/LeakyAbstractions.html

Such a leakage may be justified just as C allowing inline asm may be
justified.
However dignifying such a leakage with the primal existential verb
causes all the confusions seen on this thread (and the various
stackoverflow questions etc).

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Adam Skutt
On Apr 26, 9:37 am, Kiuhnm kiuhnm03.4t.yahoo.it wrote:
 On 4/26/2012 13:45, Adam Skutt wrote:









  On Apr 26, 1:48 am, John Naglena...@animats.com  wrote:
  On 4/25/2012 5:01 PM, Steven D'Aprano wrote:

  On Wed, 25 Apr 2012 13:49:24 -0700, Adam Skutt wrote:

  Though, maybe it's better to use a different keyword than 'is' though,
  due to the plain English
  connotations of the term; I like 'sameobj' personally, for whatever
  little it matters.  Really, I think taking away the 'is' operator
  altogether is better, so the only way to test identity is:
        id(x) == id(y)

  Four reasons why that's a bad idea:

  1) The is operator is fast, because it can be implemented directly by
  the interpreter as a simple pointer comparison (or equivalent).

       This assumes that everything is, internally, an object.  In CPython,
  that's the case, because Python is a naive interpreter and everything,
  including numbers, is boxed.  That's not true of PyPy or Shed Skin.
  So does is have to force the creation of a temporary boxed object?

  That's what C# does AFAIK.  Java defines '==' as value comparison for
  primitives and '==' as identity comparison for objects, but I don't
  exactly know how one would do that in Python.

 Why should we take from Java one of its worst misfeatures and disfigure
 Python for life?

There are a lot of misfeatures in Java.  Lack of operating overloading
really isn't one of them. I prefer languages that include operator
overloading, but readily understand and accept the arguments against
it.  Nor is the differing behavior for '==' between primitives and
objects a misfeature.

C# and Python do have a misfeature: '==' is identity comparison only
if operator== / __eq__ is not overloaded.  Identity comparison and
value comparison are disjoint operations, so it's entirely
inappropriate to combine them.

I don't necessarily mind if the two operations have the same symbol,
as long as there's some other way in-context to determine which
operation is occurring.  This is the case in C and C++, for example.

 Python's way is much much cleaner.

Nope. Automatically substituting identity equality for value equality
is wrong.  While rare, there are legitimate reasons for the former to
be True while the latter is False.  Moreover, it means that class
authors must remember to write an __eq__ when appropriate and won't
get any sort of error when they forget to do so.  That can lead to
bugs.

Adam
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Chris Angelico
On Fri, Apr 27, 2012 at 12:00 AM, Adam Skutt ask...@gmail.com wrote:
 C# and Python do have a misfeature: '==' is identity comparison only
 if operator== / __eq__ is not overloaded.  Identity comparison and
 value comparison are disjoint operations, so it's entirely
 inappropriate to combine them.

So what should happen if you don't implement __eq__? Should the ==
operator throw an exception? This can be done fairly easily:

class object(object):
def __eq__(self,other):
raise NoYouDontException(Naughty programmer, mustn't do that!)

(Works only if you always explicitly subclass object, even though
that's not necessary in Python 3.)

ChrisA
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Adam Skutt
On Apr 26, 10:18 am, rusi rustompm...@gmail.com wrote:
 On Apr 26, 4:42 pm, Adam Skutt ask...@gmail.com wrote:



  In a mathematical sense, you're saying that given f(x) = x+2, using
  f(x) is somehow more direct (whatever the hell that even means) than
  using 'x+2'.  That's just not true.  We freely and openly interchange
  them all the time doing mathematics.  Programming is no different.

 If f(x) and x+2 are freely interchangeable then you have referential
 transparency, a property that only purely functional languages have.
 In python:

I think you misunderstood what I was trying to explain.  Steven is
trying to claim that there's some sort of meaningful difference
between calling an operation/algorithm/function by some name versus
handing out its definition.  I was merely pointing out that we
routinely substitute the two when it is appropriate to do so.

My apologies if you somehow took that to mean that I was implying
there was referential transparency here.  I couldn't think of a better
example for what I was trying to say.

Adam
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Kiuhnm

On 4/26/2012 16:00, Adam Skutt wrote:

On Apr 26, 9:37 am, Kiuhnmkiuhnm03.4t.yahoo.it  wrote:

On 4/26/2012 13:45, Adam Skutt wrote:










On Apr 26, 1:48 am, John Naglena...@animats.comwrote:

On 4/25/2012 5:01 PM, Steven D'Aprano wrote:



On Wed, 25 Apr 2012 13:49:24 -0700, Adam Skutt wrote:



Though, maybe it's better to use a different keyword than 'is' though,
due to the plain English
connotations of the term; I like 'sameobj' personally, for whatever
little it matters.  Really, I think taking away the 'is' operator
altogether is better, so the only way to test identity is:
   id(x) == id(y)



Four reasons why that's a bad idea:



1) The is operator is fast, because it can be implemented directly by
the interpreter as a simple pointer comparison (or equivalent).



  This assumes that everything is, internally, an object.  In CPython,
that's the case, because Python is a naive interpreter and everything,
including numbers, is boxed.  That's not true of PyPy or Shed Skin.
So does is have to force the creation of a temporary boxed object?



That's what C# does AFAIK.  Java defines '==' as value comparison for
primitives and '==' as identity comparison for objects, but I don't
exactly know how one would do that in Python.


Why should we take from Java one of its worst misfeatures and disfigure
Python for life?


There are a lot of misfeatures in Java.  Lack of operating overloading
really isn't one of them. I prefer languages that include operator
overloading, but readily understand and accept the arguments against
it.  Nor is the differing behavior for '==' between primitives and
objects a misfeature.


The fact that you think that that's differing behaviour is what makes 
it a misfeature. The fact that you think that '==' can take objects as 
operands confirms that Java *does* confuse programmers.



C# and Python do have a misfeature: '==' is identity comparison only
if operator== / __eq__ is not overloaded.  Identity comparison and
value comparison are disjoint operations, so it's entirely
inappropriate to combine them.


They're not disjoint, in fact one almost always implies the other (*).
Python's idea is that, by default, any object is equal to itself and 
only itself. The fact that this is equivalent to identity comparison 
is just a coincidence, from a conceptual point of view.
(*) nan == nan is false, but, at least conceptually, a 'NotComparable' 
exception should be raised instead. That wouldn't be very useful, though.



I don't necessarily mind if the two operations have the same symbol,
as long as there's some other way in-context to determine which
operation is occurring.  This is the case in C and C++, for example.


Python's way is much much cleaner.


Nope. Automatically substituting identity equality for value equality
is wrong.  While rare, there are legitimate reasons for the former to
be True while the latter is False.


There shouldn't be, to be fair.


 Moreover, it means that class
authors must remember to write an __eq__ when appropriate and won't
get any sort of error when they forget to do so.  That can lead to
bugs.


I can agree on that, but that's something you can solve with a minor 
modification to the language. What I was talking about is the core 
design of Java and Python.


Kiuhnm
--
http://mail.python.org/mailman/listinfo/python-list


Re: Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Evan Driscoll
This thread has already beaten a dead horse enough that the horse came 
back as a zombie and was re-killed, but I couldn't help but respond to 
this part:



On 01/-10/-28163 01:59 PM, Adam Skutt wrote:

Code that relies on the identity of a temporary object is generally
incorrect.  This is why C++ explicitly forbids taking the address
(identity) of temporaries.


Except that C++ *doesn't* really forbid taking the address of a 
temporary, at least indirectly:


#include iostream

int const * address_of(int const  x) {
return x;
}

int main() {
std::cout  address_of(1+2)  \n;
}

That complies without warning with GCC 4.6 '-Wall -Wextra', MSVC 2010 
'/W4', and Comeau's online front end, and I am pretty confident that the 
above code is perfectly legal in terms of provoking undefined behavior 
(in the technical C++ sense of your program is now allowed to set your 
cat on fire).


Evan
--
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Ian Kelly
On Thu, Apr 26, 2012 at 3:10 AM, Steven D'Aprano
steve+comp.lang.pyt...@pearwood.info wrote:
 But I was actually referring to something more fundamental than that. The
 statement a is b is a *direct* statement of identity. John is my
 father. id(a) == id(b) is *indirect*: The only child of John's
 grandfather is the parent of the mother-in-law of my sister-in-law sort
 of thing. (Excuse me if I got the relationships mixed up.)

I might have used a different example:

1) John is my father.
2) John has the same social security number as my father.

The first is concise and clearly expresses the intended statement of identity.
The second could be read to imply any number of things: John is my
father.  Somebody at the SSA messed up and gave John the same SSN as
my father.  John is an identity thief.

If the assertion I'm trying to express is that John is my father, then
the direct statement #1 is the best way to convey that, at least in
English.  Likewise, a is b more clearly expresses the intended
comparison than does id(a) == id(b).
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread rusi
On Apr 26, 7:44 pm, Adam Skutt ask...@gmail.com wrote:
 On Apr 26, 10:18 am, rusi rustompm...@gmail.com wrote:

  On Apr 26, 4:42 pm, Adam Skutt ask...@gmail.com wrote:

   In a mathematical sense, you're saying that given f(x) = x+2, using
   f(x) is somehow more direct (whatever the hell that even means) than
   using 'x+2'.  That's just not true.  We freely and openly interchange
   them all the time doing mathematics.  Programming is no different.

  If f(x) and x+2 are freely interchangeable then you have referential
  transparency, a property that only purely functional languages have.
  In python:

 I think you misunderstood what I was trying to explain.  Steven is
 trying to claim that there's some sort of meaningful difference
 between calling an operation/algorithm/function by some name versus
 handing out its definition.  I was merely pointing out that we
 routinely substitute the two when it is appropriate to do so.

 My apologies if you somehow took that to mean that I was implying
 there was referential transparency here.  I couldn't think of a better
 example for what I was trying to say.

 Adam

And my apologies... I forgot to state my main point:
Programmer accessible object identity is the principal impediment to
referential transparency.
In a functional language one can bind a name to a value -- period.
There is nothing more essence-ial -- its platonic id -- to the name
than that and so the whole can of worms connected with object identity
remains sealed within the language implementation.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Terry Reedy

On 4/26/2012 1:48 AM, John Nagle wrote:


This assumes that everything is, internally, an object.  In CPython,
that's the case, because Python is a naive interpreter and everything,
including numbers, is boxed. That's not true of PyPy or Shed Skin.
So does is have to force the creation of a temporary boxed object?


Python Language Reference
3.1. Objects, values and types
Objects are Python’s abstraction for data. All data in a Python program 
is represented by objects or by relations between objects. ...
Every object has an identity, a type and a value. An object’s identity 
never changes once it has been created; ... The ‘is‘ operator compares 
the identity of two objects; the id()function* returns an integer 
representing its identity#. [notes added]


* the built-in function bound to 'id' on startup.
# and that integer must not change for the lifetime of the object.

None of the above is CPython implementation detail.

What the spec 'forces' is observable behavior. Internal shortcuts are 
allowed. If an interpreter 'knows' that 'a' represents anything other 
than None, than it can evaluate 'a is None' as False without boxing 'a' 
anymore than it is already.


The object model above allows for an object to represent or consist of a 
collection of raw, non-object internal data fields. A list is a sequence 
of Python objects. A string is not; it is a sequence of 'characters' or 
'bytes'. Structs and arrays, including numpy arrays, are similar in 
containing non-object values. However, when single characters, bytes, or 
other binary values are extracted and exposed to Python code by indexing 
or iteration, they must be objectivized (or at least are in CPython).


Worrying about 'is' and 'id' forcing objectness is misplaced. Except for 
comparing an object to a pre-defined constant or sentinel, 'is' is 
mainly used for introspection and testing. The main use of 'id()' is to 
make unambiguous string representations of functions, classes, and modules.


The real 'culprits' for (potentially) forcing objectness are everyday 
indexing and iteration. Numpy avoids boxing internal binary values by 
providing functions that operate on numpy arrays *without* exposing the 
internal values at the Python level. I believe that psycho and now pypy 
can analyze a function to determine whether machine ints and floats can 
used without being boxed,


--
Terry Jan Reedy


--
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread John Nagle

On 4/26/2012 4:45 AM, Adam Skutt wrote:

On Apr 26, 1:48 am, John Naglena...@animats.com  wrote:

On 4/25/2012 5:01 PM, Steven D'Aprano wrote:


On Wed, 25 Apr 2012 13:49:24 -0700, Adam Skutt wrote:



Though, maybe it's better to use a different keyword than 'is' though,
due to the plain English
connotations of the term; I like 'sameobj' personally, for whatever
little it matters.  Really, I think taking away the 'is' operator
altogether is better, so the only way to test identity is:
  id(x) == id(y)



Four reasons why that's a bad idea:



1) The is operator is fast, because it can be implemented directly by
the interpreter as a simple pointer comparison (or equivalent).


 This assumes that everything is, internally, an object.  In CPython,
that's the case, because Python is a naive interpreter and everything,
including numbers, is boxed.  That's not true of PyPy or Shed Skin.
So does is have to force the creation of a temporary boxed object?


That's what C# does AFAIK.  Java defines '==' as value comparison for
primitives and '==' as identity comparison for objects, but I don't
exactly know how one would do that in Python.


   I would suggest that is raise ValueError for the ambiguous cases.
If both operands are immutable, is should raise ValueError.
That's the case where the internal representation of immutables
shows through.

   If this breaks a program, it was broken anyway.  It will
catch bad comparisons like

if x is 1000 :
...

which is implementation dependent.

John Nagle
--
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Adam Skutt
On Apr 26, 12:02 pm, Kiuhnm kiuhnm03.4t.yahoo.it wrote:
 On 4/26/2012 16:00, Adam Skutt wrote:
  On Apr 26, 9:37 am, Kiuhnmkiuhnm03.4t.yahoo.it  wrote:
  On 4/26/2012 13:45, Adam Skutt wrote:

  On Apr 26, 1:48 am, John Naglena...@animats.comwrote:
This assumes that everything is, internally, an object.  In 
  CPython,
  that's the case, because Python is a naive interpreter and everything,
  including numbers, is boxed.  That's not true of PyPy or Shed Skin.
  So does is have to force the creation of a temporary boxed object?

  That's what C# does AFAIK.  Java defines '==' as value comparison for
  primitives and '==' as identity comparison for objects, but I don't
  exactly know how one would do that in Python.

  Why should we take from Java one of its worst misfeatures and disfigure
  Python for life?

  There are a lot of misfeatures in Java.  Lack of operating overloading
  really isn't one of them. I prefer languages that include operator
  overloading, but readily understand and accept the arguments against
  it.  Nor is the differing behavior for '==' between primitives and
  objects a misfeature.

 The fact that you think that that's differing behaviour is what makes
 it a misfeature. The fact that you think that '==' can take objects as
 operands confirms that Java *does* confuse programmers.


The equality operator can absolutely be used between two objects.  Try
it if you don't believe me.  It always does identity comparison when
given two objects. It can also be given two primitives, and in this
case, it does value comparison.  Despite performing different
operations with the same symbol, there's little risk of confusion
because I can trivially figure out if a variable is an object or an
primitive.

  C# and Python do have a misfeature: '==' is identity comparison only
  if operator== / __eq__ is not overloaded.  Identity comparison and
  value comparison are disjoint operations, so it's entirely
  inappropriate to combine them.

 They're not disjoint, in fact one almost always implies the other (*).

Almost always isn't a rebuttal.  There's no requirement whatsoever
for the results of identity comparison to be related to the results of
value comparison, ergo they are disjoint.  Changing one doesn't have
to influence the other.  Please note that I never advocated doing what
Java does, I merely noted what it does.

 Python's idea is that, by default, any object is equal to itself and
 only itself.

Which is just wrong-headed.  Many types have no meaningful definition
for value equality, ergo any code that attempts to perform the
operation is incorrect.

 (*) nan == nan is false, but, at least conceptually, a 'NotComparable'
 exception should be raised instead. That wouldn't be very useful, though.

  Python's way is much much cleaner.

  Nope. Automatically substituting identity equality for value equality
  is wrong.  While rare, there are legitimate reasons for the former to
  be True while the latter is False.

 There shouldn't be, to be fair.


Which is the whole problem.  It's nice to keep erroneous conditions
out of your domain, but it's just not always possible.  I don't know
how you implement NaN (which you need) without allowing for this.  I
don't know how you implement SQL NULL without allowing for this.
While lots of problems can avoid this issue, I'm not sure all problems
can.  Moreover, I don't know how to implement a value comparison for
many objects, so the operation should just be undefined.

I should point out that I was a little hasty in painting Python with
the same brush as C# and excluding Java.  Python and Java are equally
bad: value equality defaults to identity equality but there are
distinct operations for telling them apart.  People want identity
equality in Python write 'is', not '=='.  People who explicitly want
value equality in Java write 'equals()'.  I apologize, and blame
skipping breakfast this morning.

C# is arguably worse, since '==' on objects is defined as identity
equality unless it has been overridden.  This means that that the
intent of the operation varies with no easy way to figure it out in
context, you simply have to know.  C# also provides a way to test only
for identity, Object.ReferenceEquals(), but it's underused.
Ultimately this is really a problem of documentation: the language
shouldn't encourage conflation of intent in the manner it does.

   Moreover, it means that class
  authors must remember to write an __eq__ when appropriate and won't
  get any sort of error when they forget to do so.  That can lead to
  bugs.

 I can agree on that, but that's something you can solve with a minor
 modification to the language. What I was talking about is the core
 design of Java and Python.

The only difference is I see is which comparison is performed by the
== symbol.  But I don't see how nor why Python's decisions are
superior to Java.  Plus, I never suggested that Python should do what
Java does, merely noted what it did since it 

Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Adam Skutt
On Apr 26, 1:34 pm, rusi rustompm...@gmail.com wrote:
 On Apr 26, 7:44 pm, Adam Skutt ask...@gmail.com wrote:
  On Apr 26, 10:18 am, rusi rustompm...@gmail.com wrote:

   On Apr 26, 4:42 pm, Adam Skutt ask...@gmail.com wrote:

In a mathematical sense, you're saying that given f(x) = x+2, using
f(x) is somehow more direct (whatever the hell that even means) than
using 'x+2'.  That's just not true.  We freely and openly interchange
them all the time doing mathematics.  Programming is no different.

   If f(x) and x+2 are freely interchangeable then you have referential
   transparency, a property that only purely functional languages have.
   In python:

  I think you misunderstood what I was trying to explain.  Steven is
  trying to claim that there's some sort of meaningful difference
  between calling an operation/algorithm/function by some name versus
  handing out its definition.  I was merely pointing out that we
  routinely substitute the two when it is appropriate to do so.

  My apologies if you somehow took that to mean that I was implying
  there was referential transparency here.  I couldn't think of a better
  example for what I was trying to say.

  Adam

 And my apologies... I forgot to state my main point:
 Programmer accessible object identity is the principal impediment to
 referential transparency.
 In a functional language one can bind a name to a value -- period.
 There is nothing more essence-ial -- its platonic id -- to the name
 than that and so the whole can of worms connected with object identity
 remains sealed within the language implementation.

Yes, I agree that object identity is a major hold up, but I think side
effects are a bigger problem.  It's possible in C++ to create types
that behave like the primitive types without too much difficulty,
hence making object identity unimportant.  However, it's considerably
more difficult in C++ to write side-effect free code[1].  This is a
bit of an apple and orange thing, though. ;)

I often wonder what the world would be like if Python, C#, and Java
embraced value types more, and had better support for pure functions.
Unfortunately, building a language where all types behave like that is
rather difficult, as the Haskell guys have shown us ;).

Adam

[1] Or even just code that only uses side-effects the compiler
understands.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Adam Skutt
On Apr 26, 2:31 pm, John Nagle na...@animats.com wrote:
 On 4/26/2012 4:45 AM, Adam Skutt wrote:
  On Apr 26, 1:48 am, John Naglena...@animats.com  wrote:
  On 4/25/2012 5:01 PM, Steven D'Aprano wrote:

  On Wed, 25 Apr 2012 13:49:24 -0700, Adam Skutt wrote:

  Though, maybe it's better to use a different keyword than 'is' though,
  due to the plain English
  connotations of the term; I like 'sameobj' personally, for whatever
  little it matters.  Really, I think taking away the 'is' operator
  altogether is better, so the only way to test identity is:
        id(x) == id(y)

  Four reasons why that's a bad idea:

  1) The is operator is fast, because it can be implemented directly by
  the interpreter as a simple pointer comparison (or equivalent).

       This assumes that everything is, internally, an object.  In CPython,
  that's the case, because Python is a naive interpreter and everything,
  including numbers, is boxed.  That's not true of PyPy or Shed Skin.
  So does is have to force the creation of a temporary boxed object?

  That's what C# does AFAIK.  Java defines '==' as value comparison for
  primitives and '==' as identity comparison for objects, but I don't
  exactly know how one would do that in Python.

     I would suggest that is raise ValueError for the ambiguous cases.
 If both operands are immutable, is should raise ValueError.

I don't know how you would easily detect user-defined immutable types,
nor do I see why such an operation should be an error.  I think it
would end up violating the principal of least surprise in a lot of
cases, especially when talking about things like immutable sets, maps,
or other complicated data structures.

What I think you want is what I said above: ValueError raised when
either operand is a /temporary/ object.  Really, it should probably be
a parse-time error, since you could (and should) make the
determination at parse time.

 That's the case where the internal representation of immutables
 shows through.

You still have this problem with mutable temporary objects, as my
little snipped showed. You're still going to get a result that's
inconsistent and/or surprising sooner or later.  The problem is the
temporary nature of the object, not mutability.


     If this breaks a program, it was broken anyway.  It will
 catch bad comparisons like

      if x is 1000 :
         ...

 which is implementation dependent.

Yes, I agree that a correct fix shouldn't break anything except
already broken programs.

Adam
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Ian Kelly
On Thu, Apr 26, 2012 at 1:34 PM, Adam Skutt ask...@gmail.com wrote:
 What I think you want is what I said above: ValueError raised when
 either operand is a /temporary/ object.  Really, it should probably be
 a parse-time error, since you could (and should) make the
 determination at parse time.

I'm not sure precisely what you mean by temporary object, so I am
taking it to mean an object that is referenced only by the VM stack
(or something equivalent for other implementations).

In that case: no, you can't.  Take f() is g(), where the code
objects of f and g are supplied at runtime.  Are the objects returned
by either of those expressions temporary?  Without being able to do
static analysis of the code of f and g, there is no way to know.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Chris Angelico
On Fri, Apr 27, 2012 at 7:39 AM, Ian Kelly ian.g.ke...@gmail.com wrote:
 I'm not sure precisely what you mean by temporary object, so I am
 taking it to mean an object that is referenced only by the VM stack
 (or something equivalent for other implementations).

 In that case: no, you can't.  Take f() is g(), where the code
 objects of f and g are supplied at runtime.  Are the objects returned
 by either of those expressions temporary?  Without being able to do
 static analysis of the code of f and g, there is no way to know.

The expression itself will have references to all its operands (at
least conceptually). If their refcounts are precisely 1, then the
objects are temporaries and will be disposable as soon as the
expression's fully evaluated.

ChrisA
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Ian Kelly
On Thu, Apr 26, 2012 at 3:51 PM, Chris Angelico ros...@gmail.com wrote:
 On Fri, Apr 27, 2012 at 7:39 AM, Ian Kelly ian.g.ke...@gmail.com wrote:
 I'm not sure precisely what you mean by temporary object, so I am
 taking it to mean an object that is referenced only by the VM stack
 (or something equivalent for other implementations).

 In that case: no, you can't.  Take f() is g(), where the code
 objects of f and g are supplied at runtime.  Are the objects returned
 by either of those expressions temporary?  Without being able to do
 static analysis of the code of f and g, there is no way to know.

 The expression itself will have references to all its operands (at
 least conceptually).

Yes, the references on the VM stack.

 If their refcounts are precisely 1, then the
 objects are temporaries and will be disposable as soon as the
 expression's fully evaluated.

You can't check ref counts at parse time.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Chris Angelico
On Fri, Apr 27, 2012 at 8:04 AM, Ian Kelly ian.g.ke...@gmail.com wrote:
 You can't check ref counts at parse time.

I know, and it'd be impossible to recognize at parse time for any but
the most trivial cases (since names can always be rebound). The
detection of temporaries can only be done at run time.

ChrisA
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Nobody
On Thu, 26 Apr 2012 11:31:39 -0700, John Nagle wrote:

 I would suggest that is raise ValueError for the ambiguous cases.
 If both operands are immutable, is should raise ValueError. That's the
 case where the internal representation of immutables shows through.

This breaks one of the most common uses of is, i.e. x is None.

And it doesn't prevent a programmer from consfusing is and == with
mutable types.

 If this breaks a program, it was broken anyway.  It will
 catch bad comparisons like
 
  if x is 1000 :
   ...
 
 which is implementation dependent.

The only way to completely eliminate bugs caused by the programmer relying
upon implementation-dependent behaviour is to eliminate implementation-
dependent behaviour altogether, which is throwing the baby out with the
bath water, IMHO.

All practical languages have some implementation-defined behaviour, often
far more problematic than Python's.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Kiuhnm

On 4/26/2012 20:54, Adam Skutt wrote:

On Apr 26, 12:02 pm, Kiuhnmkiuhnm03.4t.yahoo.it  wrote:

On 4/26/2012 16:00, Adam Skutt wrote:

On Apr 26, 9:37 am, Kiuhnmkiuhnm03.4t.yahoo.it   wrote:

On 4/26/2012 13:45, Adam Skutt wrote:



On Apr 26, 1:48 am, John Naglena...@animats.com wrote:

   This assumes that everything is, internally, an object.  In CPython,
that's the case, because Python is a naive interpreter and everything,
including numbers, is boxed.  That's not true of PyPy or Shed Skin.
So does is have to force the creation of a temporary boxed object?



That's what C# does AFAIK.  Java defines '==' as value comparison for
primitives and '==' as identity comparison for objects, but I don't
exactly know how one would do that in Python.



Why should we take from Java one of its worst misfeatures and disfigure
Python for life?



There are a lot of misfeatures in Java.  Lack of operating overloading
really isn't one of them. I prefer languages that include operator
overloading, but readily understand and accept the arguments against
it.  Nor is the differing behavior for '==' between primitives and
objects a misfeature.


The fact that you think that that's differing behaviour is what makes
it a misfeature. The fact that you think that '==' can take objects as
operands confirms that Java *does* confuse programmers.



The equality operator can absolutely be used between two objects.  Try
it if you don't believe me.  It always does identity comparison when
given two objects. It can also be given two primitives, and in this
case, it does value comparison.  Despite performing different
operations with the same symbol, there's little risk of confusion
because I can trivially figure out if a variable is an object or an
primitive.


No, it can't be used between objects but only between primitives and 
references (which should be regarded as primitives, by the way). If you 
understand that your 'a' is not really an object but a reference to it, 
everything becomes clear and you see that '==' always do the same thing.
You might tell me that that's just an implementation detail, but when an 
implementation detail is easier to understand and makes more sense than 
the whole abstraction which is built upon it, something is seriously wrong.
The distinction between primitives and objects is unfortunate. It is as 
if Java tried to get rid of pointers but never completely succeeded in 
doing that.
It's the distinction between primitives and objects that should've been 
an implementation detail, IMO.


Python's lack of this misfeature is what I'm really fond of.

Everything else you said, I can agree on.


C# and Python do have a misfeature: '==' is identity comparison only
if operator== / __eq__ is not overloaded.  Identity comparison and
value comparison are disjoint operations, so it's entirely
inappropriate to combine them.


They're not disjoint, in fact one almost always implies the other (*).


Almost always isn't a rebuttal.  There's no requirement whatsoever
for the results of identity comparison to be related to the results of
value comparison, ergo they are disjoint.  Changing one doesn't have
to influence the other.  Please note that I never advocated doing what
Java does, I merely noted what it does.


Python's idea is that, by default, any object is equal to itself and
only itself.


Which is just wrong-headed.  Many types have no meaningful definition
for value equality, ergo any code that attempts to perform the
operation is incorrect.


(*) nan == nan is false, but, at least conceptually, a 'NotComparable'
exception should be raised instead. That wouldn't be very useful, though.



Python's way is much much cleaner.



Nope. Automatically substituting identity equality for value equality
is wrong.  While rare, there are legitimate reasons for the former to
be True while the latter is False.


There shouldn't be, to be fair.



Which is the whole problem.  It's nice to keep erroneous conditions
out of your domain, but it's just not always possible.  I don't know
how you implement NaN (which you need) without allowing for this.  I
don't know how you implement SQL NULL without allowing for this.
While lots of problems can avoid this issue, I'm not sure all problems
can.  Moreover, I don't know how to implement a value comparison for
many objects, so the operation should just be undefined.

I should point out that I was a little hasty in painting Python with
the same brush as C# and excluding Java.  Python and Java are equally
bad: value equality defaults to identity equality but there are
distinct operations for telling them apart.  People want identity
equality in Python write 'is', not '=='.  People who explicitly want
value equality in Java write 'equals()'.  I apologize, and blame
skipping breakfast this morning.

C# is arguably worse, since '==' on objects is defined as identity
equality unless it has been overridden.  This means that that the
intent of the operation varies with no easy 

Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Paul Rubin
Nobody nob...@nowhere.com writes:
 All practical languages have some implementation-defined behaviour, often
 far more problematic than Python's.

The usual reason for accepting implementation-defined behavior is to
enable low-level efficiency hacks written for specific machines.  C and
C++ are used for that sort of purpose, so they leave many things
implementation-defined.  Python doesn't have the same goals and should
leave less up to the implementation.  Java, Ada, Standard ML, etc.  all
try to eliminate implementation-defined behavior in the language much
more than Python does.  I don't have any idea why you consider that to
be throwing the baby out with the bath water.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Steven D'Aprano
On Thu, 26 Apr 2012 12:22:55 -0700, Adam Skutt wrote:

 I often wonder what the world would be like if Python, C#, and Java
 embraced value types more, and had better support for pure functions.

They would be slower, require more memory, harder to use, and far, far 
less popular. Some other languages just like Python, C# and Java would be 
invented to fill those niches, and the functional-obsessed crowd would 
then complain that they wished those languages would be more like Python, 
C# and Java.



-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Mark Lawrence

On 20/04/2012 20:10, dmitrey wrote:

I have spent some time searching for a bug in my code, it was due to
different work of is with () and []:

() is ()

True

[] is []

False

(Python 2.7.2+ (default, Oct  4 2011, 20:03:08)
[GCC 4.6.1] )

Is this what it should be or maybe yielding unified result is better?
D.


Congratulations, you've managed to introduce the most useless thread on 
this ng/ml that I've come across in the ten years that I've been using 
(c)Python.


I've never ever thought about using this weird thing called id in my 
code, (which comes later in all the responses) so why do some people 
think it's so important?


--
Cheers.

Mark Lawrence.

--
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Adam Skutt
On Apr 26, 6:34 pm, Kiuhnm kiuhnm03.4t.yahoo.it wrote:
 On 4/26/2012 20:54, Adam Skutt wrote:
  On Apr 26, 12:02 pm, Kiuhnmkiuhnm03.4t.yahoo.it  wrote:
  On 4/26/2012 16:00, Adam Skutt wrote:
  On Apr 26, 9:37 am, Kiuhnmkiuhnm03.4t.yahoo.it   wrote:
  The fact that you think that that's differing behaviour is what makes
  it a misfeature. The fact that you think that '==' can take objects as
  operands confirms that Java *does* confuse programmers.

  The equality operator can absolutely be used between two objects.  Try
  it if you don't believe me.  It always does identity comparison when
  given two objects. It can also be given two primitives, and in this
  case, it does value comparison.  Despite performing different
  operations with the same symbol, there's little risk of confusion
  because I can trivially figure out if a variable is an object or an
  primitive.

 No, it can't be used between objects but only between primitives and
 references (which should be regarded as primitives, by the way).

The only way to access an object is through a reference.

 If you
 understand that your 'a' is not really an object but a reference to it,
 everything becomes clear and you see that '==' always do the same thing.

Yes, object identity is implemented almost? everywhere by comparing
the value of two pointers (references)[1]. I've already said I'm not
really sure how else one would go about implementing it.

 You might tell me that that's just an implementation detail, but when an
 implementation detail is easier to understand and makes more sense than
 the whole abstraction which is built upon it, something is seriously wrong.

I'm not sure what abstraction is being built here.  I think you have
me confused for someone else, possibly Steven.

You're missing the big picture. The two comparisons are asking
different questions:
Value equality asks if the operands 'have the same state'
regardless of how they exist in memory.
Identity equality asks if the two operands are the same block of
memory.

The two are distinct because not all types support both operations.

If I write a function that does a value comparison, then it should do
value comparison on _every type that can be passed to it_, regardless
of whether the type is a primitive or an object, whether it has value
or reference semantics, and  regardless of how value comparison is
actually implemented.  If I write some function:
f(x : T, y : U) = x == y
where T and U are some unknown types, then I want the function to do a
value comparison for every type pairing that allows the function to
compile.  Likewise, if I write a function that does identity
comparison, then it logically wants to do identity comparison on
_every type that can be passed to it_.

To accomplish this, I must have a distinct way of asking each
question.  In Python we have '==' and 'is'[2]; in Java we have
'Object.equals()' and '=='; in C and C++ we distinguish by the types
of the variables being compared (T and T*).

Java gives '==' a different meaning for primitive types, but that
turns out to be OK because I can't write a function that takes both a
primitive type and a reference type at the same position.  Yes, the
reason it does this is due to what I said above, but that doesn't have
any bearing on why we pick one operation over the other as
programmers.

 The distinction between primitives and objects is unfortunate. It is as
 if Java tried to get rid of pointers but never completely succeeded in
 doing that.

 It's the distinction between primitives and objects that should've been
 an implementation detail, IMO.

 Python's lack of this misfeature is what I'm really fond of.

If anything, you have that backwards.  Look at Python: all variables
in Python have pointer semantics, not value semantics.  In imperative
languages, pointers have greater utility over value types because not
all types can obey the rules for value types.  For example, I don't
know how to give value semantics to something like a I/O object (e.g,
file, C++ fstream, C FILE), since I don't know how to create
independent copies.

One can obviously create an imperative language without pointers, but
I/O gets rather tricky.

Adam

[1] Though it need not be (and often isn't) as simple as comparing two
integers.

[2] Well, I suspect 'is' gets used mostly for comparisons against
None, True, and False in Python.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Adam Skutt
On Thu, Apr 26, 2012 at 12:05 PM, Evan Driscoll drisc...@cs.wisc.edu wrote:
 This thread has already beaten a dead horse enough that the horse came back
 as a zombie and was re-killed, but I couldn't help but respond to this part:


 On 01/-10/-28163 01:59 PM, Adam Skutt wrote:

 Code that relies on the identity of a temporary object is generally
 incorrect.  This is why C++ explicitly forbids taking the address
 (identity) of temporaries.


 Except that C++ *doesn't* really forbid taking the address of a temporary,
 at least indirectly:

    #include iostream

    int const * address_of(int const  x) {
        return x;
    }

    int main() {
        std::cout  address_of(1+2)  \n;
    }

 That complies without warning with GCC 4.6 '-Wall -Wextra', MSVC 2010 '/W4',
 and Comeau's online front end, and I am pretty confident that the above code
 is perfectly legal in terms of provoking undefined behavior (in the
 technical C++ sense of your program is now allowed to set your cat on
 fire).

Yes, you can get a const reference to a temporary object, but that's
the only thing you can do.  This is intentional, so you can use
temporaries (e.g., std::string(Hello World) ) in the same contexts
where one would use a literal (e.g., 3 or 4.2).  Note that it's
impossible to mutate the temporary and impossible for the reference to
outlive the temporary.

What the standard says is:  The result of the unary  operator is a
pointer to its operand. The operand shall be an lvalue or a
qualified-id.  The unary  operator is known as the address-of
operator.  The C++ standard is actually going further than forbidding
temporaries, it forbids rvalues, which are things one expects to see
on the Right hand side of an assignment, or =.

One of Scott Meyer's Effective C++ books covers all of this in great
detail, including how you can get a temporary that's an lvalue as
opposed to an rvalue.

Adam
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Adam Skutt
On Thu, Apr 26, 2012 at 5:39 PM, Ian Kelly ian.g.ke...@gmail.com wrote:
 On Thu, Apr 26, 2012 at 1:34 PM, Adam Skutt ask...@gmail.com wrote:
 What I think you want is what I said above: ValueError raised when
 either operand is a /temporary/ object.  Really, it should probably be
 a parse-time error, since you could (and should) make the
 determination at parse time.

 I'm not sure precisely what you mean by temporary object, so I am
 taking it to mean an object that is referenced only by the VM stack
 (or something equivalent for other implementations).

 In that case: no, you can't.  Take f() is g(), where the code
 objects of f and g are supplied at runtime.  Are the objects returned
 by either of those expressions temporary?  Without being able to do
 static analysis of the code of f and g, there is no way to know.

A temporary object would be anything that need not be alive longer
than the duration of the 'is' operation.  I am not a Python language
expert so that definition may not be exactly correct or workable for
Python.

In the example:
 [1, 2] is [3, 4]

[1,2] and [3,4] don't need to exist before the 'is' operation, nor
after it, so they are temporaries.

Adam
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Adam Skutt
On Apr 26, 7:33 pm, Steven D'Aprano steve
+comp.lang.pyt...@pearwood.info wrote:
 On Thu, 26 Apr 2012 12:22:55 -0700, Adam Skutt wrote:
  I often wonder what the world would be like if Python, C#, and Java
  embraced value types more, and had better support for pure functions.

 They would be slower, require more memory,

Funny, Haskell frequently beats C in both categories.  MATLAB is
faster and more memory efficient than naive C matrix code, since it
has a very efficient copy-on-write implementation.  As the various C++
matrix libraries will show you, efficient COW is much harder when you
have to deal with C++ aliasing rules.

 harder to use, and far, far less popular.

Alas, these two are probably true.

Adam
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Paul Rubin
Adam Skutt ask...@gmail.com writes:
 harder to use, and far, far less popular.
 Alas, these two are probably true.

Haskell is kind of abstruse and has a notoriously steep learning curve,
as it's mostly meant as a research testbed and as a playground for
language geeks.  ML/OCaml is by all accounts much easier, and I know of
a couple of former Python projects that successfully migrated to OCaml
once Python's warts and low performance got too annoying.  Erlang (which
is functional but untyped) has also been displacing Python in some
settings.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Mark Lawrence

On 27/04/2012 00:57, Adam Skutt wrote:

...And Saint Adam Skutt raised the hand grenade up on high, saying, O 
LORD, bless this Thy hand grenade that with it Thou mayest blow Thine Id 
to tiny bits, in Thy mercy. And the LORD did grin and the people did 
feast upon the lambs and sloths and carp and anchovies and orangutans 
and breakfast cereals, and fruit bats and large chu... [At this point, 
the friar is urged by Brother Maynard to skip a bit, brother]... And 
the LORD spake, saying, First shalt thou take out the Holy Pin, then 
shalt thou count to three, no more, no less. Three shall be the number 
thou shalt count, and the number of the counting shall be three. Four 
shalt thou not count, neither count thou two, excepting that thou then 
proceed to three. Five is right out. Once the number three, being the 
third number, be reached, then lobbest thou thy Holy Hand Grenade of 
Antioch towards thy foe, who being naughty in My sight, shall snuff it.


--
Cheers.

Mark Lawrence.

--
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Steven D'Aprano
On Thu, 26 Apr 2012 17:16:10 -0700, Adam Skutt wrote:

 On Apr 26, 7:33 pm, Steven D'Aprano steve
 +comp.lang.pyt...@pearwood.info wrote:
 On Thu, 26 Apr 2012 12:22:55 -0700, Adam Skutt wrote:
  I often wonder what the world would be like if Python, C#, and Java
  embraced value types more, and had better support for pure functions.

 They would be slower, require more memory,
 
 Funny, Haskell frequently beats C in both categories.

We've both been guilty of this, but don't confuse a language 
implementation with a language. Haskell and C are languages, which in a 
sense are like Platonic ideals: languages specify behaviour and 
semantics, but have no costs.

When talking about resource usage, you need to talk about concrete 
implementations of concrete tests, not hand-wavy language X is faster. 
And I'm afraid that your claim of Haskell frequently beating C doesn't 
stand up to scrutiny.

http://shootout.alioth.debian.org/u64q/benchmark.php?test=alllang=ghclang2=gcc

I'm seeing code generated by the Haskell GHC compiler being 2-4 times 
slower than code from the C gcc compiler, and on average using 2-3 times 
as much memory (and as much as 7 times).

Feel free to find your own set of benchmarks that show the opposite. I'd 
be interested to see under what conditions Haskell might be faster than C.



-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread OKB (not okblacke)
Adam Skutt wrote:

 If I write a function that does a value comparison, then it should
 do value comparison on _every type that can be passed to it_,
 regardless of whether the type is a primitive or an object, whether
 it has value or reference semantics, and  regardless of how value
 comparison is actually implemented.  If I write some function:
 f(x : T, y : U) = x == y
 where T and U are some unknown types, then I want the function to
 do a value comparison for every type pairing that allows the
 function to compile.  Likewise, if I write a function that does
 identity comparison, then it logically wants to do identity
 comparison on _every type that can be passed to it_.

What you say here makes perfect sense, but also shows that you 
really shouldn't be using Python if you want stuff to work this way.  In 
Python any value of any type can be passed to any function.  The claims 
you are making about object identity and object equality are reasonable, 
but as you show here, to really handle them requires dragging in a huge 
amount of type-system baggage.  Python's behavior is perfectly well-
defined.  You might think it's not the best way to do it based on 
abstract conceptual frameworks for how programming languages should 
work, but it works just fine.


-- 
--OKB (not okblacke)
Brendan Barnwell
Do not follow where the path may lead.  Go, instead, where there is
no path, and leave a trail.
--author unknown
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Devin Jeanpierre
On Thu, Apr 26, 2012 at 7:33 PM, Steven D'Aprano
steve+comp.lang.pyt...@pearwood.info wrote:
 On Thu, 26 Apr 2012 12:22:55 -0700, Adam Skutt wrote:

 I often wonder what the world would be like if Python, C#, and Java
 embraced value types more, and had better support for pure functions.

 They would be slower, require more memory, harder to use, and far, far
 less popular.

That's odd. PyPy supports value types and pure functions as a
performance optimization.

For reference, see e.g.

http://morepypy.blogspot.ca/2011/03/controlling-tracing-of-interpreter-with_15.html
http://morepypy.blogspot.ca/2011/08/visualization-of-jitted-code.html

PyPy can detect some pure functions (or purity annotations) and can
run them at (JIT-)compile-time to speed up the runtime. Also, JIT'd
code uses unboxed values, rather than objects. (So it can unbox
something once, then do all the arithmetic, then box again).

(Of course, this is only a special case of a value type, as far as I
understand the term. But hey!)


Also somebody else was talking about Haskell being crazy fast, but if
you want a really fast functional language, take a look at ATS (an ML
variant). (Also pay close attention to the bytes of code comparison
-- it's rare one sees a language more verbose than C)

http://shootout.alioth.debian.org/u64q/benchmark.php?test=alllang=atslang2=gcc

-- Devin
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-26 Thread Chris Angelico
On Fri, Apr 27, 2012 at 12:47 PM, Steven D'Aprano
steve+comp.lang.pyt...@pearwood.info wrote:
 On Thu, 26 Apr 2012 17:16:10 -0700, Adam Skutt wrote:

 On Apr 26, 7:33 pm, Steven D'Aprano steve
 +comp.lang.pyt...@pearwood.info wrote:
 On Thu, 26 Apr 2012 12:22:55 -0700, Adam Skutt wrote:
  I often wonder what the world would be like if Python, C#, and Java
  embraced value types more, and had better support for pure functions.

 They would be slower, require more memory,

 Funny, Haskell frequently beats C in both categories.

 I'm seeing code generated by the Haskell GHC compiler being 2-4 times
 slower than code from the C gcc compiler, and on average using 2-3 times
 as much memory (and as much as 7 times).

Also, I don't see a Python interpreter written in Haskell that's
outperforming CPython.

ChrisA
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-25 Thread Thomas Rachel

Am 24.04.2012 15:25 schrieb rusi:


Identity, sameness, equality and the verb to be are all about the same
concept(s) and their definitions are *intrinsically* circular; see
http://plato.stanford.edu/entries/identity/#2


Mybe in real life language. In programming and mathematics there are 
several forms of equality, where identity (≡) is stronger than equality (=).


Two objects can be equal (=) without being identical (≡), but not the 
other way.


As the ≡ is quite hard to type, programming languages tend to use other 
operators for this.


E.g., in C, you can have

int a;
int b;
a = 4;
b = 4;

Here a and b are equal, but not identical. One can be changed without 
changing the other.


With

int x;
int *a=x, *b=x;

*a and *b are identical, as they point to the same location.

*a = 4 results in *b becoming 4 as well.


In Python, you can have the situations described here as well.

You can have a list and bind it to 2 names, or you can take 2 lists and 
bind them to that name.


a = [3]
b = [3]

Here a == b is True, while a is b results in False.


Thomas




And the seeming simplicity of the circular definitions hide the actual
complexity of 'to be'
for python:  http://docs.python.org/reference/expressions.html#id26
(footnote 7)
for math/philosophy: 
http://www.math.harvard.edu/~mazur/preprints/when_is_one.pdf


--
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-25 Thread Nobody
On Mon, 23 Apr 2012 10:01:24 -0700, Paul Rubin wrote:

 I can't think of a single case where 'is' is ill-defined.
 
 If I can't predict the output of
 
 print (20+30 is 30+20)  # check whether addition is commutative print
 (20*30 is 30*20)  # check whether multiplication is commutative
 
 by just reading the language definition and the code, I'd have to say is
 is ill-defined.

If anything is ill-defined, then it's + and *, i.e. it's unspecified
whether the value which they return is a unique object or a reference to
some other object.

More accurately, the existence of is, is not and id cause many other
constructs to have ill-defined behaviour.

 a is b is true iff 'a' and 'b' are the same object. Why should 'is'
 lie to the user?
 
 Whether a and b are the same object is implementation-dependent.

And what's wrong with that? If you want a language which precisely
specifies all observable behaviour, you're going to end up with a rather
useless language. For a start, it can't have a time() function. For
similar reasons, you can't have networking or any form of preemptive
concurrency (which includes any form of inter-process communication on an
OS which uses preemptive multi-tasking).

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-25 Thread Steven D'Aprano
On Wed, 25 Apr 2012 13:42:31 +0200, Thomas Rachel wrote:

 Two objects can be equal (=) without being identical (≡), but not the
 other way.


 x = float('nan')
 y = x
 x is y
True
 x == y
False


By the way, in mathematics, ≡ normally means is equivalent to, which is 
not quite the same as identical to.

http://mathworld.wolfram.com/Equivalent.html



-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-25 Thread Chris Angelico
On Thu, Apr 26, 2012 at 3:27 AM, Steven D'Aprano
steve+comp.lang.pyt...@pearwood.info wrote:
 By the way, in mathematics, ≡ normally means is equivalent to, which is
 not quite the same as identical to.

That's perhaps because, in mathematics, nobody would even think of
asking if this 4 is the same as that 4. What sort of question is it?
Four is four! How could you tell one four from another? Mathematics is
not the same as programming, and the whole concept of objects in
memory simply isn't a mathematical one at all.

ChrisA
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-25 Thread Adam Skutt
On Apr 25, 10:38 am, Nobody nob...@nowhere.com wrote:
 On Mon, 23 Apr 2012 10:01:24 -0700, Paul Rubin wrote:
  I can't think of a single case where 'is' is ill-defined.

  If I can't predict the output of

      print (20+30 is 30+20)  # check whether addition is commutative print
      (20*30 is 30*20)  # check whether multiplication is commutative

  by just reading the language definition and the code, I'd have to say is
  is ill-defined.

 If anything is ill-defined, then it's + and *, i.e. it's unspecified
 whether the value which they return is a unique object or a reference to
 some other object.


Such a definition precludes meaningful operator overloading and is
highly problematic for floating-point numbers.  There's also no way to
enforce it, but I think you know that too. :)

Identity and equality are distinct concepts in programming languages.
There's nothing that can be done about that, and no particularly good
reason to force certain language behaviors because some programmers
have difficulty with the distinction.

Though, maybe it's better to use a different keyword than 'is' though,
due to the plain English
connotations of the term; I like 'sameobj' personally, for whatever
little it matters.  Really, I think taking away the 'is' operator
altogether is better, so the only way to test identity is:
id(x) == id(y)
Though I would prefer:
addr(x) == addr(y)
myself, again, for what little it matters.  The right thing to do when
confronted with this problem is teach the difference and move on.

As an aside, the whole problem with 'is' and literals is perhaps the
only really good argument for a 'new' keyword/operator like C++ and
Java have.  Then it's more explicit to the programmer that they've
created two objects (in this case, anyway).

 More accurately, the existence of is, is not and id cause many other
 constructs to have ill-defined behaviour.

  a is b is true iff 'a' and 'b' are the same object. Why should 'is'
  lie to the user?

  Whether a and b are the same object is implementation-dependent.

 And what's wrong with that? If you want a language which precisely
 specifies all observable behaviour, you're going to end up with a rather
 useless language. For a start, it can't have a time() function. For
 similar reasons, you can't have networking or any form of preemptive
 concurrency (which includes any form of inter-process communication on an
 OS which uses preemptive multi-tasking).

Fully specified does not mean fully deterministic. What makes a
specification of Any value in the range 0 through N less 'full' than
a specification of X or a constant?

Adam
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-25 Thread Terry Reedy

On 4/25/2012 4:49 PM, Adam Skutt wrote:


Identity and equality are distinct concepts in programming languages.
There's nothing that can be done about that, and no particularly good
reason to force certain language behaviors because some programmers
have difficulty with the distinction.

Though, maybe it's better to use a different keyword than 'is' though,
due to the plain English
connotations of the term; I like 'sameobj' personally, for whatever
little it matters.  Really, I think taking away the 'is' operator
altogether is better, so the only way to test identity is:
 id(x) == id(y)
Though I would prefer:
 addr(x) == addr(y)
myself, again, for what little it matters.


The fact that id(x) is machine_addr(x) in CPython is specific to 
CPython, not required by the language spec, and not true in 
implementations that move objects around when garbage collecting.


--
Terry Jan Reedy

--
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-25 Thread Steven D'Aprano
On Wed, 25 Apr 2012 13:49:24 -0700, Adam Skutt wrote:

 Though, maybe it's better to use a different keyword than 'is' though,
 due to the plain English
 connotations of the term; I like 'sameobj' personally, for whatever
 little it matters.  Really, I think taking away the 'is' operator
 altogether is better, so the only way to test identity is:
 id(x) == id(y)

Four reasons why that's a bad idea:

1) The is operator is fast, because it can be implemented directly by 
the interpreter as a simple pointer comparison (or equivalent). The id() 
idiom is slow, because it involves two global lookups and an equality 
comparison. Inside a tight loop, that can make a big difference in speed.

2) The is operator always has the exact same semantics and cannot be 
overridden. The id() function can be monkey-patched.

3) The is idiom semantics is direct: a is b directly tests the thing 
you want to test, namely whether a is b. The id() idiom is indirect: 
id(a) == id(b) only indirectly tests whether a is b.

4) The id() idiom already breaks if you replace names a, b with 
expressions:

 id([1,2]) == id([3,4])
True



 Though I would prefer:
 addr(x) == addr(y)

But that's absolutely wrong. id(x) returns an ID, not an address. It just 
happens that, as an accident of implementation, the CPython interpreter 
uses the object address as an ID, because objects can't move. That's not 
the case for all implementations. In Jython, objects can move and the 
address is not static, and so IDs are assigned on demand starting with 1:


steve@runes:~$ jython
Jython 2.5.1+ (Release_2_5_1, Aug 4 2010, 07:18:19)
[OpenJDK Client VM (Sun Microsystems Inc.)] on java1.6.0_18
Type help, copyright, credits or license for more information.
 id(42)
1
 id(Hello World!)
2
 id(None)
3


Other implementations may make other choices. I don't believe that the 
language even defines the id as a number, although I could be wrong about 
that.

Personally, I prefer the Jython approach, because it avoids those 
annoying questions like How do I dereference the address of an 
object? (answer: Python is not C, you can't do that), and IDs are 
globally unique and never reused for the lifetime of the process.


-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-25 Thread Roy Smith
In article 4f9833ff$0$29965$c3e8da3$54964...@news.astraweb.com,
 Steven D'Aprano steve+comp.lang.pyt...@pearwood.info wrote:

 On Wed, 25 Apr 2012 13:42:31 +0200, Thomas Rachel wrote:
 
  Two objects can be equal (=) without being identical (≡), but not the
  other way.
 
 
  x = float('nan')
  y = x
  x is y
 True
  x == y
 False

I love it.   Thanks for posting that.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-25 Thread Adam Skutt
On Apr 25, 8:01 pm, Steven D'Aprano steve
+comp.lang.pyt...@pearwood.info wrote:
 On Wed, 25 Apr 2012 13:49:24 -0700, Adam Skutt wrote:
  Though, maybe it's better to use a different keyword than 'is' though,
  due to the plain English
  connotations of the term; I like 'sameobj' personally, for whatever
  little it matters.  Really, I think taking away the 'is' operator
  altogether is better, so the only way to test identity is:
      id(x) == id(y)

 Four reasons why that's a bad idea:

 1) The is operator is fast, because it can be implemented directly by
 the interpreter as a simple pointer comparison (or equivalent). The id()
 idiom is slow, because it involves two global lookups and an equality
 comparison. Inside a tight loop, that can make a big difference in speed.

The runtime can optimize the two operations to be equivalent, since
they are logically equivalent operations.  If you removed 'is',
there's little reason to believe it would do otherwise.


 2) The is operator always has the exact same semantics and cannot be
 overridden. The id() function can be monkey-patched.


I can't see how that's useful at all.  Identity is a fundamental
property of an object; hence retrieval of it must be a language
operation.  The fact Python chooses to do otherwise is unfortunate,
but also irrelevant to my position.

 3) The is idiom semantics is direct: a is b directly tests the thing
 you want to test, namely whether a is b. The id() idiom is indirect:
 id(a) == id(b) only indirectly tests whether a is b.

The two expressions are logically equivalent, so I don't see how this
matters, nor how it is true.


 4) The id() idiom already breaks if you replace names a, b with
 expressions:

  id([1,2]) == id([3,4])

 True

It's not broken at all.  The lifetime of temporary objects is
intentionally undefined, and that's a /good/ thing.  What's
unfortunate is that CPython optimizes temporaries differently between
the two logically equivalent expressions.

As long as this holds:
 class A(object):
... def __del__(self):
...print Farewell to: %d % id(self)
...
 A() is A()
Farewell to: 4146953292
Farewell to: 4146953260
False
 id(A()) == id(A())
Farewell to: 4146953420
Farewell to: 4146953420
True

then there's nothing broken about the behavior of either expression.
I personally think logically equivalent expressions should give the
same results, but since both operations follow the rules of object
identity correctly, it's not the end of the world.  It's only
surprising to the programmer if:
1) They don't understand identity.
2) They don't understand what objects are and are not temporaries.

Code that relies on the identity of a temporary object is generally
incorrect.  This is why C++ explicitly forbids taking the address
(identity) of temporaries.  As such, the language behavior in your
case is inconsequential.  Making demons fly out of the programmer's
nose would be equally appropriate.

The other solution is to do what Java and C# do: banish id() entirely
and only provide 'is' (== in Java, Object.ReferenceEquals() in C#).
That seems just as fine, really,  Practically, it's also probably the
better solution for CPython, which is fine by me.  My preference for
keeping id() and removing 'is' probably comes from my background as a C
++ programmer, and I already said it matters very little.

 But that's absolutely wrong. id(x) returns an ID, not an address.
 It just
 happens that, as an accident of implementation, the CPython interpreter
 uses the object address as an ID, because objects can't move. That's not
 the case for all implementations. In Jython, objects can move and the
 address is not static, and so IDs are assigned on demand starting with 1:

 steve@runes:~$ jython
 Jython 2.5.1+ (Release_2_5_1, Aug 4 2010, 07:18:19)
 [OpenJDK Client VM (Sun Microsystems Inc.)] on java1.6.0_18
 Type help, copyright, credits or license for more information. 
 id(42)
 1
  id(Hello World!)
 2
  id(None)

 3


An address is an identifier: a number that I can use to access a
value[1].  I never said that id() must return an address the host CPU
understands (virtual, physical, or otherwise).  Most languages use
addresses that the host CPU cannot understand without assistance at
least sometimes, including C on some platforms.

 Other implementations may make other choices. I don't believe that the
 language even defines the id as a number, although I could be wrong about
 that.

http://docs.python.org/library/functions.html#id says it must be an
integer of some sort.  Even if it didn't say that, it hardly seems as
a practical imposition.


 Personally, I prefer the Jython approach, because it avoids those
 annoying questions like How do I dereference the address of an
 object? (answer: Python is not C, you can't do that),

The right way to solve that question isn't to fix the runtime, but to
teach people what pointer semantics actually mean, much like the
identity problem we're discussing now.

Adam

[1] I'd be 

Re: why () is () and [] is [] work in other way?

2012-04-25 Thread Chris Angelico
On Thu, Apr 26, 2012 at 1:50 PM, Adam Skutt ask...@gmail.com wrote:
 On Apr 25, 8:01 pm, Steven D'Aprano steve
 +comp.lang.pyt...@pearwood.info wrote:
 2) The is operator always has the exact same semantics and cannot be
 overridden. The id() function can be monkey-patched.

 I can't see how that's useful at all.  Identity is a fundamental
 property of an object; hence retrieval of it must be a language
 operation.
 ...
 The other solution is to do what Java and C# do: banish id() entirely
 and only provide 'is' (== in Java, Object.ReferenceEquals() in C#).

The 'is' operator is a language feature. The id() function is not.

ChrisA
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-25 Thread John Nagle

On 4/25/2012 5:01 PM, Steven D'Aprano wrote:

On Wed, 25 Apr 2012 13:49:24 -0700, Adam Skutt wrote:


Though, maybe it's better to use a different keyword than 'is' though,
due to the plain English
connotations of the term; I like 'sameobj' personally, for whatever
little it matters.  Really, I think taking away the 'is' operator
altogether is better, so the only way to test identity is:
 id(x) == id(y)


Four reasons why that's a bad idea:

1) The is operator is fast, because it can be implemented directly by
the interpreter as a simple pointer comparison (or equivalent).


   This assumes that everything is, internally, an object.  In CPython,
that's the case, because Python is a naive interpreter and everything,
including numbers, is boxed.  That's not true of PyPy or Shed Skin.
So does is have to force the creation of a temporary boxed object?

   The concept of object vs. the implementation of objects is
one reason you don't necessarily want to expose the implementation.

John Nagle
--
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-24 Thread rusi
On Apr 23, 9:34 am, Steven D'Aprano steve
+comp.lang.pyt...@pearwood.info wrote:

 is is never ill-defined. is always, without exception, returns True
 if the two operands are the same object, and False if they are not. This
 is literally the simplest operator in Python.

Circular definition: In case you did not notice, 'is' and 'are' are
(or is it is?) the same verb.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-24 Thread Thomas Rachel

Am 24.04.2012 08:02 schrieb rusi:

On Apr 23, 9:34 am, Steven D'Apranosteve
+comp.lang.pyt...@pearwood.info  wrote:


is is never ill-defined. is always, without exception, returns True
if the two operands are the same object, and False if they are not. This
is literally the simplest operator in Python.


Circular definition: In case you did not notice, 'is' and 'are' are
(or is it is?) the same verb.


Steven's definition tries not to define the verb is, but it defines 
the meanung of the *operator* 'is'.


He says that 'a is b' iff a and be are *the same objects*. We don't need 
to define the verb to be, but the target of the definition is the 
entity object and its identity.



Thomas
--
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-24 Thread Kiuhnm

On 4/24/2012 8:02, rusi wrote:

On Apr 23, 9:34 am, Steven D'Apranosteve
+comp.lang.pyt...@pearwood.info  wrote:


is is never ill-defined. is always, without exception, returns True
if the two operands are the same object, and False if they are not. This
is literally the simplest operator in Python.


Circular definition: In case you did not notice, 'is' and 'are' are
(or is it is?) the same verb.


Python is not English.
Double-quoted 'is' is a Python operator, while non-quoted 'is' and 'are' 
are forms of the English verb 'to be'. If you change the name of the 
operator or the language in which you define the operator, you'll 
realize that there's no real circularity in that definition.


Kiuhnm
--
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-24 Thread rusi
On Apr 24, 4:06 pm, Thomas Rachel nutznetz-0c1b6768-bfa9-48d5-
a470-7603bd3aa...@spamschutz.glglgl.de wrote:
 Am 24.04.2012 08:02 schrieb rusi:

  On Apr 23, 9:34 am, Steven D'Apranosteve
  +comp.lang.pyt...@pearwood.info  wrote:

  is is never ill-defined. is always, without exception, returns True
  if the two operands are the same object, and False if they are not. This
  is literally the simplest operator in Python.

  Circular definition: In case you did not notice, 'is' and 'are' are
  (or is it is?) the same verb.

 Steven's definition tries not to define the verb is, but it defines
 the meanung of the *operator* 'is'.

 He says that 'a is b' iff a and be are *the same objects*. We don't need
 to define the verb to be, but the target of the definition is the
 entity object and its identity.

Identity, sameness, equality and the verb to be are all about the same
concept(s) and their definitions are *intrinsically* circular; see
http://plato.stanford.edu/entries/identity/#2

And the seeming simplicity of the circular definitions hide the actual
complexity of 'to be'
for python:  http://docs.python.org/reference/expressions.html#id26
(footnote 7)
for math/philosophy: 
http://www.math.harvard.edu/~mazur/preprints/when_is_one.pdf
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-24 Thread Kiuhnm

On 4/24/2012 15:25, rusi wrote:

On Apr 24, 4:06 pm, Thomas Rachelnutznetz-0c1b6768-bfa9-48d5-
a470-7603bd3aa...@spamschutz.glglgl.de  wrote:

Am 24.04.2012 08:02 schrieb rusi:


On Apr 23, 9:34 am, Steven D'Apranosteve
+comp.lang.pyt...@pearwood.infowrote:



is is never ill-defined. is always, without exception, returns True
if the two operands are the same object, and False if they are not. This
is literally the simplest operator in Python.



Circular definition: In case you did not notice, 'is' and 'are' are
(or is it is?) the same verb.


Steven's definition tries not to define the verb is, but it defines
the meanung of the *operator* 'is'.

He says that 'a is b' iff a and be are *the same objects*. We don't need
to define the verb to be, but the target of the definition is the
entity object and its identity.


Identity, sameness, equality and the verb to be are all about the same
concept(s) and their definitions are *intrinsically* circular; see
http://plato.stanford.edu/entries/identity/#2

And the seeming simplicity of the circular definitions hide the actual
complexity of 'to be'
for python:  http://docs.python.org/reference/expressions.html#id26
(footnote 7)
for math/philosophy: 
http://www.math.harvard.edu/~mazur/preprints/when_is_one.pdf


What you say is true in general, but not from an operational point of 
view, especially if we restrict the set of objects whose sameness or 
identity we want to check:

Let O be a set of tuples (id, data) where
  {(id, data1), (id, data2)} subset O = data1 = data2
Def. (id1, data1) and (id2, data2) in O are /the same/ iff id1 = id2.
Now, it's easy to find a bijection between O and the set of Python's 
objects which are in memory at any single point in time.


Anyway, you're being unnecessarily pedantic.

Kiuhnm
--
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-23 Thread Alexander Blinne
Am 21.04.2012 14:51, schrieb gst:
 Hi,
 
 I played (python3.2) a bit on that and :
 
 case 1) Ok to me (right hand side is a tuple, whose elements are evaluated 
 one per one and have same effect as your explanation (first [] is destroyed 
 right before the second one is created) :
 
 x, y = id([]), id([])
 x == y
 True

 
 
 case 2) also ok to me:
 
 x = id([]) ; y = id([])
 x == y
 True

 
 
 case 3) NOT ok to me :
 
 x = id([])
 y = id([])
 x == y
 False

 
 
 case 4) ok to me :
 
 def f():
   x = id([])
   y = id([])
   return x == y
 
 f()
 True

 
 
 I'd have thought that cases 23 are totally, while 34 nearly, syntactically 
 equal and that case 3 is the incorrect result..
 
 how would you explain case 3 vs cases 2 and 4 ??

It is simply not defined if, after creation and destruction of an empty
list with some id, a newly created empty list should carry the same id
or not. In cases 1,2 and 4 it happens, but in case 3 it doesn't. This is
simply an implementation detail and neither behaviour is right or wrong.

Alex
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-23 Thread John Nagle

On 4/22/2012 9:34 PM, Steven D'Aprano wrote:

On Sun, 22 Apr 2012 12:43:36 -0700, John Nagle wrote:


On 4/20/2012 9:34 PM, john.tant...@gmail.com wrote:

On Friday, April 20, 2012 12:34:46 PM UTC-7, Rotwang wrote:


I believe it says somewhere in the Python docs that it's undefined and
implementation-dependent whether two identical expressions have the
same identity when the result of each is immutable


 Bad design.  Where is is ill-defined, it should raise ValueError.


is is never ill-defined. is always, without exception, returns True
if the two operands are the same object, and False if they are not. This
is literally the simplest operator in Python.

John, you've been using Python for long enough that you should know this.
I can only guess that you are trolling, although I can't imagine why.


   Because the language definition should not be what CPython does.
As PyPy advances, we need to move beyond that.

John Nagle
--
http://mail.python.org/mailman/listinfo/python-list


Re: why () is () and [] is [] work in other way?

2012-04-23 Thread Kiuhnm

On 4/22/2012 21:43, John Nagle wrote:

On 4/20/2012 9:34 PM, john.tant...@gmail.com wrote:

On Friday, April 20, 2012 12:34:46 PM UTC-7, Rotwang wrote:


I believe it says somewhere in the Python docs that it's undefined and
implementation-dependent whether two identical expressions have the same
identity when the result of each is immutable


Bad design. Where is is ill-defined, it should raise ValueError.

A worse example, one which is very implementation-dependent:

http://stackoverflow.com/questions/306313/python-is-operator-behaves-unexpectedly-with-integers


  a = 256
  b = 256
  a is b
True # this is an expected result
  a = 257
  b = 257
  a is b
False

Operator is should be be an error between immutables
unless one is a built-in constant.

[...]

I can't think of a single case where 'is' is ill-defined.
You're blaming 'is' for revealing what's really going on. 'is' is /not/ 
implementation-dependent. It's /what's going on/ that's 
implementation-dependent.
a is b is true iff 'a' and 'b' are the same object. Why should 'is' 
lie to the user?
It does exactly what it says it does: it tells the user whether two 
objects are the same.
In C++, for greater efficiency, two objects are compared for equality by 
first checking their addresses and then their contents. 'is' would be 
perfect for that.


What I don't like is 'isinstance'. I'd prefer an infix operator 'isa' or 
'is_a'.


Kiuhnm
--
http://mail.python.org/mailman/listinfo/python-list


  1   2   >