comp.lang.python by Andrey Tatarinov about using where as a new keyword in the absence of anonymous functions gave me some ideas about how such a new keyword could be useful in rendering pythonic the addition of optional static typing. However, I do not use where in the same context as Tatarinov.
Python is often described as executable pseudo-code. Therefore, rather than explaining in words my ideas, I will let the code (examples taken from Python's BDFL blogs) speak for itself. Note that the amount of code versus type declarations is not really representative of real life in the following examples. I also deliberately did not add blank lines, which could have made this more readable.
1. Optional typing.
def gcd(a, b):
where:
a: int, b: int
return c where:
c: int
while a:
a, b = b%a, a
return b
2. Optional typing with pre- and post- conditions.
def gcd(a, b):
where:
a: int, b: int
a > 0, b > 0
return c where:
c: int
c > 0
c <= a and c <= b
while a:
a, b = b%a, a
return b
3. Interfaces
interface I:
def foo(x):
where:
x: int
x > 0
return r where:
r: str
class C(object; I): # derived from object; implements I
def foo(self, x):
return str(x)
4. More interfaces
interface I1(I2, I3):
def foo(a: t1, b: t2):
where:
a: t1, b: t2
return c where:
c: t3
class C(C1, C2; I1): # derived from C1, C2; implements I1
def foo(a, b):
return a+b
5. Formerly anonymous functions.
list_of_powers = [ powers(x) for x in my_list]:
def powers(x):
return (x, x*x, x*x*x)
6. Formerly anonymous functions with typing information
list_of_powers = [ powers(x) for x in my_list]:
def powers(x):
where:
x: int
return (a, b, c) where:
a: int, b: int, c: int
return (x, x*x, x*x*x)
7. Other optional typing style, meant to be equivalent to above
def type_safe_gcd(a, b):
where:
a: int, b: int
return c where:
c: int
def gcd(a, b):
where type_safe_gcd(a, b);
while a:
a, b = b%a, a
return b
If you "grok" the above, I have made my point. If not, feel free to comment!
Please note that Blogger keeps messing up with spacing; I tried to indent using 4 spaces everywhere but, when I "publish" the page, the indention gets messed-up.
ReplyDeleteA fabulous idea. I really like it!
ReplyDeleteIt's a great idea ..
ReplyDeleteit's the way to go !!
it has an optionnal form, and a powerful feature !
it's pythonic !
it's THE way !
I like it a lot. It lumps object type with other pre-conditions which makes it more flexible and empahsizes the "optional" part. I assume that you could specify pre-conditions without specifying type. Is that your intention?
ReplyDeleteOf course, one could have pre- and post- conditions without *optional* static typing. While I did not show any example of this in this post (nor on the following post) it is clearly allowed by this syntax.
ReplyDeleteYes for the idea, but:
ReplyDelete- you show only a way to specify signature variables.
All other locals seems not to be cared of.
Or perhaps,I assume you want to declare them all in your where stuff (!!)
- I can't see the interet of your anonymous functions.
What's the advantage of your example compared to
def powers(x):return x*x
mylist=[powers(x) for x....]
- for the sub-class, I'd rather mix classes and interfaces :
class C(C1,C2,I)
Since interface are already declared with a special statement, no need to differentiate them *again*
--OPQ
Rather than have to specify a new name "c" when you want to describe the return type, what about using the arrow notation? e.g.:
ReplyDeletedef gcd(a, b):
where:
a: int, b: int
gcd -> int
I realize that the arrow syntax would be new, but Guido used it in his writings on optional static typing.
Case 1 looks a lot like a transcript of what Psyco does behind the scenes. I'd also expect the transcript of a mythical type inference mechanism to look pretty similar. It's therefore quite a convenient notation, but possibly unnecessary as a language construct given a decent enough compiler infrastructure.
ReplyDeleteRegarding the comment about using gcd -> int to specify return value. Suppose I have a function that returns multiple parameters; I might want to be able to eventually do something like the following:
ReplyDeletereturn ((x, y, z), state, colour, fname) where:
x: float, y: float, z: float # final position
state: int # moving or at rest
colour: type(Colour) # user-defined
fname: str # temporary filename used to store data
(note: spacing information might be lost by blogger.com in above code.)
i.e. add additional information as required. Furthermore, in my opinion, the notation for type information should be the same whether it is for input or output.
I was just thinking how cool it'd be to have a keyword like this. Great minds...
ReplyDelete