Re: [Python-Dev] PEP 246, redux

2005-01-13 Thread Alex Martelli
On 2005 Jan 14, at 04:08, David Ascher wrote:
Alex Martelli wrote:
Yes, there is (lato sensu) "non-determinism" involved, just like in, 
say:
for k in d:
print k
Wow, it took more than the average amount of googling to figure out 
that lato sensu means "broadly speaking",
Ooops -- sorry; I wouldn't have imagined Brazilian hits would swamp the 
google hits to that extent, mostly qualifying post-grad courses and the 
like... seems to be an idiom there for that.

 and occurs as "sensu lato" with a 1:2 ratio.
In Latin as she was spoken word order is very free, but the issue here 
is that _in taxonomy specifically_ (which was the way I intended the 
form!) the "sensu lato" order vastly predominates.  Very exhaustive 
discussion of this word order choice in taxonomy at 
, btw (mostly about 
"sensu scricto", the antonym).

I learned something today! ;-)
Me too: about Brazilian idiom, and about preferred word-order use in 
Aquinas and Bonaventura.

Also, a reflection: taxonomy, the classification of things (living 
beings, rocks, legal precedents, ...) into categories, is a discipline 
with many, many centuries of experience behind it.  I think it is 
telling that taxonomists found out they require _two_ kinds of 
``inheritance'' to do their job (no doubt there are all kind of 
_nuances_, but specialized technical wording exists for two kinds: 
"strict-sense" and "broad-sense")... they need to be able to assert 
that "A is a B _broadly speaking_" (or specifically "_strictly 
speaking_") so often that they evolved specific terminology.  Let's 
hope it doesn't take OOP many centuries to accept that both "stricto 
sensu inheritance" (Liskovianly-correct) AND "lato sensu inheritance" 
are needed to do _our_ jobs!-)

Alex
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246: lossless and stateless

2005-01-13 Thread Phillip J. Eby
At 10:20 PM 1/13/05 -0800, Guido van Rossum wrote:
[Guido]
> >This may solve the curernt raging argument, but IMO it would make the
> >optional signature declaration less useful, because there's no way to
> >accept other kind of adapters. I'd be happier if def f(X: Y) implied X
> >= adapt(X, Y).
[Phillip]
> The problem is that type declarations really want more guarantees about
> object identity and state than an unrestricted adapt() can provide,
I'm not so sure. When I hear "guarantee" I think of compile-time
checking, and I though that was a no-no.
No, it's not compile-time based, it's totally at runtime.  I mean that if 
the implementation of 'adapt()' *generates* the adapter (cached of course 
for source/target type pairs), it can trivially guarantee that adapter's 
stateless.  Quick demo (strawman syntax) of declaring adapters...

First, a type declaring that its 'read' method has the semantics of 
'file.read':

class SomeKindOfStream:
def read(self, byteCount) like file.read:
...
Second, third-party code adapting a string iterator to a readable file:
def read(self, byteCount) like file.read for type(iter("")):
# self is a string iterator here, implement read()
# in terms of its .next()
And third, some standalone code implementing an "abstract" dict.update 
method for any source object that supports a method that's "like" 
dict.__setitem__:

def update_anything(self:dict, other:dict) like dict.update for object:
for k,v in other.items(): self[k] = v
Each of these examples registers the function as an implementation of the 
"file.read" operation for the appropriate type.  When you want to build an 
adapter from SomeKindOfStream or from a string iterator to the "file" type, 
you just access the 'file' type's descriptors, and look up the 
implementation registered for that descriptor for the source type 
(SomeKindOfStream or string-iter).  If there is no implementation 
registered for a particular descriptor of 'file', you leave the 
corresponding attribute off of the adapter class, resulting in a class 
representing the subset of 'file' that can be obtained for the source class.

The result is that you generate a simple adapter class whose only state is 
a read-only slot pointing to the adapted object, and descriptors that bind 
the registered implementations to that object.  That is, the descriptor 
returns a bound instancemethod with an im_self of the original object, not 
the adapter.  (Thus the implementation never even gets a reference to the 
adapter, unless 'self' in the method is declared of the same type as the 
adapter, which would be the case for an abstract method like 'readline()' 
being implemented in terms of 'read'.)

Anyway, it's therefore trivially "guaranteed" to be stateless (in the same 
way that an 'int' is "guaranteed" to be immutable), and the implementation 
is also "guaranteed" to be able to always get back the "original" object.

Defining adaptation in terms of adapting operations also solves another 
common problem with interface mechanisms for Python: the dreaded "mapping 
interface" and "file-like object" problem.  Really, being able to 
*incompletely* implement an interface is often quite useful in practice, so 
this "monkey see, monkey do" typing ditches the whole concept of a complete 
interface in favor of "explicit duck typing".  You're just declaring "how 
can X act 'like' a duck" -- emulating behaviors of another type rather than 
converting structure.


Are there real-life uses of stateful adapters that would be thrown out
by this requirement?
Think about this: if an adapter has independent state, that means it has a 
particular scope of applicability.  You're going to keep the adapter and 
then throw it away at some point, like you do with an iterator.  If it has 
no state, or only state that lives in the original object (by tacking 
annotations onto it), then it has a common lifetime with the original object.

If it has state, then, you have to explicitly manage that state; you can't 
do that if the only way to create an adapter is to pass it into some other 
function that does the adapting, unless all it's going to do is return the 
adapter back to you!

Thus, stateful adapters *must* be explicitly adapted by the code that needs 
to manage the state.

This is why I say that PEP 246 is fine, but type declarations need a more 
restrictive version.  PEP 246 provides a nice way to *find* stateful 
adapters, it just shouldn't do it for function arguments.


> Even if you're *very* careful, your seemingly safe setup can be blown just
> by one routine passing its argument to another routine, possibly causing an
> adapter to be adapted.  This is a serious pitfall because today when you
> 'adapt' you can also access the "original" object -- you have to first
> *have* it, in order to *adapt* it.
How often is this used, though? I can imagine all sorts of problems if
you mix access to the original object and to the adap

Re: [Python-Dev] PEP 246: lossless and stateless

2005-01-13 Thread Guido van Rossum
[Guido]
> >This may solve the curernt raging argument, but IMO it would make the
> >optional signature declaration less useful, because there's no way to
> >accept other kind of adapters. I'd be happier if def f(X: Y) implied X
> >= adapt(X, Y).

[Phillip]
> The problem is that type declarations really want more guarantees about
> object identity and state than an unrestricted adapt() can provide,

I'm not so sure. When I hear "guarantee" I think of compile-time
checking, and I though that was a no-no.

> including sane behavior when objects are passed into the same or different
> functions repeatedly.  See this short post by Paul Moore:
> 
> http://mail.python.org/pipermail/python-dev/2005-January/051020.html

Hm. Maybe that post points out that adapters that add state are bad,
period. I have to say that the example of adapting a string to a file
using StringIO() is questionable. Another possible adaptation from a
string to a file would be open(), and in fact I know a couple of
existing APIs in the Python core (and elsewhere) that take either a
string or a file, and interpret the string as a filename. Operations
that are customarily done with string data or a file typically use two
different different function/method names, for example pickle.load and
pickle.loads.

But I'd be just as happy if an API taking either a string or a file
(stream) should be declared as taking the union of IString and
IStream; adapting to a union isn't that hard to define (I think
someone gave an example somewhere already).

OK, so what am I saying here (rambling really): my gut tells me that I
still like argument declarations to imply adapt(), but that adapters
should be written to be stateless. (I'm not so sure I care about
lossless.)

Are there real-life uses of stateful adapters that would be thrown out
by this requirement?

> Even if you're *very* careful, your seemingly safe setup can be blown just
> by one routine passing its argument to another routine, possibly causing an
> adapter to be adapted.  This is a serious pitfall because today when you
> 'adapt' you can also access the "original" object -- you have to first
> *have* it, in order to *adapt* it.

How often is this used, though? I can imagine all sorts of problems if
you mix access to the original object and to the adapter.

> But type declarations using adapt()
> prevents you from ever *seeing* the original object within a function.  So,
> it's *really* unsafe in a way that explicitly calling 'adapt()' is
> not.  You might be passing an adapter to another function, and then that
> function's signature might adapt it again, or perhaps just fail because you
> have to adapt from the original object.

Real-life example, please?

I can see plenty of cases where this could happen with explicit
adaptation too, for example f1 takes an argument and adapts it, then
calls f2 with the adapted value, which calls f3, which adapts it to
something else. Where is f3 going to get the original object?

I wonder if a number of these cases are isomorphic to the hypothetical
adaptation from a float to an int using the int() constructor -- no
matter how we end up defining adaptation, that should *not* happen,
and neither should adaptation from numbers to strings using str(), or
from strings to numbers using int() or float().

But the solution IMO is not to weigh down adapt(), but to agree, as a
user community, not to create such "bad" adapters, period. OTOH there
may be specific cases where the conventions of a particular
application or domain make stateful or otherwise naughty adapters
useful, and everybody understands the consequences and limitations.
Sort of the way that NumPy defines slices as views on the original
data, even though lists define slices as copies of the original data;
you have to know what you are doing with the NumPy slices but the
NumPy users don't seem to have a problem with that. (I think.)

> Clark's proposal isn't going to solve this issue for PEP 246, alas.  In
> order to guarantee safety of adaptive type declarations, the implementation
> strategy *must* be able to guarantee that 1) adapters do not have state of
> their own, and 2) adapting an already-adapted object re-adapts the original
> rather than creating a new adapter.  This is what the monkey-typing PEP and
> prototype implementation are intended to address.

Guarantees again. I think it's hard to provide these, and it feels
unpythonic. (2) feels weird too -- almost as if it were to require
that float(int(3.14)) should return 3.14. That ain't gonna happen.

> (This doesn't mean that explicit adapt() still isn't a useful thing, it
> just means that using it for type declarations is a bad idea in ways that
> we didn't realize until after the "great debate".)

Or maybe we shouldn't try to guarantee so much and instead define
simple, "Pythonic" semantics and live with the warts, just as we do
with mutable defaults and a whole slew of other cases where Python
makes a choice rooted in what is easy to expl

Re: [Python-Dev] PEP 246: lossless and stateless

2005-01-13 Thread Phillip J. Eby
At 12:00 AM 1/14/05 -0500, Clark C. Evans wrote:
On Thu, Jan 13, 2005 at 11:50:37PM -0500, Phillip J. Eby wrote:
| 'lossless' isn't really a good term for non-noisy.  The key is that a
| "noisy" adapter is one that alters the precision of the information it
| provides, by either claiming greater precision than is actually present,
| or by losing precision that was present in the meaning of the data.
Noisy doesn't cut it -- my PC fan is noisy.  In computer science,
noisy usually refers to a flag on an object that tells it to spew
debug output...
Come up with a better name, then.  Precision-munging?  :)

| Anyway, for type declaration, IMO statelessness is the key criterion.
| Type declaration "wants" to have true adapters (which can maintain object
| identity), not decorators (which are distinct objects from the things
| they add functionality to).
Stateful adapters are very useful, and the value of PEP 246 is
significantly reduced without alowing them.
Absolutely.  But that doesn't mean type declarations are the right choice 
for PEP 246.  Look at this code:

def foo(self, bar:Baz):
bar.whack(self)
self.spam.fling(bar)
Does this code produce transitive adaptation (i.e. adapt an 
adapter)?  Can't tell?  Me neither.  :)  It depends on what type 
spam.fling() declares its parameter to be, and whether the caller of foo() 
passed in an object that needed an adapter to Baz.

The problem here is that *all* of the arguments you and Alex and others 
raised in the last few days against unconstrained transitive adaptation 
apply in spades to type declarations.  My argument was that if 
well-designed and properly used, transitivity could be quite safe, but even 
I agreed that uncontrolled semi-random adapter composition was madness.

Unfortunately, having type declarations do adapt() introduces the potential 
for precisely this sort of uncontrolled semi-random adapter madness in 
seemingly harmless code.

Now compare to *this* code:
def foo(self, bar):
adapt(bar,Baz).whack(self)
self.spam.fling(bar)
It's obvious that the above does not introduce a transitive adaptation; at 
least if it was passed an "original" object, then it will pass on that 
original object to spam.fling().

So, explicit use of PEP 246 doesn't introduce this problem, but type 
declarations do.  With type declarations you can never even *know* if you 
have the "original object" or not, let alone get it if you don't have it.

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246: lossless and stateless

2005-01-13 Thread Phillip J. Eby
At 05:52 PM 1/13/05 -0800, Guido van Rossum wrote:
This may solve the curernt raging argument, but IMO it would make the
optional signature declaration less useful, because there's no way to
accept other kind of adapters. I'd be happier if def f(X: Y) implied X
= adapt(X, Y).
The problem is that type declarations really want more guarantees about 
object identity and state than an unrestricted adapt() can provide, 
including sane behavior when objects are passed into the same or different 
functions repeatedly.  See this short post by Paul Moore:

http://mail.python.org/pipermail/python-dev/2005-January/051020.html
It presents some simple examples that show how non-deterministic adaptation 
can be in the presence of stateful adapters created "implicitly" by type 
declaration.  It suggests that just avoiding transitive interface adapters 
may not be sufficient to escape C++ish pitfalls.

Even if you're *very* careful, your seemingly safe setup can be blown just 
by one routine passing its argument to another routine, possibly causing an 
adapter to be adapted.  This is a serious pitfall because today when you 
'adapt' you can also access the "original" object -- you have to first 
*have* it, in order to *adapt* it.  But type declarations using adapt() 
prevents you from ever *seeing* the original object within a function.  So, 
it's *really* unsafe in a way that explicitly calling 'adapt()' is 
not.  You might be passing an adapter to another function, and then that 
function's signature might adapt it again, or perhaps just fail because you 
have to adapt from the original object.

Clark's proposal isn't going to solve this issue for PEP 246, alas.  In 
order to guarantee safety of adaptive type declarations, the implementation 
strategy *must* be able to guarantee that 1) adapters do not have state of 
their own, and 2) adapting an already-adapted object re-adapts the original 
rather than creating a new adapter.  This is what the monkey-typing PEP and 
prototype implementation are intended to address.

