Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ isinstance(clone, Obj) # True
- [ ] cond
- [ ] construct
- [ ] constructN
- [ ] converge
- [x] converge
- [ ] count
- [x] 0.1.2 countBy
- [x] 0.1.2 curry
Expand Down Expand Up @@ -236,7 +236,7 @@ R.isEmpty(None) # False

- [ ] isNil
- [x] 0.1.2 join
- [ ] juxt
- [x] juxt
- [x] 0.1.2 keys

```python
Expand Down Expand Up @@ -373,7 +373,7 @@ R.omit(['v1', 'v3'], obj) # {'v2': 2}
- [ ] partial
- [ ] partialObject
- [ ] partialRight
- [ ] partition
- [x] partition
- [x] 0.1.2 path
- [ ] pathEq
- [ ] pathOr
Expand Down
3 changes: 3 additions & 0 deletions ramda/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from .comparator import comparator
from .compose import compose
from .concat import concat
from .converge import converge
from .countBy import countBy
from .curry import curry
from .curryN import curryN
Expand Down Expand Up @@ -40,6 +41,7 @@
from .invoker import invoker
from .isEmpty import isEmpty
from .join import join
from .juxt import juxt
from .keys import keys
from .last import last
from .lastIndexOf import lastIndexOf
Expand All @@ -57,6 +59,7 @@
from .omit import omit
from .once import once
from .Or import Or
from .partition import partition
from .path import path
from .paths import paths
from .pick import pick
Expand Down
17 changes: 17 additions & 0 deletions ramda/converge.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from .curryN import curryN
from .Max import Max
from .private._curry2 import _curry2
from .private._inspect import funcArgsLength, getArgsToUse
from .private._map import _map
from .reduce import reduce


def inner_converge(after, fns):
def wrapper(*args):
return after(*_map(lambda fn: fn(*getArgsToUse(fn, args)), fns))
arity = reduce(Max, 0, _map(funcArgsLength, fns))
return curryN(arity, wrapper)


converge = _curry2(inner_converge)
converge.__name__ = 'converge'
2 changes: 1 addition & 1 deletion ramda/curry.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

from .curryN import curryN
from .private._curry1 import _curry1
from .private._helper import funcArgsLength
from .private._inspect import funcArgsLength

curry = _curry1(lambda fn: curryN(funcArgsLength(fn), fn))
3 changes: 1 addition & 2 deletions ramda/curryN.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from .private._arity import _arity
from .private._curry1 import _curry1
from .private._curry2 import _curry2
from .private._curryN import _curryN

curryN = _curry2(lambda n, fn: _curry1(fn) if n == 1 else _arity(n, _curryN(n, [], fn)))
curryN = _curry2(lambda n, fn: _arity(n, _curryN(n, [], fn)))
2 changes: 2 additions & 0 deletions ramda/filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
def inner_filter(pred, filterable):
if _isArrayLike(filterable):
return _filter(pred, filterable)

def inner_reduce(acc, key):
"""
There are 2 cases of filterable
Expand All @@ -33,3 +34,4 @@ def inner_reduce(acc, key):

# pylint: disable=redefined-builtin
filter = _curry2(_dispatchable(['fantasy-land/filter', 'filter'], _xfilter, inner_filter))
filter.__name__ = 'filter'
2 changes: 1 addition & 1 deletion ramda/flip.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from .curryN import curryN
from .private._curry1 import _curry1
from .private._helper import funcArgsLength
from .private._inspect import funcArgsLength


def inner_flip(fn):
Expand Down
1 change: 1 addition & 0 deletions ramda/isEmpty.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ def inner_isEmpty(x):


isEmpty = _curry1(inner_isEmpty)
isEmpty.__name__ = 'isEmpty'
5 changes: 5 additions & 0 deletions ramda/juxt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .converge import converge
from .private._curry1 import _curry1

juxt = _curry1(lambda fns: converge(lambda *args: list(args), fns))
juxt.__name__ = 'juxt'
2 changes: 1 addition & 1 deletion ramda/map.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from .private._curry2 import _curry2
from .private._dispatchable import _dispatchable
from .private._has import _has
from .private._helper import funcArgsLength
from .private._inspect import funcArgsLength
from .private._isFunction import _isFunction
from .private._map import _map
from .private._reduce import _reduce
Expand Down
2 changes: 1 addition & 1 deletion ramda/once.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from .private._arity import _arity
from .private._curry1 import _curry1
from .private._helper import funcArgsLength
from .private._inspect import funcArgsLength


def inner_once(fn):
Expand Down
6 changes: 6 additions & 0 deletions ramda/partition.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from .filter import filter
from .juxt import juxt
from .reject import reject

partition = juxt([filter, reject])
partition.__name__ = 'partition'
2 changes: 1 addition & 1 deletion ramda/pipe.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from .private._arity import _arity
from .private._helper import funcArgsLength
from .private._inspect import funcArgsLength
from .private._pipe import _pipe
from .reduce import reduce
from .tail import tail
Expand Down
2 changes: 1 addition & 1 deletion ramda/private/_curry1.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ def _curry1(fn):
def f1(a=__, *_):
if _isPlaceholder(a):
return f1
return fn(a, *_)
return fn(a)
return f1
6 changes: 4 additions & 2 deletions ramda/private/_curry2.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ def _curry2(fn):
# pylint: disable=dangerous-default-value
# pylint: disable=keyword-arg-before-vararg
def f2(a=__, b=__, *_):
def f_b(_b): return fn(a, _b)
def f_b(_b):
return fn(a, _b)
if _isPlaceholder(a) and _isPlaceholder(b):
return f2
if _isPlaceholder(a):
def f_a(_a): return fn(_a, b)
def f_a(_a):
return fn(_a, b)
return _curry1(f_a)
if _isPlaceholder(b):
return _curry1(f_b)
Expand Down
3 changes: 2 additions & 1 deletion ramda/private/_curryN.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from ._arity import _arity
from ._inspect import getArgsToUse
from ._isPlaceholder import _isPlaceholder


Expand All @@ -20,6 +21,6 @@ def f1(*arguments):
left -= 1
combinedIdx += 1
if left <= 0:
return fn(*combined)
return fn(*getArgsToUse(fn, combined))
return _arity(left, _curryN(n, combined, fn))
return f1
9 changes: 1 addition & 8 deletions ramda/private/_helper.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@

from ._has import _has
from ._isArrayLike import _isArrayLike


def funcArgsLength(fn):
"""
Get the number of args for function fn
Not count *args and **kwargs
"""
return fn.__code__.co_argcount


def toNumber(a):
"""
Convert any input a to a number type
Expand Down
26 changes: 26 additions & 0 deletions ramda/private/_inspect.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

from inspect import getfullargspec

from ._isPlaceholder import _isPlaceholder


def funcArgsLength(fn):
"""
Get the number of args for function fn
Not count *args and **kwargs
"""
return fn.__code__.co_argcount


def getArgsToUse(fn, args):
"""
Get args to use for fn
"""
if getfullargspec(fn).varargs:
# we can not determine the number of args if varargs exists
return args
argsToUse = []
for i in range(funcArgsLength(fn)):
if not _isPlaceholder(args[i]):
argsToUse.append(args[i])
return argsToUse
1 change: 1 addition & 0 deletions ramda/reject.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
from .private._curry2 import _curry2

reject = _curry2(lambda pred, filterable: filter(_complement(pred), filterable))
reject.__name__ = 'reject'
5 changes: 4 additions & 1 deletion test/private/test__curry1.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import ramda as R
from ramda.private._curry1 import _curry1
from ramda.private._helper import funcArgsLength
from ramda.private._inspect import funcArgsLength


def f(a): return [a]
Expand All @@ -22,6 +22,9 @@ def test_supports_placeholder(self):
def test_has_1_arity(self):
self.assertEqual(1, funcArgsLength(g))

def test_works_even_more_args_provided(self):
self.assertEqual([1], g(1, 2, 3))


if __name__ == '__main__':
unittest.main()
5 changes: 4 additions & 1 deletion test/private/test__curry2.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import ramda as R
from ramda.private._curry2 import _curry2
from ramda.private._helper import funcArgsLength
from ramda.private._inspect import funcArgsLength

"""
https://github.com/ramda/ramda/blob/master/test/internal/_curry2.js
Expand Down Expand Up @@ -33,6 +33,9 @@ def test_supports_placeholder(self):
def test_has_2_arity(self):
self.assertEqual(2, funcArgsLength(g))

def test_works_even_more_args_provided(self):
self.assertEqual([1, 2], g(1, 2, 3))


if __name__ == '__main__':
unittest.main()
9 changes: 8 additions & 1 deletion test/private/test__curry3.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,19 @@

import ramda as R
from ramda.private._curry3 import _curry3
from ramda.private._helper import funcArgsLength
from ramda.private._inspect import funcArgsLength

"""
https://github.com/ramda/ramda/blob/master/test/internal/_curry3.js
"""


def f(a, b, c): return [a, b, c]


g = _curry3(f)


class Test_Curry3(unittest.TestCase):
def test_supports_placeholder(self):
_ = R.__
Expand Down Expand Up @@ -43,6 +47,9 @@ def test_supports_placeholder(self):
def test_has_3_arity(self):
self.assertEqual(3, funcArgsLength(g))

def test_works_even_more_args_provided(self):
self.assertEqual([1, 2, 3], g(1, 2, 3, 4))


if __name__ == '__main__':
unittest.main()
2 changes: 1 addition & 1 deletion test/test_compose.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import unittest

import ramda as R
from ramda.private._helper import funcArgsLength
from ramda.private._inspect import funcArgsLength

"""
https://github.com/ramda/ramda/blob/master/test/compose.js
Expand Down
46 changes: 46 additions & 0 deletions test/test_converge.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@

import unittest

import ramda as R
from ramda.private._inspect import funcArgsLength

"""
https://github.com/ramda/ramda/blob/master/test/converge.js
"""

f1 = R.converge(R.multiply, [R.identity, R.identity])
f2 = R.converge(R.multiply, [R.identity, lambda a, b: b])
f3 = R.converge(R.multiply, [R.identity, lambda a, b, c: c])


class TestConverge(unittest.TestCase):
def test_passes_the_results_of_applying_the_arguments_individually_to_two_separate_functions_into_a_single_one(self):
self.assertEqual(15, R.converge(R.multiply, [R.add(1), R.add(3)])(2))

def test_returns_a_function_with_the_length_of_the_longest_argument(self):
self.assertEqual(1, funcArgsLength(f1))
self.assertEqual(2, funcArgsLength(f2))
self.assertEqual(3, funcArgsLength(f3))

def test_returns_a_curried_function(self):
self.assertEqual(42, f2(6)(7))
self.assertEqual(3, funcArgsLength(f3(R.__)))

def test_works_with_empty_functions_list(self):
fn = R.converge(lambda *args: len(args), [])
self.assertEqual(0, funcArgsLength(fn))
self.assertEqual(0, fn())

def test_works_with_functions_with_different_number_of_arguments(self):
fn = R.converge(R.multiply, [R.add, R.add(1)])
self.assertEqual(6, fn(1)(2)) # curried
self.assertEqual(6, fn(1, 2))
self.assertEqual(6, fn(1)(R.__)(2))
self.assertEqual(9, fn(R.__, 1)(2))
self.assertEqual(6, fn(R.__, R.__)(1, 2))
self.assertEqual(6, fn(1, R.__)(2))
self.assertEqual(6, fn(1, 2, 3)) # works even more arguments provided


if __name__ == '__main__':
unittest.main()
6 changes: 6 additions & 0 deletions test/test_curry.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@ def f(a, b, c, *args):
self.assertEqual([1, 2, 3, 4], g(1)(2, 3, 4))
self.assertEqual([1, 2, 3, 4], g(1)(2)(3, 4))

def test_works_even_more_args_provided(self):
def f(a, b):
return [a, b]
g = R.curry(f)
self.assertEqual([1, 2], g(1, 2, 3))


if __name__ == '__main__':
unittest.main()
Loading