Skip to main content

A small clone of ramda

Project description

python_ramda

This is a repo try to copy https://github.com/ramda/ramda in python.

linting: pylint PyPI version Python Versions codecov

install

For whom wants to use this package.

> pip install python-ramda
> pip install python-ramda -U # get the latest

Usage

>>> from ramda import curry
>>> def sum(a, b, c): return a + b + c
>>> curry(sum)(1)(2, 3)
6
>>> import ramda as R # similar to ramda syntax
>>> def sum(a, b, c): return a + b + c
>>> R.curry(sum)(1)(2, 3)
6

Doc

Because the usage of python_ramda is almostly same to ramda, so we don't create any extra doc.

If you feel any behaviour is different from what is should be in ramda, please check below CheckList for more details.

Contribute

For whom wants to contribute to this repo.

$ pip install -U pylint
# see: https://pre-commit.com/ for more details
$ pre-commit install # please install hooks first

Checkout new branch from main branch directly and create PR.

CheckList

Functions supported now.

  • 0.1.2 __
  • 0.1.2 add
# different from ramda
R.add(None, None) # float('nan)
R.add(date(1,2,3), date(1,2,3)) # float('nan)
  • addIndex
  • 0.1.2 adjust
  • 0.1.2 all
    • Transducer part is not fully tested.
  • allPass
  • 0.1.2 always
  • 0.1.2 And (and is a keyword in python)
  • andThen
  • 0.1.2 any
  • anyPass
  • ap
  • aperture
  • 0.1.2 append
  • apply
  • applySpec
  • applyTo
  • ascend
  • assoc
  • assocPath
  • 0.2.0 binary
  • bind
  • both
  • call
  • chain
  • clamp
  • 0.1.2 clone

we are simply using python copy module So with no specific reason, we suggest you to use python origin copy module as your first choice.

class Obj:
  def __init__(self, x):
    self.value = x
obj = Obj(42)
clone = R.clone(obj)
obj == clone # False, obj and clone have different references
isinstance(clone, Obj) # True

class Obj:
  def __init__(self, x):
    self.value = x

  def __eq__(self, other):
    return self.value == other.value
obj = Obj(42)
clone = R.clone(obj)
obj == clone # True, if Obj override __eq__ function
isinstance(clone, Obj) # True
  • collectBy
  • 0.1.2 comparator
  • complement
  • 0.1.2 compose
  • composeWith
  • 0.1.2 concat
  • cond
  • construct
  • constructN
  • 0.1.4 converge
  • count
  • 0.1.2 countBy
  • 0.1.2 curry
  • 0.1.2 curryN
  • dec
  • defaultTo
  • descend
  • 0.1.2 difference
  • 0.1.2 differenceWith
  • dissoc
  • dissocPath
  • 0.1.2 divide
  • 0.1.2 drop
  • dropLast
  • dropLastWhile
  • dropRepeats
  • dropRepeatsWith
  • dropWhile
  • either
  • 0.1.2 empty
# We don't support empty object in python
class Obj:
  def __init__(self, value):
    self.value = value
o = Obj(42)
o == R.empty(o) # True, we will return the original cloned object

What we support for now:

  1. dict()
  2. set()
  3. list()
  4. str()
  5. any instance with empty() method
  6. any instance with 'fantasy-land/empty' property
  • endsWith
  • eqBy
  • 0.1.2 eqProps
# works for both dict and object
class Obj:
  def __init__(self, v):
    self.v = v
obj1 = Obj(1)
obj2 = Obj(1)
R.eqProps('v', obj1, obj2) # True
R.eqProps('v', {'v': 1}, {'v': 1}) # True
  • 0.1.2 equals
R.equals(float('nan'), float('nan')) # True
  • evolve
  • 0.1.2 F
  • 0.1.2 filter
  • 0.1.2 find
  • 0.1.4 findIndex
  • 0.1.4 findLast
  • 0.1.4 findLastIndex
  • 0.1.2 flatten
  • 0.1.2 flip
  • 0.1.4 forEach
  • forEachObjIndexed
  • fromPairs
  • 0.1.2 groupBy
  • groupWith
  • 0.1.2 gt
  • 0.1.2 gte
  • has
  • hasIn
  • hasPath
  • 0.1.2 head
  • identical
  • 0.1.2 identity
  • ifElse
  • inc
  • includes
  • indexBy
  • 0.1.2 indexOf
  • init
  • innerJoin
  • insert
  • insertAll
  • 0.1.2 intersection
  • intersperse
  • 0.1.2 into
  • invert
  • invertObj
  • 0.1.2 invoker
  • is
  • 0.1.2 isEmpty