(This doesn't mean that explicit adapt() still isn't a useful thing, it 
just means that using it for type declarations is a bad idea in ways that 
we didn't realize until after the "great debate".)

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246: lossless and stateless

2005-01-13 Thread Clark C. Evans
On Thu, Jan 13, 2005 at 11:50:37PM -0500, Phillip J. Eby wrote:
| 'lossless' isn't really a good term for non-noisy.  The key is that a 
| "noisy" adapter is one that alters the precision of the information it 
| provides, by either claiming greater precision than is actually present, 
| or by losing precision that was present in the meaning of the data.  

Noisy doesn't cut it -- my PC fan is noisy.  In computer science,
noisy usually refers to a flag on an object that tells it to spew
debug output...


| 'statelessness', on the other hand, is primarily useful as a guide to 
| whether what you're building is really an "as-a" adapter.  If an adapter 
| has per-adapter state, it's an extremely good indication that it's 
| actually a *decorator* (in GoF pattern terminology).

GoF is very nice, but I'm using a much broader definition of 'adapt':

   To make suitable to or fit for a specific use or situation
   
By this definition, decorators, facade are both kinds of adapters.

| Anyway, for type declaration, IMO statelessness is the key criterion.  
| Type declaration "wants" to have true adapters (which can maintain object 
| identity), not decorators (which are distinct objects from the things 
| they add functionality to).

Stateful adapters are very useful, and the value of PEP 246 is 
significantly reduced without alowing them.

| Unfortunately, in practice this will just lead to people ignoring the 
| arguments, because 1) it's easier and 2) it will make their code work 
| with type declarations!  So, it won't actually produce any useful effect.

Hmm.

Best,

Clark
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246: lossless and stateless

2005-01-13 Thread Phillip J. Eby
At 08:03 PM 1/13/05 -0500, Clark C. Evans wrote:
Ok.  I think we have identified two sorts of restrictions on the
sorts of adaptations one may want to have:
  `stateless'  the adaptation may only provide a result which
   does not maintain its own state
  `lossless'   the adaptation preserves all information available
   in the original object, it may not discard state
'lossless' isn't really a good term for non-noisy.  The key is that a 
"noisy" adapter is one that alters the precision of the information it 
provides, by either claiming greater precision than is actually present, or 
by losing precision that was present in the meaning of the data.  (I.e., 
truncating 12.3 to 12 loses precision, but dropping the middle name field 
of a name doesn't because the first and last name are independent from the 
middle name).

Anyway, being non-noisy is only a prerequisite for interface-to-interface 
adapters, because they're claiming to be suitable for all possible 
implementations of the source interface.

'statelessness', on the other hand, is primarily useful as a guide to 
whether what you're building is really an "as-a" adapter.  If an adapter 
has per-adapter state, it's an extremely good indication that it's actually 
a *decorator* (in GoF pattern terminology).

In GoF, an Adapter simply converts one interface to another, it doesn't 
implement new functionality.  A decorator, on the other hand, is used to 
"add responsibilities to individual objects dynamically and transparently, 
that is, without affecting other objects."

In fact, as far as I can tell from the GoF book, you can't *have* multiple 
adapter instances for a given object in their definition of the "adapter 
pattern".  IOW, there's no per-adapter state, and their examples never 
suggest the idea that the adapter pattern is intended to add any 
per-adaptee state, either.

So, by their terminology, PEP 246 is a mechanism for dynamically selecting 
and obtaining *decorators*, not adapters.  As if people weren't already 
confused enough about decorators.  :)

Anyway, for type declaration, IMO statelessness is the key criterion.  Type 
declaration "wants" to have true adapters (which can maintain object 
identity), not decorators (which are distinct objects from the things they 
add functionality to).


In other words, while calling adapt directly would allow for any adapter;
using the 'Static Typing' short-cut one would be asking for adapters
which are both stateless and lossless.  Since __conform__ and __adapt__
would sprout two new arguments, it would make those writing adapters
think a bit more about the kind of adapter that they are providing.
Unfortunately, in practice this will just lead to people ignoring the 
arguments, because 1) it's easier and 2) it will make their code work with 
type declarations!  So, it won't actually produce any useful effect.

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] redux: fractional seconds in strptime

2005-01-13 Thread Brett C.
Skip Montanaro wrote:
A couple months ago I proposed (maybe in a SF bug report)
http://www.python.org/sf/1006786
 that
time.strptime() grow some way to parse time strings containing fractional
seconds based on my experience with the logging module.  I've hit that
stumbling block again, this time in parsing files with timestamps that were
generated using datetime.time objects.  I hacked around it again (in
miserable fashion), but I really think this shortcoming should be addressed.
A couple possibilities come to mind:
1. Extend the %S format token to accept simple decimals that match
   the re pattern "[0-9]+(?:\.[0-9]+)".
2. Add a new token that accepts decimals as above to avoid overloading
   the meaning of %S.
3. Add a token that matches integers corresponding to fractional parts.
   The Perl DateTime module uses %N to match nanoseconds (wanna bet that
   was added by a physicist?).  Arbitrary other units can be specified
   by sticking a number between the "%" and the "N".  I didn't see an
   example, but I presume "%6N" would match integers that are
   interpreted as microseconds.
The problem I have always had with this proposal is that the value is 
worthless, time tuples do not have a slot for fractional seconds.  Yes, it 
could possibly be changed to return a float for seconds, but that could 
possibly break things.

My vote is that if something is added it be like %N but without the optional 
optional digit count.  This allows any separator to be used while still 
consuming the digits.  It also doesn't suddenly add optional args which are not 
supported for any other directive.

-Brett
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] redux: fractional seconds in strptime

2005-01-13 Thread Skip Montanaro
A couple months ago I proposed (maybe in a SF bug report) that
time.strptime() grow some way to parse time strings containing fractional
seconds based on my experience with the logging module.  I've hit that
stumbling block again, this time in parsing files with timestamps that were
generated using datetime.time objects.  I hacked around it again (in
miserable fashion), but I really think this shortcoming should be addressed.

A couple possibilities come to mind:

1. Extend the %S format token to accept simple decimals that match
   the re pattern "[0-9]+(?:\.[0-9]+)".

2. Add a new token that accepts decimals as above to avoid overloading
   the meaning of %S.

3. Add a token that matches integers corresponding to fractional parts.
   The Perl DateTime module uses %N to match nanoseconds (wanna bet that
   was added by a physicist?).  Arbitrary other units can be specified
   by sticking a number between the "%" and the "N".  I didn't see an
   example, but I presume "%6N" would match integers that are
   interpreted as microseconds.

The advantage of the third choice is that you can use anything as the
"decimal" point.  The logging module separates seconds from their fractional
part with a comma for some reason.  (I live in the USofA where decimal
points are usually represented by a period.  I would be in favor of
replacing the comma with a locale-specific decimal point in a future version
of the logging module.)  I'm not sure I like the optional exponent thing in
Perl's DateTime module but it does make it easy to interpret integers
representing fractions of a second when they occur without a decimal point
to tell you where it is.

I'm open to suggestions and will be happy to implement whatever is agreed
to.


Skip
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246, redux

2005-01-13 Thread David Ascher
Alex Martelli wrote:
Yes, there is (lato sensu) "non-determinism" involved, just like in, say:
for k in d:
print k
Wow, it took more than the average amount of googling to figure out that 
lato sensu means "broadly speaking", and occurs as "sensu lato" with a 
1:2 ratio.

I learned something today! ;-)
--david
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246, redux

2005-01-13 Thread James Y Knight
On Jan 13, 2005, at 12:46 PM, Clark C. Evans wrote:
My current suggestion to make 'transitive adaption' easy for a
application builder (one putting togeher components) has a few
small parts:
  - If an adaptation is not found, raise an error, but list in
the error message two additional things: (a) what possible
adaptation paths exist, and (b) how to register one of
these paths in their module.
  - A simple method to register an adaption path, the error message
above can even give the exact line needed,
   adapt.registerPath(from=A,to=C,via=B)
I'd just like to note that this won't solve my use case for transitive 
adaptation. To keep backwards compatibility, I can't depend on the 
application developer to register an adapter path from A through 
IResource to INewResource. Trying to adapt A to INewResource needs to 
just work. I can't register the path either, because I (the framework 
author) don't know anything about A.

A solution that would work is if I have to explicitly declare the 
adapter from IResource to INewResource as 'safe', as long as I don't 
also have to declare the adapter from A to IResource as 'safe'. (That 
is, I suppose -- in a transitive adapter chain, all except one adapter 
in the chain would have to be declared 'safe').

I don't know whether or not it's worthwhile to have this encoded in the 
framework, as it is clearly possible to do it on my own in any case. 
I'll leave that for others to debate. :)

James
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246: lossless and stateless

2005-01-13 Thread Clark C. Evans
On Thu, Jan 13, 2005 at 08:08:43PM -0500, Bob Ippolito wrote:
| >Ok.  I think we have identified two sorts of restrictions on the
| >sorts of adaptations one may want to have:
| >
| >  `stateless'  the adaptation may only provide a result which
| >   does not maintain its own state
| >
| >  `lossless'   the adaptation preserves all information available
| >   in the original object, it may not discard state
| >
| >If we determined that these were the 'big-ones', we could possibly
| >allow for the signature of the adapt request to be parameterized with
| >these two designations, with the default to accept any sort of adapter:
| >
| >   adapt(object, protocol, alternative = None,
| > stateless = False, lossless = False)
| >
| >Then, Guido's 'Optional Static Typing',
| >
| > def f(X: Y):
| > pass
| >
| >   would be equivalent to
| >
| >  def f(X):
| >  X = adapt(X,Y, stateless = True, lossless = True)
..
| 
| In some cases, such as when you plan to consume the whole thing in one 
| function call, you wouldn't care so much if it's stateless.

etrepum,
   True False

  statelessadapter may not add  adapter may have its
   state beyond that alreadyown state, if it wishes
   provided by the object   but additional state is
not required


  lossless adapter must preserve andadapter may discard 
   give all information which   information if it wishes
   the underlying object has


So, in this case, if your consumer doesn't care if the adapter is
stateless or not, just call adapt(), which defaults to the case
that you wish.

Is this a better explanation?  Or is this whole idea too convoluted?

Best,

Clark
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


RE: [Python-Dev] PEP 246: lossless and stateless

2005-01-13 Thread Raymond Hettinger
> Ok.  I think we have identified two sorts of restrictions on the
> sorts of adaptations one may want to have:
> 
>   `stateless'  the adaptation may only provide a result which
>does not maintain its own state
> 
>   `lossless'   the adaptation preserves all information available
>in the original object, it may not discard state

+1 on having a provision for adapters to provide some meta-information
about themselves.  With these two key properties identified at the
outset, adapt calls can be made a bit more intelligent (or at least less
prone to weirdness).

There is some merit to establishing these properties right away rather
than trying to retrofit adapters after they've been in the wild for a
while.



 
> Since __conform__ and __adapt__
> would sprout two new arguments, it would make those writing adapters
> think a bit more about the kind of adapter that they are providing.

Using optional arguments may not be the most elegant or extensible
approach.  Perhaps a registry table or adapter attributes would fare
better.



Raymond Hettinger

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246: lossless and stateless

2005-01-13 Thread Guido van Rossum
> Then, Guido's 'Optional Static Typing',
> 
>  def f(X: Y):
>  pass
> 
>would be equivalent to
> 
>   def f(X):
>   X = adapt(Y, True, True)
> 
> In other words, while calling adapt directly would allow for any adapter;
> using the 'Static Typing' short-cut one would be asking for adapters
> which are both stateless and lossless.  Since __conform__ and __adapt__
> would sprout two new arguments, it would make those writing adapters
> think a bit more about the kind of adapter that they are providing.

This may solve the curernt raging argument, but IMO it would make the
optional signature declaration less useful, because there's no way to
accept other kind of adapters. I'd be happier if def f(X: Y) implied X
= adapt(X, Y).

-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246: lossless and stateless

2005-01-13 Thread Bob Ippolito
On Jan 13, 2005, at 20:03, Clark C. Evans wrote:
Ok.  I think we have identified two sorts of restrictions on the
sorts of adaptations one may want to have:
  `stateless'  the adaptation may only provide a result which
   does not maintain its own state
  `lossless'   the adaptation preserves all information available
   in the original object, it may not discard state
If we determined that these were the 'big-ones', we could possibly
allow for the signature of the adapt request to be parameterized with
these two designations, with the default to accept any sort of adapter:
   adapt(object, protocol, alternative = None,
 stateless = False, lossless = False)
   __conform__(self, protocol, stateless, lossless)
   __adapt__(self, object, stateless, lossless)
Then, Guido's 'Optional Static Typing',
 def f(X: Y):
 pass
   would be equivalent to
  def f(X):
  X = adapt(Y, True, True)
In other words, while calling adapt directly would allow for any 
adapter;
using the 'Static Typing' short-cut one would be asking for adapters
which are both stateless and lossless.  Since __conform__ and __adapt__
would sprout two new arguments, it would make those writing adapters
think a bit more about the kind of adapter that they are providing.

Furthermore, perhaps composite adapters can be automatically generated
from 'transitive' adapters (that is, those which are both stateless
and lossless).  But adaptations which were not stateless and lossless
would not be used (by default) in an automatic adapter construction.
Your thoughts?
In some cases, such as when you plan to consume the whole thing in one 
function call, you wouldn't care so much if it's stateless.

-bob
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] PEP 246: lossless and stateless

2005-01-13 Thread Clark C. Evans
Ok.  I think we have identified two sorts of restrictions on the
sorts of adaptations one may want to have:

  `stateless'  the adaptation may only provide a result which
   does not maintain its own state
   
  `lossless'   the adaptation preserves all information available
   in the original object, it may not discard state

If we determined that these were the 'big-ones', we could possibly
allow for the signature of the adapt request to be parameterized with 
these two designations, with the default to accept any sort of adapter:

   adapt(object, protocol, alternative = None, 
 stateless = False, lossless = False)

   __conform__(self, protocol, stateless, lossless)

   __adapt__(self, object, stateless, lossless)

Then, Guido's 'Optional Static Typing',

 def f(X: Y):
 pass

   would be equivalent to

  def f(X):
  X = adapt(Y, True, True)

In other words, while calling adapt directly would allow for any adapter; 
using the 'Static Typing' short-cut one would be asking for adapters
which are both stateless and lossless.  Since __conform__ and __adapt__
would sprout two new arguments, it would make those writing adapters 
think a bit more about the kind of adapter that they are providing.

Furthermore, perhaps composite adapters can be automatically generated
from 'transitive' adapters (that is, those which are both stateless
and lossless).  But adaptations which were not stateless and lossless
would not be used (by default) in an automatic adapter construction.

Your thoughts?

Clark

-- 
Clark C. Evans  Prometheus Research, LLC.
http://www.prometheusresearch.com/
o   office: +1.203.777.2550 
  ~/ ,  mobile: +1.203.444.0557 
 //
