problem with curring in python
Terry Reedy
tjreedy at udel.edu
Tue Oct 22 06:02:29 EDT 2019
On 10/22/2019 4:58 AM, Antoon Pardon wrote:
> Using python 3.5
>
> I have been experimenting with curried functions. A bit like in Haskell.
> So I can write the following function:
>
> def sum4(a, b, c, d):
> return a + b + c + d
>
> summing = curry(sum4)
>
> print summing(1)(2)(3)(4) # this prints 10.
>
> The problem is I need the signature of the original function in order to
> know when to finally call the function and return the actual result.
> However buildin functions don't have a
I believe most do.
>>> help(abs)
Help on built-in function abs in module builtins:
abs(x, /)
Return the absolute value of the argument.
>>> abs.__text_signature__
'($module, x, /)'
>>> import inspect
>>> inspect.signature(abs)
<Signature (x, /)>
The exceptions are those with complicated signatures still given in
multiple lines in the docstring since the true signature would be too
complicated for humans to digest. Example:
>>> help(bytes)
Help on class bytes in module builtins:
class bytes(object)
| bytes(iterable_of_ints) -> bytes
| bytes(string, encoding[, errors]) -> bytes
| bytes(bytes_or_buffer) -> immutable copy of bytes_or_buffer
| bytes(int) -> bytes object of size given by the parameter
initialized with null bytes
| bytes() -> empty bytes object
The latter 5 lines are from bytes.__doc__. signature(bytes) raises
ValueError. Note that parameter 1 is the union of 4 types, 3
iterable_of_ints, bytes_or_buffer, int, and string (str_or_bytes), 2 of
which are unions themselves and 2 of which are non-disjoint.
Furthermore, the presence of 1 or 2 more args is only valid if the 1st
arg is a string. The concept of currying does not really apply to this
situation very well.
In other words, the cases without signatures should probably not be curried.
> signature. Here below is my
> current experimental implementation. Any ideas for an other approach?
>
> def curry(func, *args):
> arg_len = len(signature(func).parameters)
> if arg_len <= len(args):
> return func(*args)
> else:
> return CurryType(func, arg_len, args)
>
> class CurryType:
> def __init__(self, func, arg_len, args):
> self.func = func
> self.arg_len = arg_len
> self.args = list(args)
>
> def __call__(self, *args):
> args = self.args + list(args)
> if self.arg_len <= len(args):
> return self.func(*args)
> else:
> return CurryType(self.func, self.arg_len, args)
--
Terry Jan Reedy
More information about the Python-list
mailing list