class Obj:
  pass
# Any custom object will be treated as non-empty
R.isEmpty(Obj()) # False
R.isEmpty(None) # False
  • isNil
  • 0.1.2 join
  • 0.1.4 juxt
  • 0.1.2 keys
# When using R.keys(obj) and obj is a class instance, we use obj.__dict__ as keys.
class A:
  c = 'not included'
  def __init__(self):
    self.a = 1
    self.b = 2
a = A()
R.keys(a) # ['a', 'b']
# keys include super class attributes
class A:
  def __init__(self, a):
    self.a = a

class B(A):
  def __init__(self, a, b):
    super().__init__(a)
    self.b = b

class C(A):
  def __init__(self, c):
    self.c = c

a = A(1)
b = B(2, 3)
c = C(4)
R.keys(a) # ['a']
R.keys(b) # ['a', 'b']
R.keys(c) # ['c'], because c does not call super().__init__()

# For normal dict
R.keys({'a': 1, 'b': 2}) # ['a', 'b']
  • 0.2.0 keysIn

Different from keys, keysIn will return all attributes of the object, including super class attributes and class static variables.

class A:
  a_static = 1
  def __init__(self):
    self.a = 1
class B(A):
  b_static = 2
  def __init__(self, b):
    super().__init__()
    self.b = b

R.keysIn(A()) # ['a_static', 'a']
R.keysIn(B(2)) # ['a_static', 'a', 'b_static', 'b']

# For normal dict
R.keysIn({'a': 1, 'b': 2}) # ['a', 'b']
  • 0.1.4 last
  • 0.1.2 lastIndexOf
  • length
  • lens
  • lensIndex
  • lensPath
  • lensProp
  • lift
  • liftN
  • 0.1.2 lt
  • 0.1.2 lte
  • 0.1.2 map
  • mapAccum
  • mapAccumRight
  • mapObjIndexed
  • 0.1.2 match
  • mathMod
  • 0.1.2 Max (max is a keyword in python)

If R.Max(a, b) a and b are with different types, we will compare with str(a) and str(b).

R.Max('A', None) # None, 'A' < 'None'
  • maxBy
  • mean
  • median
  • memoizeWith
  • mergeAll
  • mergeDeepLeft
  • mergeDeepRight
  • mergeDeepWith
  • mergeDeepWithKey
  • mergeLeft
  • mergeRight
  • mergeWith
  • mergeWithKey
  • 0.1.2 Min (min is a keyword in python)

If R.Min(a, b) a and b are with different types, we will compare with str(a) and str(b).

R.Min('A', None) # 'A', 'A' < 'None'
  • minBy
  • modify
  • modifyPath
  • 0.1.4 modulo

Python modulo on negative numbers has different behavior than JS.

5 % -3 # -1
5 % -3 // 2
  • move
  • 0.1.2 multiply
  • 0.2.0 nAry
  • negate
  • none
  • 0.1.2 not
  • 0.1.2 nth
  • nthArg
  • o
  • 0.1.2 objOf
  • of
  • 0.1.2 omit

we support both dict type and object type.

class Obj:
  def __init__(self, v1, v2):
    self.v1 = v1
    self.v2 = v2
obj = Obj(1, 2)
R.omit(['v1'], obj) # {'v2': 2}
R.omit(['v1', 'v3'], obj) # {'v2': 2}
  • on
  • 0.1.2 once
  • 0.1.2 or
  • otherwise
  • over
  • pair
  • partial
  • partialObject
  • partialRight
  • 0.1.4 partition
  • 0.1.2 path
  • pathEq
  • pathOr
  • 0.1.2 paths
  • pathSatisfies
  • 0.1.2 pick
  • 0.1.2 pickAll

both pick and pickAll support both dict and object type.

class Obj:
  def __init__(self, v1, v2):
    self.v1 = v1
    self.v2 = v2
obj = Obj(1, 2)
R.pick(['v1'], obj) # {'v1': 1}
R.pickAll(['v1', 'v3'], obj) # {'v1': 1, 'v3': None}
  • pickBy
  • 0.1.2 pipe
  • pipeWith
  • 0.1.2 pluck