((   Prometheus Research: Transforming Data Into Knowledge
 \\  ,
   \/- Research Exchange Database
   /\- Survey & Assessment Technologies
   ` \   - Software Tools for Researchers
~ *
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: getting special from type, not instance (was Re: [Python-Dev] copy confusion)

2005-01-13 Thread Alex Martelli
On 2005 Jan 14, at 00:11, Guido van Rossum wrote:
Let's do override descriptors.
A Pronouncement!!!
And please, someone fix copy.py in 2.3 and 2.4.
Sure -- what way, though?  The way I proposed in my last post about 
it?
This would do it, right? (From your first post in this conversation
according to gmail:)
Armin's fix was to change:
conform = getattr(type(obj), '__conform__', None)
into:
for basecls in type(obj).__mro__:
if '__conform__' in basecls.__dict__:
conform = basecls.__dict__['__conform__']
break
else:
# not found
Yes, the code could be expanded inline each time it's needed (for 
__copy__, __getstate__, and all other special methods copy.py needs to 
get-from-the-type).  It does seem better to write it once as a private 
function of copy.py, though.

Plus, to fix the effbot's bug, we need to have in function copy() a 
test about object type that currently is in deepcopy() [[for the 
commented purpose of fixing a problem with Boost's old version -- but 
it works to make deepcopy work in the effbot's case too]] but not in 
copy().  Lastly, the tests should also be enriched to make sure they 
catch the bug (no doc change needed, it seems to me).

I can do it this weekend if the general approach is OK, since Clark has 
kindly agreed to do the next rewrite of PEP 246;-).

Alex
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: getting special from type, not instance (was Re: [Python-Dev] copy confusion)

2005-01-13 Thread Guido van Rossum
> > Let's do override descriptors.
> 
> A Pronouncement!!!
> 
> > And please, someone fix copy.py in 2.3 and 2.4.
> 
> Sure -- what way, though?  The way I proposed in my last post about it?

This would do it, right? (From your first post in this conversation
according to gmail:)

> Armin's fix was to change:
>
> conform = getattr(type(obj), '__conform__', None)
>
> into:
>
> for basecls in type(obj).__mro__:
> if '__conform__' in basecls.__dict__:
> conform = basecls.__dict__['__conform__']
> break
> else:
> # not found

-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246, redux

2005-01-13 Thread Alex Martelli
On 2005 Jan 13, at 22:43, Paramjit Oberoi wrote:
On Thu, 13 Jan 2005 20:40:56 +0100, Alex Martelli <[EMAIL PROTECTED]> 
wrote:
So please explain what's imperfect in wrapping a str into a StringIO?
If I understand Philip's argument correctly, the problem is this:
def print_next_line(f: file):
print f.readline()
s = "line 1\n" "line 2"
print_next_line(s)
print_next_line(s)
This will print "line 1" twice.
Ah!  A very clear example, thanks.  Essentially equivalent to saying 
that adapting a list to an iterator ``rewinds'' each time the 
``adaptation'' is performed, if one mistakenly thinks of iter(L) as 
providing an _adapter_:

def print_next_item(it: iterator):
print it.next()
L = ['item 1', 'item 2']
print_next_item(L)
print_next_item(L)
Funny that the problem was obvious to me for the list->iterator issue 
and yet I was so oblivious to it for the str->readablefile one.  OK, 
this does show that (at least some) classical cases of Adapter Design 
Pattern are unsuitable for implicit adaptation (in a language with 
mutation -- much like, say, a square IS-A rectangle if a language does 
not allow mutation, but isn't if the language DOES allow it).

Thanks!
Alex
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246, redux

2005-01-13 Thread Paul Moore
On Thu, 13 Jan 2005 13:43:53 -0800, Paramjit Oberoi <[EMAIL PROTECTED]> wrote:
> On Thu, 13 Jan 2005 20:40:56 +0100, Alex Martelli <[EMAIL PROTECTED]> wrote:
> >
> > So please explain what's imperfect in wrapping a str into a StringIO?
> 
> If I understand Philip's argument correctly, the problem is this:
> 
> def print_next_line(f: file):
> print f.readline()
> 
> s = "line 1\n" "line 2"
> 
> print_next_line(s)
> print_next_line(s)
> 
> This will print "line 1" twice.

Nice example!

The real subtlety here is that

f = adapt(s, StringIO)
print_next_line(f)
print_next_line(f)

*does* work - the implication is that for the original example to
work, adapt(s, StringIO) needs to not only return *a* wrapper, but to
return *the same wrapper* every time. Which may well break *other*
uses, which expect a "new" wrapper each time.

But the other thing that this tends to make me believe even more
strongly is that using Guido's type notation for adaptation is a bad
thing.

def print_next_line(f):
ff = adapt(f, file)
print ff.readline()

Here, the explicit adaptation step in the definition of the function
feels to me a little more obviously a "wrapping" operation which may
reinitialise the adapter - and would raise warning bells in my mind if
I thought of it in terms of a string->StringIO adapter.

Add this to the inability to recover the original object (for
readaptation, or passing on as an argument to another function), and
I'm very concerned about Guido's type notation being used as an
abbreviation for adaptation...

Paul.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] frame.f_locals is writable

2005-01-13 Thread Brett C.
Shane Holloway (IEEE) wrote:
For a little background, I'm working on making an edit and continue 
support in python a little more robust.  So, in replacing references to 
unmodifiable types like tuples and bound-methods (instance or class), I 
iterate over gc.get_referrers.

So, I'm working on frame types, and wrote this code::
def replaceFrame(self, ref, oldValue, newValue):
for name, value in ref.f_locals.items():
if value is oldValue:
ref.f_locals[name] = newValue
assert ref.f_locals[name] is newValue
But unfortunately, the assert fires.  f_locals is writable, but not 
modifiable.  I did a bit of searching on Google Groups, and found 
references to a desire for smalltalk like "swap" functionality using a 
similar approach, but no further ideas or solutions.

While I am full well expecting the smack of "don't do that", this 
functionality would be very useful for debugging long-running 
applications.  Is this possible to implement in CPython and ports?  Is 
there an optimization reason to not do this?

So it would be doable, but it is not brain-dead simple if you want to keep the 
interface of a dict.  Locals, in the frame, are an array of PyObjects (see 
PyFrameObject->f_localsplus).  When you request f_locals that returns a dict 
that was created by a function that takes the array, traverses it, and creates 
a dict with the proper names (using PyFrameObject->f_code->co_varnames for the 
array offset -> name mapping).  The resulting dict gets stored in 
PyFrameObject->f_locals.  So it is writable as you discovered since it is just 
a dict, but it is not used in Python/ceval.c except for IMPORT_STAR; changes 
are just never even considered.  The details for all of this can be found in 
Objects/frameobject.c:PyFrame_FastToLocals() .

The interesting thing is that there is a corresponding PyFrame_LocalsToFast() 
function that seems to do what you want; it takes the dict in 
PyFrameObject->f_locals and propogates the changes into 
PyFrameObject->f_localsplus (or at least seems to; don't have time to stare at 
the code long enough to make sure it does that exactly).  So the functionality 
is there (and is in the API even).  It just isn't called explicitly except in 
two points in Python/ceval.c where you can't get at it.  =)

As to making changes to f_locals actually matter would require either coming up 
with a proxy object that is stored in f_locals instead of a dict and 
dynamically grab everything from f_localsplus as needed.  That would suck for 
performance and be a pain to keep the dict API.  So you can count that out.

Other option would be to add a function that either directly modified single 
values in f_localsplus, a function that takes a dict and propogates the values, 
or a function that just calls PyFrame_LocalsToFast() .

Personally I am against this, but that is because you would single-handedly 
ruin my master's thesis and invalidate any possible type inferencing one can do 
in Python without some semantic change.  But then again my thesis shows that 
amount of type inferencing is not worth the code complexity so it isn't totally 
devastating.  =)

And you are right, "don't do that".  =)
Back to the putrid, boggy marsh of JavaLand for me...
-Brett
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246, redux

2005-01-13 Thread Paramjit Oberoi
On Thu, 13 Jan 2005 20:40:56 +0100, Alex Martelli <[EMAIL PROTECTED]> wrote:
>
> So please explain what's imperfect in wrapping a str into a StringIO?

If I understand Philip's argument correctly, the problem is this:

def print_next_line(f: file):
print f.readline()

s = "line 1\n" "line 2"

print_next_line(s)
print_next_line(s)

This will print "line 1" twice.

-param
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246, redux

2005-01-13 Thread Clark C. Evans
On Thu, Jan 13, 2005 at 08:40:56PM +0100, Alex Martelli wrote:
| >The other issue with registries (and why I avoided them in the 
| >origional) is that they often require a scoping; in this case, 
| >the path taken by one module might be different from the one 
| >needed by another.
| 
| I think that should not be supported, just like different modules 
| cannot register different ways to copy.copy(X) for the same X.  One 
| size had better fit all, be it a single specific adapter or potentially 
| a path thereof.

Sounds good.

| >Ok.  I just think you all are solving a problem that doesn't exist,
| 
| Apparently, the existence of the problem is testified by the experience 
| of the Eclipse developers (who are, specifically, adapting plugins: 
| Eclipse being among the chief examples f plugin-based architecture... 
| definitely an N-players scenario).

Some specific examples from Eclipse developers would help then,
especially ones that argue strongly for automagical transitive
adaptation.  That is, ones where an alternative approach that
is not automatic is clearly inferior.

| >   A component developer X and a framework developer Y both
| >   have stuff that an application developer A is putting
| >   together.  The goal is for A to not worry about _how_ the
| >   components and the framework fit; to automatically "find"
| >   the glue code.
... 
| I'm quite ready to consider the risk of having too-thick combined 
| layers of glue resulting from adaptation (particularly but not 
| exclusively with transitivity): indeed PJE's new ideas may be seen as a 
| novel way to restart-from-scratch and minimize glue thickness in the 
| overall resulting concoction.

I do like PJE's idea, since it seems to focus on declaring individual 
functions rather than on sets of functions; but I'm still unclear
what problem it is trying to solve.

| But the optional ability for 
| particularly skilled glue-layers to have that extra layer which makes 
| everything better should perhaps not be discounted.  Although, 
| considering PJE's new just-started effort, it may well be wisest for 
| PEP 246 to stick to a minimalist attitude -- leave open the possibility 
| of future additions or alterations but only specify that minimal core 
| of functionality which we all _know_ is needed.

I'd rather not be pushing for a powerful regsistry mechansim unless
we have solid evidence that the value it provides outweighs the costs
that it incurres.

| >I strongly disagree; the most useful adapters are the ones that
| >discard unneeded information.
| 
| The Facade design pattern?  It's useful, but I disagree that it's "most 
| useful" when compared to general Adapter

My qualification was not very well placed.  That said, I don't see any 
reason why a facade can't also be asked for via the adapt() mechanism.

| So please explain what's imperfect in wrapping a str into a StringIO?

It adds information, and it implies mutability which the underlying
object is not.  In short, it's quite a different animal from a String,
which is why String->StringIO is a great example for an adapter.

| >| What about "registered explicitly as being suitable for transitivity",
| >| would that suffice?
| >
| >I suppose so.  But I think it is a bad idea for a few reasons:
| >
| >  1. it seems to add complexity without a real-world justifcation,
| > let's go without it; and add it in a later version if it turns
| > out to be as valueable as people think
| 
| Particularly in the light of PJE's newest ideas, being spare and 
| minimal in PEP 246 does sound good, as long as we're not shutting and 
| bolting doors against future improvements.

Agreed!

| >  2. different adapters have different intents...
|
| If you've ever looked into "quality of data" issues in huge databases, 
| you know that these are two (out of thousands) typical problems -- but 
| not problems in _adaptation_, in fact.

I deal with these issues all of the time; but what I'm trying to
express with the example is that someone may _think_ that they are
writing a perfect adapter; but they may be wrong, on a number of
levels.  It's not so much to say what is good, but rather to 
challenge the notion of a 'perfect adapter'. 

| >In short, unless a human is giving the 'ok' to an adapter's
| >use, be it the application, framework, or component developer,
| >then I'd expect wacko bugs.
| 
| A lot of the data quality problems in huge databases come exactly from 
| humans -- data entry issues, form design issues, ... all the way to 
| schema-design issues.  I don't see why, discussing a data-quality 
| problem, you'd think that having a human OK whatsoever would help wrt 
| having a formalized rule (e.g. a database constraint) do it.

The point I was trying to make is that automatically constructing
adapters isn't a great idea unless you have someone who can vouche
for the usefulness.  In other words, I picture this as a physics
story problem, where a bunch of numbers are given with units. While
the

[Python-Dev] frame.f_locals is writable

2005-01-13 Thread Shane Holloway (IEEE)
For a little background, I'm working on making an edit and continue 
support in python a little more robust.  So, in replacing references to 
unmodifiable types like tuples and bound-methods (instance or class), I 
iterate over gc.get_referrers.

So, I'm working on frame types, and wrote this code::
def replaceFrame(self, ref, oldValue, newValue):
for name, value in ref.f_locals.items():
if value is oldValue:
ref.f_locals[name] = newValue
assert ref.f_locals[name] is newValue
But unfortunately, the assert fires.  f_locals is writable, but not 
modifiable.  I did a bit of searching on Google Groups, and found 
references to a desire for smalltalk like "swap" functionality using a 
similar approach, but no further ideas or solutions.

While I am full well expecting the smack of "don't do that", this 
functionality would be very useful for debugging long-running 
applications.  Is this possible to implement in CPython and ports?  Is 
there an optimization reason to not do this?

At worst, if this isn't possible, direct references in the stack will be 
wrong above the reload call, and corrected on the invocation of the 
function.  This is a subtle issue with reloading code, and can be 
documented.  And at best there is an effective way to replace it, the 
system can be changed to a consistent state even in the stack, and I can 
rejoice.  Even if I have to wait until 2.5.  ;)

Thanks for your time!
-Shane Holloway
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246, redux

2005-01-13 Thread Alex Martelli
On 2005 Jan 13, at 19:21, Clark C. Evans wrote:
   ...
Are you _sure_ you have M*N adapters here?  But even so,
Yep.
  for j in (J1,J2,J3,J4,...,JM)
for i in (I1,I2,...,IN):
  register(j,i)
Uh?  WHAT are you registering for each j->i...?
The other issue with registries (and why I avoided them in the 
origional
PEP) is that they often require a scoping; in this case, the path taken
by one module might be different from the one needed by another.
I think that should not be supported, just like different modules 
cannot register different ways to copy.copy(X) for the same X.  One 
size had better fit all, be it a single specific adapter or potentially 
a path thereof.

| The convenience of this is undeniable; and (all other things being
| equal) convenience raises productivity and thus is valuable.
It also hides assumptions.  If you are doing adaptation paths

Not sure if it hides them very deeply, but yes, there may be some 
aspects of "information hiding" -- which is not necessarily a bad 
thing.

Ok.  I just think you all are solving a problem that doesn't exist,
Apparently, the existence of the problem is testified by the experience 
of the Eclipse developers (who are, specifically, adapting plugins: 
Eclipse being among the chief examples f plugin-based architecture... 
definitely an N-players scenario).


and in the process hurting a the more common use case:
   A component developer X and a framework developer Y both
   have stuff that an application developer A is putting
   together.  The goal is for A to not worry about _how_ the
   components and the framework fit; to automatically "find"
   the glue code.
The assertion that you can layer glue... is well, tenuous at best.
If you ever did any glueing (of the traditional kind, e.g. in 
historical-furniture restoration, as opposed to relatively new miracle 
glues) you know you typically DO layer glue -- one layer upon one of 
the pieces of wood you're glueing; one layer on the other; let those 
two dry a bit; then, you glue the two together with a third layer in 
the middle.  Of course it takes skill (which is why although I know the 
theory when I have any old valuable piece of furniture needing such 
restoration I have recourse to professionals;-) to avoid the 
easy-to-make mistake of getting the glue too thick (or uneven, etc).

I'm quite ready to consider the risk of having too-thick combined 
layers of glue resulting from adaptation (particularly but not 
exclusively with transitivity): indeed PJE's new ideas may be seen as a 
novel way to restart-from-scratch and minimize glue thickness in the 
overall resulting concoction.  But the optional ability for 
particularly skilled glue-layers to have that extra layer which makes 
everything better should perhaps not be discounted.  Although, 
considering PJE's new just-started effort, it may well be wisest for 
PEP 246 to stick to a minimalist attitude -- leave open the possibility 
of future additions or alterations but only specify that minimal core 
of functionality which we all _know_ is needed.


| In terms of "should" as opposed to convenience, though, the argument 
is
| that interface to interface adapters SHOULD always, inherently be
| suitable for transitive chains because there is NO reason, EVER, 
under
| ANY circumstances, to have such adapters be less than perfect,
| lossless, noiseless, etc, etc.

I strongly disagree; the most useful adapters are the ones that
discard unneeded information.
The Facade design pattern?  It's useful, but I disagree that it's "most 
useful" when compared to general Adapter.  My favourite example is 
wrapping a str into a StringIO to make a filelike readable object -- 
that doesn't discard anything, it *adds* a "current reading point" 
state variable (which makes me dubious of the new "no per-state 
adapter" craze, which WOULD be just fine if it was true that discarding 
unneeded info -- facading -- is really the main use case).

  The big picture above, where you're
plugging components into the framework will in most cases be lossy
-- or the frameworks / components would be identical and you woudn't
want to hook them up. Frankly, I think the whole idea of "perfect
adapters" is just, well, arrogant.
So please explain what's imperfect in wrapping a str into a StringIO?

| What about "registered explicitly as being suitable for 
transitivity",
| would that suffice?

I suppose so.  But I think it is a bad idea for a few reasons:
  1. it seems to add complexity without a real-world justifcation,
 let's go without it; and add it in a later version if it turns
 out to be as valueable as people think
Particularly in the light of PJE's newest ideas, being spare and 
minimal in PEP 246 does sound good, as long as we're not shutting and 
bolting doors against future improvements.


  2. different adapters have different intents, and I think a given
 adapter may be perfect in one situation, it may royally
 screw up in another; users of systems oft

[Python-Dev] Re: Recent IBM Patent releases

2005-01-13 Thread Scott David Daniels
Terry Reedy wrote:
"Scott David Daniels" <[EMAIL PROTECTED]>
I believe our current policy is that the author warrants that the code
is his/her own work and not encumbered by any patent.
Without a qualifier such as 'To the best of my knowledge', the latter is an 
impossible warrant both practically, for an individual author without 
$1000s to spend on a patent search, and legally.  Legally, there is no 
answer until the statute of limitations runs out or until there is an 
after-the-fact final answer provided by the court system.
Absolutely.  I should have written that in the first place.  I was
trying to generate a little discussion about a particular case (the
released IBM patents) where we might want to say, "for these patents,
feel free to include code based on them."  My understanding is that
we will remove patented code if we get notice that it _is_ patented,
and that we strive to not put any patented code into the source.
--Scott David Daniels
[EMAIL PROTECTED]
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246, redux

2005-01-13 Thread Clark C. Evans

On Thu, Jan 13, 2005 at 06:27:08PM +0100, Alex Martelli wrote:
| >The 'implicit' adaptation refers to the automagical construction of
| >composite adapters assuming that a 'transitive' property holds. I've
| >seen nothing in this thread to explain why this is so valueable, why
| 
| Let me play devil's advocate: I _have_ seen explanations of why 
| transitive adaptation can be convenient -- the most direct one being an 
| example by Guido which came in two parts, the second one a 
| clarification which came in response to my request about the first one. 

hypothetical pseudocode ;)

| To summarize it: say we have N concrete classes A1, A2, ... AN which 
| all implement interface I.
| Now we want to integrate into the system function f1, which requires an 
| argument with interface J1, i.e.
| def f1(x):
| x = adapt(x, J1)
| ...
| or in Guido's new notation equivalently
| def f1(x: J1):
| ...
| and also f2, ..., fM, requiring an argument with interface J2, ..., JM 
| respectively.
| 
| Without transitivity, we need to code and register M*N adapters. 

Are you _sure_ you have M*N adapters here?  But even so,

  for j in (J1,J2,J3,J4,...,JM)
for i in (I1,I2,...,IN):
  register(j,i)

| WITH transitivity, we only need M: I->J1, I->J2, ..., I->JM.

Without transitivity, a given programmer, in a given module will
probably only use a few of these permutations; and in each case,
you can argue that the developer should be aware of the 'automatic'
conversions that are going on.  Imagine an application developer
plugging a component into a framework and getting this error:

"""Adaption Error
   
Could not convert A1 to a J1.   There are two adaption pathways
which you could register to do this conversion for you:
   
# A1->I1 followed by I1->J1
adapt.registerPath((A1,I1),(I1,J1))

# A1->X3 followed by X3 -> PQ follwed by PQ -> J1
adapt.registerPath((A1,X3),(X3,PQ),(PQ,J1))
"""

The other issue with registries (and why I avoided them in the origional
PEP) is that they often require a scoping; in this case, the path taken
by one module might be different from the one needed by another.

| The convenience of this is undeniable; and (all other things being 
| equal) convenience raises productivity and thus is valuable.

It also hides assumptions.  If you are doing adaptation paths

| James Knight gave a real-life example, although, since no combinatorial 
| explosion was involved, the extra convenience that he missed in 
| transitivity was minor compared to the potential for it when the N*M 
| issue should arise.

Right.  And that's more like it.

| >it shouldn't be explicit,
| 
| On this point I'm partly with you: I do not see any real loss of 
| convenience in requiring that an adapter which is so perfect and 
| lossless as to be usable in transitivity chains be explicitly so 
| registered/defined/marker.  E.g., provide a
| registerAdapter_TRANSITIVITY_SUITABLE(X, Y)
| entry in addition to the standard registerAdapter which does not supply 
| transitivity (or equivalently an optional suitable_for_transitivity 
| argument to registerAdapter defaulting to False, etc, etc).

Ok.  I just think you all are solving a problem that doesn't exist,
and in the process hurting a the more common use case:

   A component developer X and a framework developer Y both 
   have stuff that an application developer A is putting
   together.  The goal is for A to not worry about _how_ the
   components and the framework fit; to automatically "find"
   the glue code.

The assertion that you can layer glue... is well, tenuous at best.

| In terms of "should" as opposed to convenience, though, the argument is 
| that interface to interface adapters SHOULD always, inherently be 
| suitable for transitive chains because there is NO reason, EVER, under 
| ANY circumstances, to have such adapters be less than perfect, 
| lossless, noiseless, etc, etc. 

I strongly disagree; the most useful adapters are the ones that
discard unneeded information.  The big picture above, where you're
plugging components into the framework will in most cases be lossy
-- or the frameworks / components would be identical and you woudn't
want to hook them up. Frankly, I think the whole idea of "perfect
adapters" is just, well, arrogant.  

| > and on the contrary, most of the "problems
| >with adapt()" seem to stem from this aggressive extension of what
| >was proposed: Automatic construction of adapter chains is _not_ part
| 
| Fair enough, except that it's not just chains of explicitly registered 
| adapters: interface inheritance has just the same issues, indeed, in 
| PJE's experience, MORE so, because no code is interposed -- if by 
| inheriting an interface you're asserting 100% no-problem 
| substitutability, the resulting "transitivity" may thus well give 
| problems (PJE and I even came close to agreeing that MS COM's 
| QueryInterface idea that interface inheritance does NOT implic

Re: getting special from type, not instance (was Re: [Python-Dev] copy confusion)

2005-01-13 Thread Alex Martelli
On 2005 Jan 13, at 18:02, Guido van Rossum wrote:
   ...
In all cases, I'm +1 on seeing built-in method objects 
(PyMethodDescr_Type)
become data descriptors ("classy descriptors?" :-).
Let's do override descriptors.
A Pronouncement!!!
And please, someone fix copy.py in 2.3 and 2.4.
Sure -- what way, though?  The way I proposed in my last post about it?
Alex
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246, redux

2005-01-13 Thread Clark C. Evans
On Wed, Jan 12, 2005 at 01:15:20PM -0800, Guido van Rossum wrote:
| [Clark]
| >   - add a flag to adapt, allowTransitive, which defaults to False
| 
| That wouldn't work very well when most adapt() calls are invoked
| implicitly through signature declarations (per my blog's proposal).

Understood.  This was a side-suggestion -- not the main thrust of my
response.  I'm writing to convince you that automatic "combined"
adaptation, even as a last resort, is a bad idea.  It should be
manual, but we can provide easy mechanisms for application developers 
to specify combined adapters easily.

On Wed, Jan 12, 2005 at 02:57:11PM -0500, Clark C. Evans wrote:
| On Wed, Jan 12, 2005 at 10:16:14AM -0800, Guido van Rossum wrote:
| | But now, since I am still in favor of automatic "combined" adaptation
| | *as a last resort*

A few problems with automatic "combined" adaptation:

  1. Handling the case of multiple adaptation pathways is one issue;
 how do you choose? There isn't a good cost algorithem since the
 goodness of an adapter depends largely on the programmer's need.

  2. Importing or commenting out the import of a module that may seem
 to have little bearing on a given chunk of code could cause
 subtle changes in behavior or adaptation errors, as a new path
 becomes available, or a previously working path is disabled.

  3. The technique causes people to want to say what is and isn't
 an adapter -- when this choice should be soly up to the
 appropriate developers.  I'd rather not have to standardize
 that FileName -> File is a _bad_ adaption, but File -> String
 is a good adaption.  Or whatever is in vogue that year.

  4. It's overly complicated for what it does.  I assert that this is
 a very minor use case. When transitive adaptation is needed,
 an explicit registration of an adapter can be made simple.

My current suggestion to make 'transitive adaption' easy for a 
application builder (one putting togeher components) has a few
small parts:

  - If an adaptation is not found, raise an error, but list in
the error message two additional things: (a) what possible
adaptation paths exist, and (b) how to register one of
these paths in their module.
   
  - A simple method to register an adaption path, the error message
above can even give the exact line needed,
  
   adapt.registerPath(from=A,to=C,via=B)
   
  - Make it an error to register more than one adapter from A
to C, so that conflicts can be detected.  Also, registrations
could be 'module specific', or local, so that adapters used 
by a library need necessarly not be global.

In general, I think registries suffer all sorts of namespace and
scoping issues, which is why I had proposed __conform__ and __adapt__
Extending registry mechanism with automatic 'transitive' adapters 
makes things even worse.

Cheers,

Clark
-- 
Clark C. Evans  Prometheus Research, LLC.
http://www.prometheusresearch.com/
o   office: +1.203.777.2550 
  ~/ ,  mobile: +1.203.444.0557 
 //
((   Prometheus Research: Transforming Data Into Knowledge
 \\  ,
   \/- Research Exchange Database
   /\- Survey & Assessment Technologies
   ` \   - Software Tools for Researchers
~ *
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246, redux

2005-01-13 Thread Alex Martelli
On 2005 Jan 13, at 16:13, Carlos Ribeiro wrote:
   ...
+1, specially for the last sentence. An adapter with local state is
not an adapter anymore! It's funny how difficult it's to get this...
but it's obvious once stated.
...?  A StringIO instance adapting a string to be used as a 
readablefile is not an adapter?!  It's definitely a pristine example of 
the Adapter Design Pattern (per Gof4), anyway... and partly because of 
that I think it SHOULD be just fine as an ``adapter''... honestly I 
fail to see what's wrong with the poor StringIO instance keeping the 
"we have read as far as HERE" index as its "local state" (imagine a 
readonlyStringIO if you want, just to make for simpler concerns).

Or, consider a View in a Model-View-Controller arrangement; can't we 
get THAT as an adapter either, because (while getting most data from 
the Model) it must still record some few presentation-only details 
locally, such as, say, the font to use?

I'm not sure I'm all that enthusiastic about this crucial aspect of 
PJE's new "more pythonic than Python" [r]evolution, if it's being 
presented correctly here.

Alex
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: getting special from type, not instance (was Re: [Python-Dev] copy confusion)

2005-01-13 Thread Phillip J. Eby
At 09:02 AM 1/13/05 -0800, Guido van Rossum wrote:
[Armin]
> I guess that a name-based hack in type_new() to turn all __*__() 
methods into
> data descriptors would be even more obscure?

To the contary, I just realized in this would in fact be the right
approach. In particular, any *descriptor* named __*__ would be
considered a "data descriptor". Non-descriptors with such names can
still be overridden in the instance __dict__ (I believe this is used
by Zope).
It should check that the __*__-named thing isn't *already* an override 
descriptor, though.

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246, redux

2005-01-13 Thread Alex Martelli
On 2005 Jan 13, at 16:08, Phillip J. Eby wrote:
this with their string/file/path discussions -- *nobody* is safe from 
implicit adaptation if adaptation actually creates new objects with 
independent state!  An adapter's state needs to be kept with the 
original object, or not at all, and most of the time "not at all" is 
the correct answer.
So, no way to wrap a str with a StringIO to adapt to 
"IReadableFile"...?  Ouch:-(  That was one of my favourite trivial use 
cases...

Anyway -- I'm pointing out that what to put in a rewrite of PEP 246 
as a result of all this is anything but obvious at this point, at 
least to me.
LOL.  Me either!
...so let's hope Clark has clearer ideas, as it appears he does: as per 
a previous msg, I've asked him if he could be the one doing the next 
round of edits, instead of me...

Alex
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246, redux

2005-01-13 Thread Alex Martelli
On 2005 Jan 13, at 15:34, Clark C. Evans wrote:
   ...
The 'implicit' adaptation refers to the automagical construction of
composite adapters assuming that a 'transitive' property holds. I've
seen nothing in this thread to explain why this is so valueable, why
Let me play devil's advocate: I _have_ seen explanations of why 
transitive adaptation can be convenient -- the most direct one being an 
example by Guido which came in two parts, the second one a 
clarification which came in response to my request about the first one. 
 To summarize it: say we have N concrete classes A1, A2, ... AN which 
all implement interface I.
Now we want to integrate into the system function f1, which requires an 
argument with interface J1, i.e.
def f1(x):
x = adapt(x, J1)
...
or in Guido's new notation equivalently
def f1(x: J1):
...
and also f2, ..., fM, requiring an argument with interface J2, ..., JM 
respectively.

Without transitivity, we need to code and register M*N adapters.  WITH 
transitivity, we only need M: I->J1, I->J2, ..., I->JM.

The convenience of this is undeniable; and (all other things being 
equal) convenience raises productivity and thus is valuable.

James Knight gave a real-life example, although, since no combinatorial 
explosion was involved, the extra convenience that he missed in 
transitivity was minor compared to the potential for it when the N*M 
issue should arise.

it shouldn't be explicit,
On this point I'm partly with you: I do not see any real loss of 
convenience in requiring that an adapter which is so perfect and 
lossless as to be usable in transitivity chains be explicitly so 
registered/defined/marker.  E.g., provide a
registerAdapter_TRANSITIVITY_SUITABLE(X, Y)
entry in addition to the standard registerAdapter which does not supply 
transitivity (or equivalently an optional suitable_for_transitivity 
argument to registerAdapter defaulting to False, etc, etc).
In terms of "should" as opposed to convenience, though, the argument is 
that interface to interface adapters SHOULD always, inherently be 
suitable for transitive chains because there is NO reason, EVER, under 
ANY circumstances, to have such adapters be less than perfect, 
lossless, noiseless, etc, etc.  I am not entirely convinced of this but 
"devil's advocacy wise" I could probably argue for it: for the hapless 
programmers' own good, they should be forced to think very VERY 
carefully of what they're doing, etc, etc.  Yeah, I know, I don't sound 
convincing because I'm not all that convinced myself;-).

 and on the contrary, most of the "problems
with adapt()" seem to stem from this aggressive extension of what
was proposed: Automatic construction of adapter chains is _not_ part
Fair enough, except that it's not just chains of explicitly registered 
adapters: interface inheritance has just the same issues, indeed, in 
PJE's experience, MORE so, because no code is interposed -- if by 
inheriting an interface you're asserting 100% no-problem 
substitutability, the resulting "transitivity" may thus well give 
problems (PJE and I even came close to agreeing that MS COM's 
QueryInterface idea that interface inheritance does NOT implicitly and 
undeniably assert substitutability is very practical, nice, and 
usable...).

of the original PEP 246 and I hope it remains that way.   I've
outlined in several posts how this case could be made easy for a
application developer to do:
  - transitive adapters should always be explicit
What about "registered explicitly as being suitable for transitivity", 
would that suffice?

  - it should be an error to have more than one adapter
from A to Z in the registry
OK, I think.  There has to be a way to replace an adapter with another, 
I think, but it might be fair to require that this be done in two 
steps:
unregister the old adapter, THEN immediately
register the new one
so that trying to register an adapter for some A->Z pair which already 
has one is an error.  Replacing adapters feels like a rare enough 
operation that the tiny inconvenience should not be a problem, it 
appears to me.

  - when adaptation fails, an informative error message can
tell the application developer of possible "chains"
which could work
Nice, if not too much work.
  - registration of transitive adapters can be simple command
application developers use:  adapt.transitive(from=A,to=Z,via=M)
error message can tell an application developer
OK, convenient if feasible.
Considering all of your proposals, I'm wondering: would you be willing 
to author the next needed draft of the PEP in the minimal spirit I was 
proposing?  Since I wrote the last round, you might do a better job of 
editing the next, and if more rounds are needed we could keep 
alternating (perhaps using private mail to exchange partially edited 
drafts, too)...

The 'registry' idea (which was not explored in the PEP) emerges from
the need, albeit limited, for the application developer who is

Re: [Python-Dev] PEP 246, redux

2005-01-13 Thread Clark C. Evans
On Fri, Jan 14, 2005 at 12:30:17AM +1000, Nick Coghlan wrote:
| Anyway, I'd like to know if the consensus I think you've reached is the 
| one the pair of you think you've reached :)

This stated position is not the current PEP status, and it's 
not a concensus position I share.

| That is, with A being our starting class, C being a target class, and F 
| being a target interface, the legal adaptation chains are:
|   # Class to class
|   A->C
|   # Class to interface, possibly via other interfaces
|   A(->F)*->F

PEP246 should not talk about legal or illegal adaption chains, 
all adaption chains should be explicit, and if they are explicit,
the programmer who specified them has made them legal.

| With a lookup sequence of:
|   1. Check the global registry for direct adaptations
|   2. Ask the object via __conform__
|   3a. Check using isinstance() unless 2 raised LiskovViolation
|   3b. Nothing, since object.__conform__ does an isinstance() check
|   4. Ask the interface via __adapt__

These are OK up to 4.

|   5. Look for transitive chains of interfaces in the global registry.

No! No! No!  Perhaps...

5. Raise a AdaptionFailed error, which includes the protocol
   which is being asked for.  This error message _could_ also
   include a list of possible adaptation chains from the global
   registry, but this is just a suggestion.
   
| 3a & 3b are the current differing answers to the question of who should 
| be checking for inheritance - the adaptation machinery or the __conform__ 
| method.

Correct.  I think either method is OK, and perfer Phillip's approach.

Best,

Clark


-- 
Clark C. Evans  Prometheus Research, LLC.
http://www.prometheusresearch.com/
o   office: +1.203.777.2550 
  ~/ ,  mobile: +1.203.444.0557 
 //
((   Prometheus Research: Transforming Data Into Knowledge
 \\  ,
   \/- Research Exchange Database
   /\- Survey & Assessment Technologies
   ` \   - Software Tools for Researchers
~ *
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: getting special from type, not instance (was Re: [Python-Dev] copy confusion)

2005-01-13 Thread Guido van Rossum
> > The descriptor for __getattr__ and other special attributes could
> > claim to be a "data descriptor"
> 
> This has the nice effect that x[y] and x.__getitem__(y) would again be
> equivalent, which looks good.
> 
> On the other hand, I fear that if there is a standard "metamethod" decorator
> (named after Phillip's one), it will be misused.  Reading the documentation
> will probably leave most programmers with the feeling "it's something magical
> to put on methods with __ in their names", and it won't be long before someone
> notices that you can put this decorator everywhere in your classes (because it
> won't break most programs) and gain a tiny performance improvement.
> 
> I guess that a name-based hack in type_new() to turn all __*__() methods into
> data descriptors would be even more obscure?

To the contary, I just realized in this would in fact be the right
approach. In particular, any *descriptor* named __*__ would be
considered a "data descriptor". Non-descriptors with such names can
still be overridden in the instance __dict__ (I believe this is used
by Zope).

> Finally, I wonder if turning all methods whatsoever into data descriptors
> (ouch! don't hit!) would be justifiable by the feeling that it's often bad
> style and confusing to override a method in an instance (as opposed to
> defining a method in an instance when there is none on the class).
> (Supporting this claim: Psyco does this simplifying hypothesis for performance
> reasons and I didn't see yet a bug report for this.)

Alas, it's a documented feature that you can override a (regular)
method by placing an appropriate callable in the instance __dict__.

> In all cases, I'm +1 on seeing built-in method objects (PyMethodDescr_Type)
> become data descriptors ("classy descriptors?" :-).

Let's do override descriptors.

And please, someone fix copy.py in 2.3 and 2.4.

-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246, redux

2005-01-13 Thread Clark C. Evans
On Fri, Jan 14, 2005 at 02:03:57AM +1000, Nick Coghlan wrote:
| Carlos Ribeiro wrote:
| > On Thu, 13 Jan 2005 10:08:10 -0500, Phillip J. Eby wrote:
| > > With the previous PEP, people could create all sorts of subtle problems 
| > > in their code (with or without transitivity!) and have no direct 
| > > indicator of a problem.  Clark and Ian made me realize this with their 
| > > string/file/path discussions -- *nobody* is safe from implicit 
| > > adaptation if adaptation actually creates new objects with independent
| > > state!  An adapter's state needs to be kept with the original object,
| > > or not at all, and most of the time "not at all" is the correct answer.
| >
| >+1, specially for the last sentence. An adapter with local state is
| >not an adapter anymore! It's funny how difficult it's to get this...
| >but it's obvious once stated.
| 
| +lots

-1

There is nothing wrong with an adapter from String to File, one
which adds the current read position in its state.  No adapter is a
perfect translation -- or you woudn't need them in the first place.
An adapter, by default, does just that, it wraps the object to make
it compliant with another interface.  To disallow it from having
local state is, like taking the wheels off a car and expecting it
to be useful (in somecases it is, for ice fishing, but that's 
another and rather oblique story).

Ian stated the issue properly: adapters bring with them an intent,
which cannot, in general way, be expressed in code.  Therefore,
combining adapters haphazardly will, of course, get you into
trouble.  The solution is simple -- don't do that.  PEP 246 should
at the very least remain silent on this issue, it should not
encourage or specify automagic transitive adaptation.  If a user
blows their foot off, by their own actions, they will be able to
track it down and learn; if the system shots their foot off, by
some automatic transitive adaption; well, that's another issue.

| Now that it's been stated, I think this is similar to where implicit type 
| conversions in C++ go wrong, and to the extent that PEP 246 aligns with 
| those. . . *shudder*.

PEP 246 doesn't align at all with this problem. 

Best,

Clark

-- 
Clark C. Evans  Prometheus Research, LLC.
http://www.prometheusresearch.com/
o   office: +1.203.777.2550 
  ~/ ,  mobile: +1.203.444.0557 
 //
((   Prometheus Research: Transforming Data Into Knowledge
 \\  ,
   \/- Research Exchange Database
   /\- Survey & Assessment Technologies
   ` \   - Software Tools for Researchers
~ *
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246, redux

2005-01-13 Thread Paul Moore
On Thu, 13 Jan 2005 10:26:54 -0500, Phillip J. Eby
<[EMAIL PROTECTED]> wrote:
> At 09:34 AM 1/13/05 -0500, Clark C. Evans wrote:
> >On Thu, Jan 13, 2005 at 10:35:39AM +, Paul Moore wrote:
> >| One thing I feel is key is the fact that adaptation is a *tool*, and
> >| as such will be used in different ways by different people. That is
> >| not a bad thing, even if it does mean that some people will abuse the tool.
> >|
> >| Now, a lot of the talk has referred to "implicit" adaptation. I'm
> >| still struggling to understand how that concept applies in practice,
> >| beyond the case of adaptation chains - at some level, all adaptation
> >| is "explicit", insofar as it is triggered by an adapt() call.
> >
> >The 'implicit' adaptation refers to the automagical construction of
> >composite adapters assuming that a 'transitive' property holds.
> 
> Maybe some folks are using the term that way; I use it to mean that in this
> code:
> 
> someOb.something(aFoo)
> 
> 'aFoo' may be "implicitly adapted" because the 'something' method has a
> type declaration on the parameter.

Whoa! At this point in time, parameters do not have type declarations,
and PEP 246 does NOTHING to change that.

In terms of Python *now* you are saying that if someOb.something is
defined like so:

def someOb.something(f):
adapted_f = adapt(f, ISomethingOrOther)

then aFoo is being "implicitly adapted". I'm sorry, but this seems to
me to be a completely bogus argument. The caller of someOb.something
has no right to know what goes on internal to the method. I would
assume that the documented interface of someOb.something would state
that its parameter "must be adaptable to ISomethingOrOther" - but
there's nothing implicit going on here, beyond the entirely sensible
presumption that if a method requires an argument to be adaptable,
it's because it plans on adapting it!

And as a user of someOb.something, I would be *entirely* comfortable
with being given the responsibility of ensuring that relevant
adaptations exist.

> Further, 'something' might call another method with another type
> declaration, passing the adapted version of 'foo', which results in you
> possibly getting implicit transitive adaptation *anyway*, without having
> intended it.

So you think it's reasonable for someOb.something to pass adapted_f on
to another function? I don't - it should pass f on. OK, that's a major
disadvantage of Guido's type declaration proposal - the loss of the
original object - but raise that with Guido, not with PEP 246. I'd
suspect that one answer from the POV of Guido's proposal would be a
way of introspecting the original object - but even that would be
horribly dangerous because of the significant change in semantics of
an argument when a type declaration is added. (This may kill
type-declaration-as-adaptation, so it's certainly serious, but *not*
in terms of PEP 246).

> Also, if adapters have per-adapter state, and 'someOb.something()' is
> expecting 'aFoo' to keep some state it puts there across calls to methods
> of 'someOb', then this code won't work correctly.

That one makes my brain hurt. But you've already said that per-adapter
state is bad, so maybe the pain is good for me :-)

> All of these things are "implicit adaptation" issues, IMO, and exist even
> withoutPyProtocols-style transitivity.

I'd certainly not characterise them as "implicit adaptation" issues
(except for the type declaration one, which doesn't apply to Python as
it is now), and personally (as I hope I've explained above) I don't
see them as PEP 246 issues, either.

> ... "Duck adaptation" solves these issues ...

... and may indeed be a better way of using Guido's type declarations
than making them define implicit adaptation. So I do support a
separate PEP for this. But I suspect its implementation timescale will
be longer than that of PEP 246...

Paul.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


RE: [Python-Dev] Re: PEP 246: LiskovViolation as a name

2005-01-13 Thread Chermside, Michael
Phillip writes:
> IMO, it's simpler to handle this use case by letting __conform__
return 
> None, since this allows people to follow the One Obvious Way to not
conform 
> to a particular protocol.
> 
> Then, there isn't a need to even worry about the exception name in the

> first place, either...

+1. Writing a default __conform__ for object is reasonable.

Alex writes:
> I'd rather not make a change to built-in ``object''  a prereq for PEP
246

Why not? Seems quite reasonable. Before __conform__ existed, there
wasn't
one for object; now that it exists, object needs one.

-- Michael Chermside



This email may contain confidential or privileged information. If you believe 
you have received the message in error, please notify the sender and delete the 
message without copying or disclosing it.

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246, redux

2005-01-13 Thread Nick Coghlan
Carlos Ribeiro wrote:
On Thu, 13 Jan 2005 10:08:10 -0500, Phillip J. Eby
<[EMAIL PROTECTED]> wrote:
With the previous PEP, people could create all sorts of subtle problems in
their code (with or without transitivity!) and have no direct indicator of
a problem.  Clark and Ian made me realize this with their string/file/path
discussions -- *nobody* is safe from implicit adaptation if adaptation
actually creates new objects with independent state!  An adapter's state
needs to be kept with the original object, or not at all, and most of the
time "not at all" is the correct answer.

+1, specially for the last sentence. An adapter with local state is
not an adapter anymore! It's funny how difficult it's to get this...
but it's obvious once stated.
+lots
Now that it's been stated, I think this is similar to where implicit type 
conversions in C++ go wrong, and to the extent that PEP 246 aligns with those. . 
. *shudder*.

I've also learned from this discussion just how wrong my own ideas about how to 
safely use adaptation were. Most Python programmers aren't going to have the 
benefit of listening to some smart people work through the various issues in public.

Cheers,
Nick.
--
Nick Coghlan   |   [EMAIL PROTECTED]   |   Brisbane, Australia
---
http://boredomandlaziness.skystorm.net
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246, redux

2005-01-13 Thread Nick Coghlan
Phillip J. Eby wrote:
Anyway, I'm at least +0 on dropping this; the reservation is just 
because I don't think everybody else will agree with this, and don't 
want to be appearing to imply that consensus between you and me implies 
any sort of community consensus on this point.  That is, the adaptation 
from "Alex and Phillip agree" to "community agrees" is noisy at best!  ;)
You seem to be doing a pretty good job of covering the bases, though. . .
Anyway, I'd like to know if the consensus I think you've reached is the one the 
pair of you think you've reached :)

That is, with A being our starting class, C being a target class, and F being a 
target interface, the legal adaptation chains are:
  # Class to class
  A->C
  # Class to interface, possibly via other interfaces
  A(->F)*->F

With a lookup sequence of:
  1. Check the global registry for direct adaptations
  2. Ask the object via __conform__
  3a. Check using isinstance() unless 2 raised LiskovViolation
  3b. Nothing, since object.__conform__ does an isinstance() check
  4. Ask the interface via __adapt__
  5. Look for transitive chains of interfaces in the global registry.
3a & 3b are the current differing answers to the question of who should be 
checking for inheritance - the adaptation machinery or the __conform__ method.

If classes wish to adapt to things which their parents adapt to, they must 
delegate to their parent's __conform__ method as needed (or simply not override 
__conform__). The ONLY automatic adaptation links are those that allow a subtype 
to be used in place of its parent type, and this can be overriden using 
__conform__. (FWIW, this point about 'adapting to things my parent can adapt to' 
by delegating in __conform__ inclines me in favour of option 3b for handling 
subtyping. However, I can appreciate wanting to keep the PEP free of proposing 
any changes to the core - perhaps mention both, and leave the decision to the BDFL?)

One question - is the presence of __adapt__ enough to mark something as an 
interface in the opinion of the adaptation machinery (for purposes of step 5)?

Second question - will there be something like __conformant__ and __conforming__ 
to allow classes and interfaces to provide additional information in the 
transitive search in step 5?

Or are both of these questions more in PEP 245 territory?
Cheers,
Nick.
Almost sent this to c.l.p by mistake . . .
--
Nick Coghlan   |   [EMAIL PROTECTED]   |   Brisbane, Australia
---
http://boredomandlaziness.skystorm.net
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246, redux

2005-01-13 Thread Phillip J. Eby
At 09:34 AM 1/13/05 -0500, Clark C. Evans wrote:
On Thu, Jan 13, 2005 at 10:35:39AM +, Paul Moore wrote:
| One thing I feel is key is the fact that adaptation is a *tool*, and
| as such will be used in different ways by different people. That is
| not a bad thing, even if it does mean that some people will abuse the tool.
|
| Now, a lot of the talk has referred to "implicit" adaptation. I'm
| still struggling to understand how that concept applies in practice,
| beyond the case of adaptation chains - at some level, all adaptation
| is "explicit", insofar as it is triggered by an adapt() call.
The 'implicit' adaptation refers to the automagical construction of
composite adapters assuming that a 'transitive' property holds.
Maybe some folks are using the term that way; I use it to mean that in this 
code:

   someOb.something(aFoo)
'aFoo' may be "implicitly adapted" because the 'something' method has a 
type declaration on the parameter.

Further, 'something' might call another method with another type 
declaration, passing the adapted version of 'foo', which results in you 
possibly getting implicit transitive adaptation *anyway*, without having 
intended it.

Also, if adapters have per-adapter state, and 'someOb.something()' is 
expecting 'aFoo' to keep some state it puts there across calls to methods 
of 'someOb', then this code won't work correctly.

All of these things are "implicit adaptation" issues, IMO, and exist even 
withoutPyProtocols-style transitivity.  "Duck adaptation" solves these 
issues by prohibiting per-adapter state and by making adaptation 
order-insensitive.  (I.e. adapt(adapt(a,B),C) should always produce the 
same result as adapt(a,C).)

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: getting special from type, not instance (was Re: [Python-Dev] copy confusion)

2005-01-13 Thread Phillip J. Eby
At 10:16 AM 1/13/05 +, Armin Rigo wrote:
On the other hand, I fear that if there is a standard "metamethod" decorator
(named after Phillip's one), it will be misused.  Reading the documentation
will probably leave most programmers with the feeling "it's something magical
to put on methods with __ in their names",
Possible solution: have it break when it's used in a non-subtype of 
'type'.  That is to say, when it's not used in a metaclass.


Finally, I wonder if turning all methods whatsoever into data descriptors
(ouch! don't hit!) would be justifiable by the feeling that it's often bad
style and confusing to override a method in an instance (as opposed to
defining a method in an instance when there is none on the class).
Hm.  I look at this the opposite way: sometimes it's nice to provide a 
default version of a callable that's supposed to be stuck on the object 
later, just like it's nice to have a default initial value for a variable 
supplied by the type.  I don't think that doing away with this feature for 
non-special methods is a step forwards.


In all cases, I'm +1 on seeing built-in method objects (PyMethodDescr_Type)
become data descriptors ("classy descriptors?" :-).
Heh.  :)
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246, redux

2005-01-13 Thread Phillip J. Eby
At 10:35 AM 1/13/05 +, Paul Moore wrote:
Now, a lot of the talk has referred to "implicit" adaptation. I'm
still struggling to understand how that concept applies in practice,
beyond the case of adaptation chains - at some level, all adaptation
is "explicit", insofar as it is triggered by an adapt() call.
It's "implicit" in that the caller of the code that contains the adapt() 
call carries no visible indication that adaptation will take place.


>   It's *still* not intuitively incorrect to me, but there's a couple
> things I can think of...
>
> (a) After you adapted the path to the file, and have a side-effect of
> opening a file, it's unclear who is responsible for closing it.
> (b) The file object clearly has state the path object doesn't have, like
> a file position.
> (c) You can't  go adapting the path object to a file whenever you
> wanted, because of those side effects.
In the context of my example above, I was assuming that C was an
"interface" (whatever that might be). Here, you're talking about
adapting to a file (a concrete class), which I find to be a much
muddier concept.
This is very much a "best practices" type of issue, though. I don't
see PEP 246 mandating that you *cannot* adapt to concrete classes, but
I can see that it's a dangerous thing to do.
Even the string->path adaptation could be considered suspect. Rather,
you "should" be defining an IPath *interface*, with operations such as
join, basename, and maybe open. Then, the path class would have a
trivial adaptation to IPath, and adapting a string to an IPath would
likely do so by constructing a path object from the string. From a
practical point of view, the IPath interface adds nothing over
adapting direct to the path class, but for the purposes of clarity,
documentation, separation of concepts, etc, I can see the value.
This confusion was another reason for the "Duck-Typing Adaptation" 
proposal; it's perfectly fine to take a 'path' class and "duck-type" an 
interface from it: i.e when you adapt to 'path', then if you call 
'basename' on the object, you will either:

1. Invoke a method that someone has claimed is semantically equivalent to 
path.basename, OR

2. Get a TypeError indicating that the object you're using doesn't have 
such an operation available.

In effect, this is the duck-typing version of a Java cast: it's more 
dynamic because it doesn't require you to implement all operations "up 
front", and also because third parties can implement the operations and add 
them, and because you can define abstract operations that can implement 
operations "in terms of" other operations.


Some mistakes are easier to avoid if you have the correct conceptual
framework. I suspect that interfaces are the conceptual framework
which make adaptation fall into place. If so, then PEP 246, and
adaptation per se, is always going to be hard to reason about for
people without a background in interfaces.
Exactly, and that's a problem -- so, I think I've invented (or reinvented, 
one never knows) the concept of a "duck interface", that requires no 
special background to understand or use, because (for example) it has no 
inheritance except normal inheritance, and involves no "adapter classes" 
anywhere.  Therefore, the reasoning you already apply to ordinary Python 
classes "just works".  (Versus e.g. the interface-logic of Zope and 
PyProtocols, which is *not* ordinary Python inheritance.)


Hmm. I think I just disqualified myself from making any meaningful 
comments :-)
And I just requalified you.  Feel free to continue commenting.  :)
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246, redux

2005-01-13 Thread Carlos Ribeiro
On Thu, 13 Jan 2005 10:08:10 -0500, Phillip J. Eby
<[EMAIL PROTECTED]> wrote:
> With the previous PEP, people could create all sorts of subtle problems in
> their code (with or without transitivity!) and have no direct indicator of
> a problem.  Clark and Ian made me realize this with their string/file/path
> discussions -- *nobody* is safe from implicit adaptation if adaptation
> actually creates new objects with independent state!  An adapter's state
> needs to be kept with the original object, or not at all, and most of the
> time "not at all" is the correct answer.

+1, specially for the last sentence. An adapter with local state is
not an adapter anymore! It's funny how difficult it's to get this...
but it's obvious once stated.

-- 
Carlos Ribeiro
Consultoria em Projetos
blog: http://rascunhosrotos.blogspot.com
blog: http://pythonnotes.blogspot.com
mail: [EMAIL PROTECTED]
mail: [EMAIL PROTECTED]
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246, redux

2005-01-13 Thread Phillip J. Eby
At 11:31 AM 1/13/05 +0100, Alex Martelli wrote:
On 2005 Jan 12, at 21:42, Phillip J. Eby wrote:
   ...
Anyway, hopefully this post and the other one will be convincing that 
considering ambiguity to be an error *reinforces* the idea of I-to-I 
perfection, rather than undermining it.  (After all, if you've written a 
perfect one, and there's already one there, then either one of you is 
mistaken, or you are wasting your time writing one!)
I'd just like to point out, as apparently conceded in your "fair enough" 
sentence in another mail, that all of this talk of "wasting your time 
writing" is completely unfounded.
The above refers to two I-to-I adapters between the same two points, not 
the addition of an adapter that creates an adaptation diamond.  I have 
indeed agreed that an "innocent" adapter diamond can trigger a "false 
alarm" from PyProtocols with respect to duplication.


 Since that "fair enough" of yours was deeply buried somewhere inside 
this huge conversation, some readers might miss the fact that your 
numerous repetitions of the similar concept in different words are just 
invalid, because, to recap:

Given four interfaces A, B, C, D, there may be need of each of the single 
steps A->B, A->C, B->D, C->D.  Writing each of these four adapters can IN 
NO WAY be considered "wasting your time writing one", because there is no 
way a set of just three out of the four can be used to produce the fourth one.
Right, I agreed to this.  However, the fact that a test can produce false 
positives does not in and of itself mean that it's "just invalid" -- the 
question is how often the result is *useful*.


I seems to me that you do at least feel some unease at the whole 
arrangement, given that you say "this whole debate has made me even less 
enamored of adaptation", as
Not exactly, because my experience to date has been that false alarms are 
exceedingly rare and I have yet to experience a *useful* adapter diamond of 
the type you've described in an actual real-life interface, as opposed to a 
made up group of A,B,C,D.So, my unease in relation to the adapter 
diamond issue is only that I can't say for absolutely certain that if PEP 
246 use became widespread, the problem of accidental I-to-I adapter 
diamonds might not become much more common than it is now.


it's not clear to me that any _other_ aspect of "this whole debate" was 
quite as problematic (e.g. issues such as "how to best get a special 
method from class rather than instance" -- while needing to be resolved 
for adaptation just as much as for copy.py etc -- hardly seem likely to 
have been the ones prompting you to go looking for "a cleaner, more 
intuitive way to do it" outside of the canonical, widespread approach to OOP).
No, the part that made me seek another solution is the reactions of people 
who were relatively fresh to the debate and the concepts of adaptation, 
interfaces, etc. in Python.  The fact that virtually every single one of 
them immediately reached for what developers who were more "seasoned" in 
this concept thought of as "adapter abuse", meant to me that:

1) Any solution that relied on people doing the right thing right out of 
the gate wasn't going to work

2) The true "Pythonic" solution would be one that requires the least 
learning of interfaces, covariance, contravariance, Liskov, all that other 
stuff

3) And to be Pythonic, it would have to provide only one "obvious way to do 
it", and that way should be in some sense the "right" way, making it at 
least a little harder to do something silly.

