mrocklin / toolz

More tools for Python
Other
51 stars 0 forks source link

merge_with is not very useful #13

Open bismigalis opened 10 years ago

bismigalis commented 10 years ago

I cant use binary operations with it

>>> import toolz as tz
>>> import operator as op
>>> tz.merge_with(op.mod, {"a":1}, {"a":2})
TypeError: op_mod expected 2 arguments, got 1

CLojure's version http://clojuredocs.org/clojure_core/clojure.core/merge-with does right thing

here is python version of it

  def merge_with(f, *maps):
        if any(maps):
            def merge_entry(m, e):
                k = e[0]
                v = e[1]
                if k in m:
                    m[k] = f(m[k], v)
                else:
                    m[k] = v
                return m

            def merge2(m1, m2):
                return reduce(merge_entry, m2.items(), (m1 or {}))

            return reduce(merge2, maps)
mrocklin commented 10 years ago

Hi @bismigalis ,

Thanks for the suggestion. I'm sorry that you feel that merge_with is not useful to your application. Binary operators simply aren't as popular within the Python community as they are in Clojure's, hence our decision to use reduction functions (like sum) rather than binary operators (like add). This is pretty subjective though and it's not clear that it was the right decision.

One solution would be to support variadic functions in merge_with if the inspect module can detect them. This is the solution proposed in https://github.com/pytoolz/toolz/pull/127

Another solution is simply to reduce your binary operator prior to using merge_with

In [1]: from operator import mod

In [2]: from toolz import curry, merge_with

In [3]: reduce = curry(reduce)

In [4]: merge_with(reduce(mod), {'a': 1}, {'a': 2})
Out[4]: {'a': 1}