
Show HN: Omg-Curry – JavaScript currying library - debdut
https://github.com/Debdut/omg-curry
======
ufo
I had mixed results in the past when I tried to use currying in Javascript.
The stack traces were cluttered by references to the currying function and it
also masked bugs if you forgot to pass an argument. Without currying, if you
pass less arguments than the function expects then you usually get an error
right away complaining that the argument is undefined. However, if the
function is curried then it silently succeeds. You only notice the problem
later, when you try to use the return value and realize that it is actually a
function. To make things worse, when this happens the stack trace points to
the place that is trying to use the return value instead of pointing to the
function call that is the actual source of the problem.

My final impression was that currying works better a language like Haskell
that has a strong type system. In a dynamic language it is more problematic.

~~~
tutfbhuf
How about Typescript then?

~~~
ufo
When I did that it was before Typescript existed. If anyone has tried currying
with Typescript I'd love to hear how it went.

------
brundolf
JavaScript actually has a pretty ergonomic way of doing currying natively:

    
    
      const add = (a) => (b) => a + b;
      
      [1, 2, 3, 4].map(add(2));  // [3, 4, 5, 6]

~~~
javajosh
I like this too (and use a version myself) however this form only supports one
argument at a time. E.g. add(1,2) is going to return the curry of add(1),
which is not what you want. The OP's function doesn't have that problem.

Something I would really like, although this would require some language-level
changes, I think, is the ability to curry arguments in any order, maybe using
placeholders. So you could say add(_, 2) and get back a function of one
argument, such that if you call it with 1, for example, you invoke add(1, 2).

~~~
brundolf
What it ends up being for normal usage is something like this:

    
    
      add(1)(2)
    

Which is admittedly a little bit clunky, though from a quick read I don't
think the library helps with this.

You might be interested in the "pipeline operator" proposal. In addition to
pairing nicely with curried functions, it offers a certain amount of re-
ordering.

~~~
javajosh
Yeah I think your quick read is off:

    
    
      add4(1)(3)(5)(10)
      add4(1)(3,5)(10)
      add4(1,3,5,10)
      // 19

------
gitgud
Sorry I'm not that familiar with this. What would be a good use-case for
currying?

The example doesn't feel that exciting...

    
    
        add4(1)(3)(5)(10)
        add4(1)(3,5)(10)
        add4(1,3,5,10)
        // 19

~~~
smichel17
It's nice for any type of list iteration. I'll share my "match" function (for
use when filtering) when I'm at my computer tomorrow.

~~~
smichel17
It's tomorrow somewhere…

    
    
        /**
         * These functions are intended to be used with array iteration methods
         * -------------------
         * // Example data:
         * let e1 = { a: 1, b:  2, c: "C" };
         * let e2 = { a: 2, b: 12, c: "D" };
         * let myArray = [ e1, e2 ];
         *
         * // Basic usage, matching a constant
         * myArray.filter(match({a: 1})); // [ e1 ]
         * myArray.filter(match({a: 3})); // [ ]
         *
         * // Matching multiple properties
         * myArray.filter(match({ a: 1, c: "C" }));    // [ e1 ]
         * myArray.filter(match({ a: 1, c: "D" }));    // [ ]
         * myArray.filter(matchAny({ a: 1, c: "D" })); // [ e1, e2 ]
         *
         * // If a function is provided, return the result of the function
         * // called with the corresponding property as its argument.
         * let belowTen = n => n < 10;
         * myArray.filter(match({ a: belowTen, b: belowTen })); // [ e1 ]
         * myArray.filter(matchAny({ a: belowTen, b: belowTen })); // [ e1, e2 ]
         *
         */
        export const match = o1 => o2 => Object.entries(o1).every(
          ([k, v]) => typeof v === "function" ? v(o2[k]) : o2[k] === v
        );
        export const matchAny = o1 => o2 => Object.entries(o1).some(
          ([k, v]) => typeof v === "function" ? v(o2[k]) : o2[k] === v
        );

------
giancarlostoro
> WTF is Curry?

> A Curry takes arguments one by one unlike functions which takes all
> arguments at once.

Took the words right out of my brain.

------
finnh
The old "drop a link" routine isn't beloved here at HN, but this xkcd is just
so good:

[https://xkcd.com/2210/](https://xkcd.com/2210/)

------
randompwd
funny how most react devs were using currying directly when they were calling
redux lib.

still think it(redux) was a misplaced usage of currying.