In other words, I concluded that we "seasoned" developers might be right 
about what adaptation is supposed to be, but that our mere presentation of 
the ideas wasn't going to sway real users.

So no, my goal wasn't to fix the adapter diamond problem per se, although I 
believe that the equivalent concept in duck adaptation (overlapping 
abstract methods) will *also* be able to trivially ignore adapter diamonds 
and still warn about meaningful ambiguities.

Instead, the goal was to make it so that people who try to abuse adapters 
will quickly discover that they *can't*, and second, as soon as they ask 
how, the obvious answer will be, "well, that's because you're doing a type 
conversion.  You need to create an instance of the thing you want, because 
you can't use that thing "as a" such-and-such."  And then they will go, 
"Ah, yes, I see...  that makes sense," and then go and sin no more.

With the previous PEP, people could create all sorts of subtle problems in 
their code (with or without transitivity!) and have no direct indicator of 
a problem.  Clark and Ian made me realize this with their string/file/path 
discussions -- *nobody* is safe from implicit adaptation if adaptation 
actually creates new objects with independent state!  An adapter's state 
needs to be kept with the original object, or not at all, and most of the 
time "not at all" is the correct answer.


Anyway -- I'm pointing out that what to put

Re: [Python-Dev] Re: PEP 246: LiskovViolation as a name

