|
Re: Roeland Rengelink
|
Posted: Jan 9, 2005 7:35 AM
|
|
> > Suppose that, as a user, I want to sort the result of > > f , and that f returns a sequence. I now > > have to write: > > > > x = f() > > x = adapt(x, list) # or adapt(x, sortable)? > > x.sort() > >
> > This wouldn't be necessary if f just said that it > > returned a list. > > Actually, 'x = sorted(f())' should work just fine, since > 'sorted()' takes an iterable now. >
s/sort/append
> Even if sorted didn't exist, it would suffice to say > 'x=list(f()); x.sort()' anyway. >
Ahh, but that's my point. This would be a bad solution if f() did return a list, because then list(f()) is an unnecessary (potentially expensive) operation. So, you'd have to use adapt(f(), list), which just returns the result of f() if f() did indeed produce a list.
> > > My point would be that the default 'user' of an > > interface is someone who uses a concrete > > implementation, not someone who writes a concrete > > implementation. And the interface > > should cater to the default user. I must admit that in > > the case of frameworks, this may actually be the other > > way around. > > Both kinds of user occur quite a bit, but for a framework > one of the big reasons for having an interface is to > document what the framework expects of an implementation > created by the user. IOW, the user of an interface is > quite frequently the author of a concrete implementation. >
Let's make this distinction:
- The default user of a library is someone who would call f
- The default user of a framework is someone who would implement f
I.e., libraries and frameworks are distinguished by the way in which a user would use the interface.
I wrote my original comment as a library user. And I do think that a library interface shouldn't be vague about what it returns. Moreover, even if the library is not vague about what it returns, as a reader of library code, I wouldn't like to see something like:
def f()->list: return ()
that return an empty list due to the adapatation magic. Hence, my only suggestion to Guido was to remove the adaptation step on the return value and replace it with an assertion
Note that when I write 'list' as the return type, I mean the list interface (List?), i.e.: an interface with 1 concrete implementation (possibly sub-classed).
I'm thinking of a new built-in conforms(obj, interface) , where conforms(x, T) returns True iff adapt(x, T) would return x . And my suggestion would be to replace
def f(x:T1, y:T2)-> T2:
with
def f(x, t): x=adapt(x, T1) y=adapt(x, T2) r = f__(x, y) assert conforms(r, T3) return r
This would still allow one to write
def f()->sequence: return ()
but wouldn't allow:
def f()->List: return ()
This doen't hurt the framework writers, but keeps the library writers honest.
> > > Probably because I think of the interface definition > > first as a promise by the original implementor, not as > > a requirement on the writer of a conforming > > implementation. > > It's both. You can't really have an agreement unless both > sides agree; this is what "programming by contract" means. > :) >
But it's library writers and framework writers who have to agree with their respective users. They don't necessarily have to agree with each other (except about the implementation of Guido's wrapper)
|
|