Overloading operators for currying, a PEP309 suggestion

Lenard Lindstrom PEP308reply at telus.net
Wed Mar 12 02:08:01 EST 2003


"Stephen Horne" <intentionally at blank.co.uk> wrote in message
news:bmjr6vgc7efto3qqqfbmkri9u68l54k78c at 4ax.com...
>
> You may be onto something, but I'm not keen on your '|' version in
> particular.
>
I  chose the '|' bitwise or and '<<' left shift operators because of a
superficial simularity between currying a parameter list and manipulating a
string of bits. Doing an 'or' allows you to selectively set arguments; doing
a 'shift' allows you to remove arguments sequencially. However, there are
many operators to choose from.

> I would prefer defining the __len__, __getitem__, __setitem__ and
> __delitem__ methods to allow direct manipulation (and creation and
> deletion) of the closure. Though probably the function object should
> be immutable.
>
Yes, I think the curried function object should be immutable. This leaves
out __setitem__. But is it needed?

> How about...
>
>   <function-obj> [ <int> | <slice> ] -> <closure-item-ref>
>   <function-obj> . <keyword>         -> <closure-item-ref>
>...
or <function-obj> [ <int> | <slice> | <keyword> ]

Using my '<<' grammer, positional assignment might be done like this:

fn << {<posn>:<value>, ...}

eg:
    fn1 = fn << {1:'a'}  # the key is an integer posn rather than an arg.
name.

>...
>   <closure-item-ref> << <value>
>     Return a new function/closure with the selected fields from the
>     old one added or modified.
>
Maybe this is where __call__ comes in.
    <closure-item-ref>(<value>, ...)

In addition to the currying operators one can add a 'curry' method that
behaves like the curry function proposed for the functional module.

> That would mean, for a function...
>
>   def fn (a, b, c, d) :
>     pass
>
> ...you could write...
>
>   fn2 = fn [0] << "x"       #  Curry first parameter
>   fn2 = fn [-1] << "x"      #  Curry last parameter
>
    fn2 = fn[0]("x")
    fn2 = fn[-1]("x")

>   fn2 = fn.b << "x"         #  Curry keyword parameter
>
    fn2 = fn["b"]("x")

>   fn2 = fn [1:2] << (1, 2)  #  Curry a slice
>
    fn2 = fn[1:2](1, 2)

>...
>   fn2.a.value ()            #  Get value currently assigned to a
>
    fn2["a"].value ()
    fn2["a"]                 # Hmmm.
    fn2.getargval("a")     # ?

Having to use some method or property like 'value' is awkward. What other
ways are there? If an argument already has a value, this could be returned
instead of a <closure-item-ref>. Then a 'has_arg' method would be needed for
argument testing. This needs more thought. Anyways, implementing value
retrieval would require additional data be kept around if Python closures
are used to save the argument values. How important is it?

>...
> One advantage - it should be possible to write this as a library
> without any language changes. I think.
>
from functional import curryfunction

def fn(<args>):
    <body>
fn = curryfunction(fn)

At some point class 'function' will be rewritten to allow subclassing. At
that time curry operation methods could be added. At the very least the def
statement could be extended to provide a way to specify a function class
like the class statement and metaclasses. Then a subclass of 'function'
could define the curry operators.

Lenard Lindstrom
"<%s%s.%s>" % ("len-l.", 'telus', 'net')







More information about the Python-list mailing list