2005-01-13 Thread Phillip J. Eby
At 09:00 AM 1/13/05 +0100, Alex Martelli wrote:
Incidentally, "get this specialmethod from the type (with specialcasing 
for classic classes &c)" is a primitive that PEP 246 needs as much as, 
say, copy.py needs it.  In the light of the recent discussions of how to 
fix copy.py etc, I'm unsure about what to assume there, in a rewrite of 
PEP 246: that getattr(obj, '__aspecial__', None) always does the right 
thing via special descriptors, that I must spell everything out, or, what 
else...?
I think you can make it a condition that metaclasses with __conform__ or 
__adapt__ must use a data descriptor like my "metamethod" decorator.  Then, 
there is no metaconfusion since metaconfusion requires a metaclass to 
exist, and you're requiring that in that case, they must use a descriptor 
to avoid the problem.

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Re: PEP 246: LiskovViolation as a name

2005-01-13 Thread Skip Montanaro

stelios> Yes but in order to fall into a Liskov Violation, one will have
stelios> to use extreme OOP features (as I understand from the ongoing
stelios> discussion for which, honestly, I understand nothing:). 

The first example here:

http://www.compulink.co.uk/~querrid/STANDARD/lsp.htm

Looks pretty un-extreme to me.  It may not be detectable without the pep 246
stuff, but I suspect it's pretty common.

