From 4bcd0fb27d82f73b2cdfe5bbd5a5d99d32869ea6 Mon Sep 17 00:00:00 2001 From: maxicot Date: Sat, 25 Oct 2025 15:31:10 +0300 Subject: [PATCH 1/3] Implement currying --- currying/__init__.py | 1 + currying/src/__init__.py | 1 + currying/src/lib.py | 20 ++++++++++++++++++++ currying/tests/__init__.py | 1 + currying/tests/test.py | 34 ++++++++++++++++++++++++++++++++++ 5 files changed, 57 insertions(+) create mode 100644 currying/__init__.py create mode 100644 currying/src/__init__.py create mode 100644 currying/src/lib.py create mode 100644 currying/tests/__init__.py create mode 100644 currying/tests/test.py diff --git a/currying/__init__.py b/currying/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/currying/__init__.py @@ -0,0 +1 @@ + diff --git a/currying/src/__init__.py b/currying/src/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/currying/src/__init__.py @@ -0,0 +1 @@ + diff --git a/currying/src/lib.py b/currying/src/lib.py new file mode 100644 index 0000000..c1c487b --- /dev/null +++ b/currying/src/lib.py @@ -0,0 +1,20 @@ +# Curry a given function. +# If the definition uses *args, specify the amount given in a specific case +def curry(f: callable, arity=None): + if arity is None: + arity = f.__code__.co_argcount + elif arity < 0: + raise Exception("negative arity") + elif arity < f.__code__.co_argcount: + raise Exception("specified arity is lesser than required") + + if arity == 0: + return lambda: f() + + def inner(*args): + if len(args) >= arity: + return f(*args) + + return lambda arg: inner(*args, arg) + + return lambda arg: inner(arg) diff --git a/currying/tests/__init__.py b/currying/tests/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/currying/tests/__init__.py @@ -0,0 +1 @@ + diff --git a/currying/tests/test.py b/currying/tests/test.py new file mode 100644 index 0000000..8643e8b --- /dev/null +++ b/currying/tests/test.py @@ -0,0 +1,34 @@ +from ..src.lib import curry +import pytest + + +def add_args(*args): + return sum(args) + + +def add2(a, b): + return a + b + + +def test_specified(): + assert curry(add_args, 3)(1)(2)(3) == 6 + + +def test_negative(): + with pytest.raises(Exception) as e: + curry(add2, -1) + assert e == "negative arity" + + +def test_less(): + with pytest.raises(Exception) as e: + curry(add2, 1) + assert e == "specified arity is lesser than required" + + +def test_unspecified(): + assert curry(add2)(1)(2) == 3 + + +def test_zero(): + assert curry(add_args, 0)() == 0 From 05104571d677ba56678720a28782f53173c8e992 Mon Sep 17 00:00:00 2001 From: maxicot Date: Sat, 25 Oct 2025 15:33:24 +0300 Subject: [PATCH 2/3] Reformat imports --- currying/tests/test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/currying/tests/test.py b/currying/tests/test.py index 8643e8b..0dfe42d 100644 --- a/currying/tests/test.py +++ b/currying/tests/test.py @@ -1,6 +1,7 @@ -from ..src.lib import curry import pytest +from ..src.lib import curry + def add_args(*args): return sum(args) From a6c162adc4ec75d85af93af07bc83099a86151ac Mon Sep 17 00:00:00 2001 From: maxicot Date: Sat, 25 Oct 2025 15:44:50 +0300 Subject: [PATCH 3/3] Implement uncurrying --- currying/src/lib.py | 16 ++++++++++++++++ currying/tests/test.py | 12 +++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/currying/src/lib.py b/currying/src/lib.py index c1c487b..b28e50a 100644 --- a/currying/src/lib.py +++ b/currying/src/lib.py @@ -18,3 +18,19 @@ def inner(*args): return lambda arg: inner(*args, arg) return lambda arg: inner(arg) + + +# Uncurry a curried function +def uncurry(f: callable): + def inner(*args): + value = f + + for arg in args: + try: + value = value(arg) + except Exception: + raise Exception("incorrect amount of arguments provided") + + return value + + return inner diff --git a/currying/tests/test.py b/currying/tests/test.py index 0dfe42d..97c1a1d 100644 --- a/currying/tests/test.py +++ b/currying/tests/test.py @@ -1,6 +1,6 @@ import pytest -from ..src.lib import curry +from ..src.lib import curry, uncurry def add_args(*args): @@ -33,3 +33,13 @@ def test_unspecified(): def test_zero(): assert curry(add_args, 0)() == 0 + + +def test_uncurry(): + assert uncurry(curry(add2))(1, 2) == 3 + + +def test_uncurry_incorrect(): + with pytest.raises(Exception) as e: + uncurry(curry(add2))(1, 2, 3) + assert e == "incorrect amount of arguments provided"