# works for both dict and object
class Obj:
  def __init__(self, v1, v2):
    self.v1 = v1
    self.v2 = v2
obj1 = Obj(1, 2)
obj2 = Obj(3, 4)
R.pluck('v1', [obj1, obj2]) # [1, 3]
  • 0.1.2 prepend
  • 0.1.2 product
  • 0.1.2 project
# works for both dict and object
class Obj:
  def __init__(self, v1, v2):
    self.v1 = v1
    self.v2 = v2
obj1 = Obj(1, 2)
obj2 = Obj(3, 4)
R.project(['v1'], [obj1, obj2]) # [{'v1': 1}, {'v1': 3}]
  • promap
  • 0.1.2 prop
  • 0.1.2 propEq
# works for both dict and object
class Obj:
  def __init__(self, v1, v2):
    self.v1 = v1
    self.v2 = v2
obj1 = Obj(1, 2)
R.propEq(1, 'v1', obj1) # True
R.propEq(2, 'v2', obj1) # True
R.propEq(1, 'v2', obj1) # False

R.propEq(1, 'v1', {'v1': 1}) # True
  • propIs
  • propOr
  • 0.1.2 props
  • propSatisfies
  • 0.1.2 range
  • 0.1.2 reduce
  • 0.1.2 reduceBy
  • 0.1.2 reduced
  • 0.1.2 reduceRight
  • reduceWhile
  • 0.1.2 reject
  • remove
  • 0.1.4 repeat
  • replace
  • 0.1.2 reverse
  • scan
  • sequence
  • set
  • 0.1.2 slice
R.slice(1, 3, ['a', 'b', 'c', 'd']) # ['b', 'c']
R.slice(1, None, ['a', 'b', 'c', 'd']) # ['b', 'c', 'd']
  • 0.1.2 sort
  • 0.1.2 sortBy
  • sortWith
  • 0.1.2 split
  • splitAt
  • splitEvery
  • splitWhen
  • splitWhenever
  • startsWith
  • 0.1.2 subtract
# different from ramda
R.subtract(None, None) # float('nan)
R.subtract(date(1,2,3), date(1,2,3)) # float('nan)
  • 0.1.2 sum
  • symmetricDifference
  • symmetricDifferenceWith
  • 0.1.2 T
  • 0.1.2 tail
  • 0.1.2 take
  • takeLast
  • takeLastWhile
  • 0.1.2 takeWhile
  • 0.1.2 tap
  • test
  • thunkify
  • 0.1.4 times
  • toLower
  • toPairs
  • toPairsIn
  • 0.1.2 toString

Partially supported

  1. String type, supported
  2. for others, just use str(x) instead
  • toUpper
  • transduce
  • transpose
  • traverse
  • trim
  • tryCatch
  • type
  • unapply
  • 0.2.0 unary
  • uncurryN
  • unfold
  • 0.1.2 union
  • 0.1.2 unionWith
  • 0.1.2 uniq
  • 0.1.2 uniqBy
  • 0.1.2 uniqWith
  • unless
  • unnest
  • until
  • unwind
  • update
  • 0.1.2 useWith
  • 0.1.2 values
# works for both dict and object
class Obj:
  def __init__(self, v1, v2):
    self.v1 = v1
    self.v2 = v2
obj = Obj(1, 2)
R.values(obj) # [1, 2]
R.values({'a': 1, 'b': 2}) # [1, 2]
  • 0.2.0 valuesIn

Use R.keysIn to get the keys of an object.

  • view
  • when
  • 0.1.4 where

spec(first param) is prefer to be a dict.

method where supports both dict and object as second param.

class Obj:
  def __init__(self, x, y):
    self.x = x
    self.y = y

spec = {'x': R.equals(1)}
R.where(spec, {'x': 1, 'y': 2}) # True
R.where(spec, Obj(1, 2)) # True
  • whereAny
  • whereEq
  • without
  • xor
  • 0.1.2 xprod
  • 0.1.2 zip
  • zipObj
  • 0.1.2 zipWith

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

python_ramda-0.2.0.tar.gz (60.2 kB view hashes)

Uploaded Source

Built Distribution

python_ramda-0.2.0-py3-none-any.whl (132.2 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page