Skip
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246, redux

2005-01-13 Thread Clark C. Evans
On Thu, Jan 13, 2005 at 10:35:39AM +, Paul Moore wrote:
| One thing I feel is key is the fact that adaptation is a *tool*, and
| as such will be used in different ways by different people. That is
| not a bad thing, even if it does mean that some people will abuse the tool.
| 
| Now, a lot of the talk has referred to "implicit" adaptation. I'm
| still struggling to understand how that concept applies in practice,
| beyond the case of adaptation chains - at some level, all adaptation
| is "explicit", insofar as it is triggered by an adapt() call.

The 'implicit' adaptation refers to the automagical construction of
composite adapters assuming that a 'transitive' property holds. I've
seen nothing in this thread to explain why this is so valueable, why
it shouldn't be explicit, and on the contrary, most of the "problems
with adapt()" seem to stem from this aggressive extension of what
was proposed: Automatic construction of adapter chains is _not_ part
of the original PEP 246 and I hope it remains that way.   I've
outlined in several posts how this case could be made easy for a
application developer to do:

  - transitive adapters should always be explicit
  - it should be an error to have more than one adapter 
from A to Z in the registry
  - when adaptation fails, an informative error message can
tell the application developer of possible "chains" 
which could work
  - registration of transitive adapters can be simple command
