Overloading operators for currying, a PEP309 suggestion

Stephen Horne intentionally at blank.co.uk
Wed Mar 12 05:45:04 EST 2003


On Wed, 12 Mar 2003 07:08:01 GMT, "Lenard Lindstrom"
<PEP308reply at telus.net> wrote:

>
>"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 see what you are saying, but to me the only one of your original
examples that seemed completely intuitive was '<<' - and that mainly
because I see it in the same sense as C++ stream insertion.

The '>>' looks like it should be removing something from the closure
(analogous with stream extraction).

The '|' version looks - well - I'm not sure, just not right.

Much of this is probably just the fact that you're re-using existing
operators, of course. My initial reaction to C++ stream insertion and
extraction operators was basically 'what - yuck!', but now I quite
like them.

>> 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?

The thought was...

  <function-name> [<param-selection>] = <value>

...for currying, without needing to save a result or use alternative
operators.

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

OK - I was a bit confused there.

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

I think this creates a problem.

  fn << 1              #  Curries left parameter with rvalue
  fn << { 2 : "x" }    #  Does not curry left parameter with rvalue -
                       #  treats rvalues type as special case.

In short, I think this is a potentially confusing inconsistency.

>>   <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>, ...)

Not sure - call syntax suggests calling to strongly, which we are not
doing. I though it would be better to choose a syntax which emphasizes
that no call is done - only manipulation of closure contents and
selection flags.

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

True

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

True, but not IMO important.

> Anyways, implementing value
>retrieval would require additional data be kept around if Python closures
>are used to save the argument values.

I didn't know that - I don't know how Python closures work, only what
the general principle behind closures is.

> How important is it?

Not important - which is why an awkward syntax didn't seem to be a
problem.

BTW - 'fn2["a"]' without a method for getting the value was rejected
because it already has the closure-manipulating meaning. It's a shame,
but - as already noted - I didn't think it was that important.

>> 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)

Yes, but - erm - well - I don't like it!

I don't think you should need to convert a normal function into a
curryable function - functions should be functions, whether they
support currying or not.





More information about the Python-list mailing list