Friday, January 07, 2005

"where" keyword and Python as pseudo-code

There has been much discussion lately about what is now a series of blogs by Guido van Rossum (see Optional Static Typing -- Stop the Flames! for the latest discussion) about optional static typing in Python and related extensions to the language. A recent post
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!


10 comments:

  1. 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.

    ReplyDelete
  2. Anonymous1:34 AM

    A fabulous idea. I really like it!

    ReplyDelete
  3. Anonymous7:07 AM

    It's a great idea ..
    it's the way to go !!
    it has an optionnal form, and a powerful feature !
    it's pythonic !
    it's THE way !

    ReplyDelete
  4. Anonymous7:34 AM

    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?

    ReplyDelete
  5. Of 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.

    ReplyDelete
  6. Anonymous11:57 AM

    Yes for the idea, but:

    - 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

    ReplyDelete
  7. 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.:

    def 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.

    ReplyDelete
  8. Anonymous12:32 PM

    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.

    ReplyDelete
  9. Regarding 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:

    return ((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.

    ReplyDelete
  10. Anonymous1:44 AM

    I was just thinking how cool it'd be to have a keyword like this. Great minds...

    ReplyDelete

Spammers: none shall pass.

Note: Only a member of this blog may post a comment.