application developers use:  adapt.transitive(from=A,to=Z,via=M)
error message can tell an application developer 

| James Knight's example (which seemed to get lost in the discussion, or
| at least no-one commented on it) brought up a new point for me, namely
| the fact that it's the library writer who creates interfaces, and
| calls adapt(), but it's the library *user* who says what classes
| support (can be adapted to) what interface. I hadn't focused on the
| different people involved before this point.

I'd say the more common pattern is three players.  The framework
builder, the component budiler, and the application designer.  Adapt
provides a mechansim for the framework builder (via __adapt__) and
the component builder (via __conform__) to work together without
involving the application designer.

The 'registry' idea (which was not explored in the PEP) emerges from
the need, albeit limited, for the application developer who is
plugging a component into a framework, to have some say in the
process.  I think that any actions taken by the user, by registering
an adapter, should be explicit.  

The 'diamond' problem discussed by Phillip has only confirmed this
belief.  You don't want the adapt() system going around assuming
transitivity.  However, if the application developer is certain that
a conversion path from A to Z going through B, and/or Y will work,
then it should be easy for them to specify this adaptation path.

| Now, if we have a transitive case A->B->C, where A is written by "the
| user", and C is part of "the library" and library code calls
| adapt(x,C) where x is a variable which the user supplies as an object
| of type A, then WHO IS RESPONSIBLE FOR B And does it matter, and
| if it does, then what are the differences?

Great question.  But I'd like to rephrase that C is probably a framework,
A and B are probably components; and we assume that either the framework
or component developers have enabled A->B and B->C.   If the user wishes
to make an adapter from A->C assuming no (or acceptable for his purposes)
information loss from A->C through B, then this is his/her choice.  However,
it shouldn't be done by the framework or component developers unless it is
a perfect adaptation, and it certainly shouldn't be automagic.

I don't think who owns B is particularly more important than A or C.

| As I write this, being careful *not* to talk interms of "interfaces"
| and "classes", I start to see Philip's point - in my mind, A (written
| by the user) is a class, and C (part of the library) is an
| "interface". So the answer to the question above about B is that it
| depends on whether B is an interface or a class - and the sensible
| transitivity rules could easily (I don't have the experience to
| decide) depend on whether B is a class or an interface.

I'd like to say that _any_ transitivity rule should be explicit; there
is a point where you make it easy for the programmer, but for heavens
sake, let's not try to do their job.

| BUT, and again, Philip has made this point, I can't reason about
| interfaces in the context of PEP 246, because interfaces aren't
| defined there. So PEP 246 can't make a clear statement about
| transitivity, precisely because it doesn't define interfaces. But does
| this harm PEP 246? I'm not sure.

Well, PEP 246 should be edited, IMHO, to assert that all 'implicit'
adaptions are out-of-scope, and if they are supported should be done
so under the direct control of the application developer.

-- 
Clark C. Evans   

Re: [Python-Dev] Son of PEP 246, redux

2005-01-13 Thread Michael Walter
Ahhh, there we go, so "file" is type you declare. All I was asking
for, I thought you were thinking in a different/"more sophisticated"
direction (because what "f" actually wants is not a file, but a "thing
which has a read() like file" -- I thought one would like to manifest
that in the type instead of implicitely by the code). Your concept is
cool, tho :-)

Michael


On Thu, 13 Jan 2005 08:52:21 -0500, Phillip J. Eby
<[EMAIL PROTECTED]> wrote:
> At 10:18 PM 1/13/05 +1000, Nick Coghlan wrote:
> >Michael Walter wrote:
> >>Yepyep, but *how* you declare types now? Can you quickly type the function
> >>def f(x): x.read()? without needing an interface interface x_of_f: def
> >>read(): pass or a decorator like @foo(x.read)? I've no idea what you
> >>mean, really :o)
> >
> >Why would something like
> >
> >   def f(x):
> > x.read()
> >
> >do any type checking at all?
> 
> It wouldn't.  The idea is to make this:
> 
> def f(x:file):
> x.read()
> 
> automatically find a method declared '@implements(file.read,X)' where X is
> in x.__class__.__mro__ (or the equivalent of MRO if x.__class__ is classic).
> 
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> http://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: 
> http://mail.python.org/mailman/options/python-dev/michael.walter%40gmail.com
>
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Son of PEP 246, redux

2005-01-13 Thread Phillip J. Eby
At 08:50 AM 1/13/05 +0100, Alex Martelli wrote:
Your proposals are novel and interesting.  They also go WAY deeper into a 
critical reappraisal of the whole object model of Python, which has always 
been quite reasonably close to the above-mentioned "canon" and indeed has 
been getting _more_ so, rather than less, since 2.2 (albeit in a uniquely 
Pythonical way, as is Python's wont -- but not conceptually, nor, mostly, 
practically, all that VERY far from canonic OOP).
Actually, the whole generic function thing was just a way to break out of 
the typing problems the Python community has struggled with for 
years.  Every attempt to bring typing or interfaces to Python has run 
aground on simple, practical concepts like, "what is the abstract type of 
dict?  file?"

In essence, the answer is that Python's object model *already* has a 
concept of type...  duck typing!  Basically, I'm proposing a way to 
"formalize" duck typing...  when you say you want a 'file', then when you 
call the object's read method, it "reads like a file".

This isn't a critical reappraisal of Python's current object model at 
all!  It's a reappraisal of the ways we've been trying (and largely 
failing) to make it fit into the mold of other languages' object models.


 Moreover, your proposals are at a very early stage and no doubt need a 
lot more experience, discussion, maturation, and give-and-take.
Agreed.  In particular, operations on numeric types are the main area that 
needs conceptual work; most of the rest is implementation details.  I hope 
to spend some time prototyping an implementation this weekend (I start a 
new contract today, so I'll be busy with "real work" till then).

Nonetheless, the idea is so exciting I could barely sleep, and even as I 
woke this morning my head was spinning with comparisons of adaptation 
networks and operation networks, finding them isomorphic no matter what I 
tried.

One really exciting part is that this concept basically allows you to write 
"good" adapters, while making it very difficult or impossible to write 
"bad" ones!  Since it forces adapters to have no per-adapter state, it 
almost literally forces you to only create "as-a" adapters.  For example, 
if you try to define file operations on a string, you're dead in the water 
before you even start: strings have no place to *store* any state.  So, you 
can't adapt an immutable into a mutable.  You *can*, however, add extra 
state to a mutable, but it has to be per-object state, not per-adapter 
state.  (Coincidentally, this eliminates the need for PyProtocols' somewhat 
kludgy concept of "sticky" adapters.)

As a result of this, this adapter model is shaped like a superset of COM - 
you can adapt an object as many times as you like, and the adapters you get 
are basically "pointers to interfaces" on the same object, with no adapter 
composition.  And adapt(x,object) can always give you back the "original" 
object.

This model also has some potential to improve performance: adapter classes 
have all their methods in one dictionary, so there's no __mro__ scan, and 
they have no instance dictionary, so there's no __dict__ lookup.  This 
should mean faster lookups of methods that would otherwise be inherited, 
even without any special interpreter support.  And it also allows a 
possible fast-path opcode to be used for calling methods on a type-declared 
parameter or variable, possibly eventually streamlined to a vtable-like 
structure eliminating any dictionary lookups at all (except at function 
definition time, to bind names in the code object to vtable offsets 
obtained from the types being bound to the function signature).  But of 
course all that is much further down the road.

Anyway, I suppose the *really* exciting thing about all this is how *many* 
different problems the approach seems to address.  :)

(Like automatically detecting certain classes of Liskov violations, for 
example.  And not having to create adapter classes by hand.  And being able 
to support Ping's abstract operations.  Etc., etc., etc.)


So, I think the best course of action at this time might be for me to edit 
PEP 246 to reflect some of this enormously voluminous discussion, 
including points of contention (it's part of a PEP's job to also indicate 
points of dissent, after all); and I think you should get a new PEP number 
to use for your new ideas, and develop them on that separate PEP, say PEP 
XYZ.  Knowing that a rethink of the whole object-model and related canon 
is going on at the same time should help me keep PEP 246 reasonably 
minimal and spare, very much in the spirit of YAGNI -- as few features as 
possible, for now.
Sounds good to me.

If Guido, in consequence, decides to completely block 246's progress while 
waiting for the Copernican Revolution of your new PEP XYZ to mature, so be 
it -- his ``nose'' will no doubt be the best guide to him on the matter.
It's not that big of a revolution, really.  This should make Python *more* 
like Python,

Re: [Python-Dev] Son of PEP 246, redux

2005-01-13 Thread Phillip J. Eby
At 10:18 PM 1/13/05 +1000, Nick Coghlan wrote:
Michael Walter wrote:
Yepyep, but *how* you declare types now? Can you quickly type the function
def f(x): x.read()? without needing an interface interface x_of_f: def
read(): pass or a decorator like @foo(x.read)? I've no idea what you
mean, really :o)
Why would something like
  def f(x):
x.read()
do any type checking at all?
It wouldn't.  The idea is to make this:
   def f(x:file):
   x.read()
automatically find a method declared '@implements(file.read,X)' where X is 
in x.__class__.__mro__ (or the equivalent of MRO if x.__class__ is classic).

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Son of PEP 246, redux

2005-01-13 Thread Nick Coghlan
Michael Walter wrote:
Yepyep, but *how* you declare types now? Can you quickly type the function
def f(x): x.read()? without needing an interface interface x_of_f: def
read(): pass or a decorator like @foo(x.read)? I've no idea what you
mean, really :o)
Why would something like
  def f(x):
x.read()
do any type checking at all?
Cheers,
Nick.
--
Nick Coghlan   |   [EMAIL PROTECTED]   |   Brisbane, Australia
---
http://boredomandlaziness.skystorm.net
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 246, redux

2005-01-13 Thread Paul Moore
On Wed, 12 Jan 2005 21:50:14 -0600, Ian Bicking <[EMAIL PROTECTED]> wrote:
> Phillip J. Eby wrote:
> > At 04:07 PM 1/12/05 -0600, Ian Bicking wrote:
> >
> >> It also seems quite reasonable and unambiguous that a path object
> >> could be adapted to a IReadableFile by opening the file at the given
> >> path.
> >
> >
> > Not if you think of adaptation as an "as-a" relationship, like using a
> > screwdriver "as a" hammer (really an IPounderOfNails, or some such).  It
> > makes no sense to use a path "as a" readable file, so this particular
> > adaptation is bogus.
> 
> I started to realize that in a now-aborted reply to Steven, when my
> defense of the path->IReadableFile adaptation started making less sense.

I think I'm getting a clearer picture here (at last!)

One thing I feel is key is the fact that adaptation is a *tool*, and
as such will be used in different ways by different people. That is
not a bad thing, even if it does mean that some people will abuse the
tool.

Now, a lot of the talk has referred to "implicit" adaptation. I'm
still struggling to understand how that concept applies in practice,
beyond the case of adaptation chains - at some level, all adaptation
is "explicit", insofar as it is triggered by an adapt() call.

James Knight's example (which seemed to get lost in the discussion, or
at least no-one commented on it) brought up a new point for me, namely
the fact that it's the library writer who creates interfaces, and
calls adapt(), but it's the library *user* who says what classes
support (can be adapted to) what interface. I hadn't focused on the
different people involved before this point.

Now, if we have a transitive case A->B->C, where A is written by "the
user", and C is part of "the library" and library code calls
adapt(x,C) where x is a variable which the user supplies as an object
of type A, then WHO IS RESPONSIBLE FOR B And does it matter, and
if it does, then what are the differences?

As I write this, being careful *not* to talk interms of "interfaces"
and "classes", I start to see Philip's point - in my mind, A (written
by the user) is a class, and C (part of the library) is an
"interface". So the answer to the question above about B is that it
depends on whether B is an interface or a class - and the sensible
transitivity rules could easily (I don't have the experience to
decide) depend on whether B is a class or an interface.

BUT, and again, Philip has made this point, I can't reason about
interfaces in the context of PEP 246, because interfaces aren't
defined there. So PEP 246 can't make a clear statement about
transitivity, precisely because it doesn't define interfaces. But does
this harm PEP 246? I'm not sure.

>   It's *still* not intuitively incorrect to me, but there's a couple
> things I can think of...
> 
> (a) After you adapted the path to the file, and have a side-effect of
> opening a file, it's unclear who is responsible for closing it.
> (b) The file object clearly has state the path object doesn't have, like
> a file position.
> (c) You can't  go adapting the path object to a file whenever you
> wanted, because of those side effects.

In the context of my example above, I was assuming that C was an
"interface" (whatever that might be). Here, you're talking about
adapting to a file (a concrete class), which I find to be a much
muddier concept.

This is very much a "best practices" type of issue, though. I don't
see PEP 246 mandating that you *cannot* adapt to concrete classes, but
I can see that it's a dangerous thing to do.

Even the string->path adaptation could be considered suspect. Rather,
you "should" be defining an IPath *interface*, with operations such as
join, basename, and maybe open. Then, the path class would have a
trivial adaptation to IPath, and adapting a string to an IPath would
likely do so by constructing a path object from the string. From a
practical point of view, the IPath interface adds nothing over
adapting direct to the path class, but for the purposes of clarity,
documentation, separation of concepts, etc, I can see the value.

> So those are some more practical reasons that it *now* seems bad to me,
> but that wasn't my immediate intuition, and I could have happily written
> out all the necessary code without countering that intuition.  In fact,
> I've misused adaptation before (I think) though in different ways, and
> it those mistakes haven't particularly improved my intuition on the
> matter.  If you can't learn from mistakes, how can you learn?
> 
> One way is with principles and rules, even if they are flawed or
> incomplete.  Perhaps avoiding adaptation diamonds is one such rule; it
> may not be necessarily and absolutely a bad thing that there is a
> diamond, but it is often enough a sign of problems elsewhere that it may
> be best to internalize that belief anyway.  Avoiding diamonds alone
> isn't enough of a rule, but maybe it's a start.

Some mistakes are easier to avoid if you have the correct conceptual
framework

Re: [Python-Dev] PEP 246, redux

2005-01-13 Thread Alex Martelli
On 2005 Jan 12, at 21:42, Phillip J. Eby wrote:
   ...
Anyway, hopefully this post and the other one will be convincing that 
considering ambiguity to be an error *reinforces* the idea of I-to-I 
perfection, rather than undermining it.  (After all, if you've written 
a perfect one, and there's already one there, then either one of you 
is mistaken, or you are wasting your time writing one!)
I'd just like to point out, as apparently conceded in your "fair 
enough" sentence in another mail, that all of this talk of "wasting 
your time writing" is completely unfounded.  Since that "fair enough" 
of yours was deeply buried somewhere inside this huge conversation, 
some readers might miss the fact that your numerous repetitions of the 
similar concept in different words are just invalid, because, to recap:

Given four interfaces A, B, C, D, there may be need of each of the 
single steps A->B, A->C, B->D, C->D.  Writing each of these four 
adapters can IN NO WAY be considered "wasting your time writing one", 
because there is no way a set of just three out of the four can be used 
to produce the fourth one.

The only "redundancy" comes strictly because of transitivity being 
imposed automatically: at the moment the fourth one of these four 
needed adapters gets registered, there appear to be two same-length 
minimal paths A->x->D (x in {B, C}).  But inferring _from this 
consequence of transitivity_ that there's ANYTHING wrong with any of 
the four needed adapters is a big unwarranted logical jump -- IF one 
really trusted all interface->interface adapters to be perfect, as is 
needed to justify transitivity and as you here claims gets "reinforced" 
(?!).

Thinking of it as "redundancy" is further shown to be fallacious 
because the only solution, if each of those 4 adapters is necessary, is 
to write and register a FIFTH one, A->D directly, even if one has no 
interest whatsoever in A->D adaptation, just to shut up the error or 
warning (as you say, there may be some vague analogy to static typing 
here, albeit in a marginal corner of the stage rather than smack in the 
spotlight;-).

Yes, there is (lato sensu) "non-determinism" involved, just like in, 
say:
for k in d:
print k
for a Python dictionary d - depending on how d was constructed and 
modified during its lifetime (which may in turn depend on what order 
modules were imported, etc), this produces different outputs.  Such 
non-determinism may occasionally give some problems to unwary 
programmers (who could e.g. expect d1==d2 <--> repr(d1)==repr(d2) when 
keys and values have unique repr's: the right-pointing half of this 
implication doesn't hold, so using repr(d) to stand in for d when you 
need, e.g., a set of dictionaries, is not quite sufficient); such 
problems at the margin appear to be generally considered acceptable, 
though.

I seems to me that you do at least feel some unease at the whole 
arrangement, given that you say "this whole debate has made me even 
less enamored of adaptation", as it's not clear to me that any _other_ 
aspect of "this whole debate" was quite as problematic (e.g. issues 
such as "how to best get a special method from class rather than 
instance" -- while needing to be resolved for adaptation just as much 
as for copy.py etc -- hardly seem likely to have been the ones 
prompting you to go looking for "a cleaner, more intuitive way to do 
it" outside of the canonical, widespread approach to OOP).

Anyway -- I'm pointing out that what to put in a rewrite of PEP 246 as 
a result of all this is anything but obvious at this point, at least to 
me.

Alex
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: getting special from type, not instance (was Re: [Python-Dev] copy confusion)

2005-01-13 Thread Alex Martelli
On 2005 Jan 12, at 18:59, Guido van Rossum wrote:
   ...
[Alex]
Armin's fix was to change:
   ...
[And then proceeds to propose a new API to improve the situation]
I wonder if the following solution wouldn't be more useful (since less
code will have to be changed).
The descriptor for __getattr__ and other special attributes could
claim to be a "data descriptor" which means that it gets first pick
*even if there's also a matching entry in the instance __dict__*.
   ...
Normal methods are not data descriptors, so they can be overridden by
something in __dict__; but it makes some sense that for methods
implementing special operations like __getitem__ or __copy__, where
the instance __dict__ is already skipped when the operation is invoked
using its special syntax, it should also be skipped by explicit
attribute access (whether getattr(x, "__getitem__") or x.__getitem__
-- these are entirely equivalent).
A very nice idea for how to proceed in the future, and I think 
definitely the right solution for Python 2.5.  But maybe we need to 
think about a bugfix for 2.3/2.4, too.

We would need to introduce a new decorator so that classes overriding
these methods can also make those methods "data descriptors", and so
that users can define their own methods with this special behavior
(this would be needed for __copy__, probably).
I don't think this will cause any backwards compatibility problems --
since putting a __getitem__ in an instance __dict__ doesn't override
the x[y] syntax, it's unlikely that anybody would be using this.
...in new-style classes, yes.  And classic types and old-style classes 
would keep behaving the old-way (with per-instance override) so the bug 
that bit the effbot would disappear... in Python 2.5.  But the bug is 
there in 2.3 and 2.4, and it seems to me we should still find a fix 
that is applicable there, even though the fix won't need to get into 
the 2.5 head, just the 2.3 and 2.4 bugfix branches.

"Ordinary" methods will still be overridable.
PS. The term "data descriptor" now feels odd, perhaps we can say "hard
descriptors" instead. Hard descriptors have a __set__ method in
addition to a __get__ method (though the __set__ method may always
raise an exception, to implement a read-only attribute).
Good terminology point, and indeed explaining the ``data'' in "data 
descriptor" has always been a problem.  "Hard" or "Get-Set" descriptors 
or other terminology yet will make explanation easier; to pick the best 
terminology we should also think of the antonym, since ``non-data'' 
won't apply any more ("soft descriptors", "get-only descriptors", ...). 
 ``strong'' descriptors having a __set__, and ``weak'' ones not having 
it, is another possibility.

But back to the bugfix for copy.py (and I believe at least pprint.py 
too, though of course that's more marginal than copy.py!) in 2.3 and 
2.4: am I correct that this new descriptor idea is too big/invasive for 
ths bugfix, and thus we should still be considering localized changes 
(to copy.py and pprint.py) via a function copy._get_special (or 
whatever) in 2.3.5 and 2.4.1?

This small, local, minimally invasive change to copy.py would go well 
with the other one we need (as per my latest post with
Subject: 	Re: [Python-Dev] Re: copy confusion
	Date: 	2005 January 12 10:52:10 CET
) -- having the check for issubclass(cls, type) in copy.copy() just as 
we have it in copy.deepcopy() and for the same reason (which is a bit 
wider than the comment in copy.deepcopy about old versions of Boost 
might suggest).

Alex
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: getting special from type, not instance (was Re: [Python-Dev] copy confusion)

2005-01-13 Thread Armin Rigo
Hi Guido,

On Wed, Jan 12, 2005 at 09:59:13AM -0800, Guido van Rossum wrote:
> The descriptor for __getattr__ and other special attributes could
> claim to be a "data descriptor"

This has the nice effect that x[y] and x.__getitem__(y) would again be
equivalent, which looks good.

On the other hand, I fear that if there is a standard "metamethod" decorator
(named after Phillip's one), it will be misused.  Reading the documentation
will probably leave most programmers with the feeling "it's something magical
to put on methods with __ in their names", and it won't be long before someone
notices that you can put this decorator everywhere in your classes (because it
won't break most programs) and gain a tiny performance improvement.

I guess that a name-based hack in type_new() to turn all __*__() methods into
data descriptors would be even more obscure?

Finally, I wonder if turning all methods whatsoever into data descriptors
(ouch! don't hit!) would be justifiable by the feeling that it's often bad
style and confusing to override a method in an instance (as opposed to
defining a method in an instance when there is none on the class).  
(Supporting this claim: Psyco does this simplifying hypothesis for performance
reasons and I didn't see yet a bug report for this.)

In all cases, I'm +1 on seeing built-in method objects (PyMethodDescr_Type)  
become data descriptors ("classy descriptors?" :-).


Armin
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Son of PEP 246, redux

2005-01-13 Thread Michael Walter
On Thu, 13 Jan 2005 01:04:01 -0500, Phillip J. Eby
<[EMAIL PROTECTED]> wrote:
> At 12:01 AM 1/13/05 -0500, Michael Walter wrote:
> >What am I missing?
> 
> The fact that this is a type-declaration issue, and has nothing to do with
> *how* types are checked.
I was talking about how you declare such types, sir :] (see the
interface pseudo code sample -- maybe my reference to type inference
lead you to think the opposite.)

> In other words, compared to the previous state of things, this should
> actually require *fewer* interfaces to accomplish the same use cases, and
> it doesn't require Python to have a built-in notion of "interface", because
> the primitive notion is an operation, not an interface.
Yepyep, but *how* you declare types now? Can you quickly type the function
def f(x): x.read()? without needing an interface interface x_of_f: def
read(): pass or a decorator like @foo(x.read)? I've no idea what you
mean, really :o)

Michael
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Son of PEP 246, redux

2005-01-13 Thread Alex Martelli
On 2005 Jan 13, at 03:57, Phillip J. Eby wrote:
Okay, I'm really out of time now.  Hate to dump this in as a possible 
spoiler on PEP 246, because I was just as excited as Alex about the 
possibility of it going in.  But this whole debate has made me even 
less enamored of adaptation, and more interested in finding a cleaner, 
more intuitive way to do it.
Perfectly reasonable, of course.  Doubts about the class / inheritance 
/ interface / instance / method / ... "canon" as the OTW to do OOP are 
almost as old as that canon itself, and have evolved along the years, 
producing many interesting counterexamples and variations, and I fully 
share your interest in them.  Adaptation is rather ``ensconced'' in 
that canon, and the conceptual and practical issues of IS-A which 
pervade the canon are all reflected in the new ``(can be automatically 
adapted to be used) AS-A'' which adaptation introduces.  If adaptation 
cannot survive some vigorous critical appraisal, it's much better to 
air the issues now than later.

Your proposals are novel and interesting.  They also go WAY deeper into 
a critical reappraisal of the whole object model of Python, which has 
always been quite reasonably close to the above-mentioned "canon" and 
indeed has been getting _more_ so, rather than less, since 2.2 (albeit 
in a uniquely Pythonical way, as is Python's wont -- but not 
conceptually, nor, mostly, practically, all that VERY far from canonic 
OOP).  Moreover, your proposals are at a very early stage and no doubt 
need a lot more experience, discussion, maturation, and give-and-take.

Further, you have indicated that, far from _conflicting_ with PEP 246, 
your new ideas can grow alongside and on top of it -- if I read you 
correctly, you have prototyped some variations of them using PEP 246 
for implementation, you have some ideas of how 'adapt' could in turn be 
recast by using your new ideas as conceptual and practical foundations, 
etc, etc.

So, I think the best course of action at this time might be for me to 
edit PEP 246 to reflect some of this enormously voluminous discussion, 
including points of contention (it's part of a PEP's job to also 
indicate points of dissent, after all); and I think you should get a 
new PEP number to use for your new ideas, and develop them on that 
separate PEP, say PEP XYZ.  Knowing that a rethink of the whole 
object-model and related canon is going on at the same time should help 
me keep PEP 246 reasonably minimal and spare, very much in the spirit 
of YAGNI -- as few features as possible, for now.

If Guido, in consequence, decides to completely block 246's progress 
while waiting for the Copernican Revolution of your new PEP XYZ to 
mature, so be it -- his ``nose'' will no doubt be the best guide to him 
on the matter.  But I hope that, in the same pragmatic and minimalist 
spirit as his "stop the flames" Artima post -- proposing minimalistic 
interfaces and adaptation syntax as a starting point, while yet keeping 
as a background reflection the rich and complicated possibilities of 
parameterized types &c as discussed in his previous Artima entries -- 
he'll still give a minimalistic PEP 246 the go-ahead so that 
widespread, real-world experimentation with adaptation and his other 
proposals can proceed, and give many Pythonistas some practical 
experience which will make future discussions and developments much 
sounder-based and productive.

So, what do you think -- does this new plan of action sound reasonable 
to you?

Alex
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Re: PEP 246: LiskovViolation as a name

2005-01-13 Thread Alex Martelli
On 2005 Jan 13, at 02:18, Phillip J. Eby wrote:
At 05:54 PM 1/12/05 -0700, Steven Bethard wrote:
Not that my opinion counts for much =), but returning None does seem
much simpler to me.  I also haven't seen any arguments against this
route of handling protocol nonconformance...  Is there a particular
advantage to the exception-raising scheme?
Only if there's any objection to giving the 'object' type a default 
__conform__ method that returns 'self' if 
'isinstance(protocol,ClassTypes) and isinstance(self,protocol)'.
In the spirit of minimalism in which I propose to rewrite PEP 246 (as 
per my latest post: make a simple, noninvasive, unassuming PEP 246 
while new ``copernical revolution'' ideas which you proposed mature in 
another PEP), I'd rather not make a change to built-in ``object''  a 
prereq for PEP 246; so, I think the reference implementation should 
avoid assuming such changes, if it's at all possible to avoid them 
(while, no doubt, indicating the desirability of such changes for 
simplification and acceleration).

Incidentally, "get this specialmethod from the type (with specialcasing 
for classic classes &c)" is a primitive that PEP 246 needs as much as, 
say, copy.py needs it.  In the light of the recent discussions of how 
to fix copy.py etc, I'm unsure about what to assume there, in a rewrite 
of PEP 246: that getattr(obj, '__aspecial__', None) always does the 
right thing via special descriptors, that I must spell everything out, 
or, what else...?

If anybody has advice or feedback on these points, it will be welcome!
Alex
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com