These are chat archives for ramda/ramda

15th
Dec 2015
Julien Goux
@jgoux
Dec 15 2015 07:24 UTC
@kibin Thank you ! A very nice solution :D
Hardy Jones
@joneshf
Dec 15 2015 13:31 UTC
@CrossEye I think you're right.
@CrossEye which makes sense now. ap doesn't say anything about commutativity, only associativity.
Scott Sauyet
@CrossEye
Dec 15 2015 15:38 UTC
@kibin: That's a really elegant little solution! Did you start from @urmastalimaa's solution? It looks quite similar, and very different from my first thought. I love how this accumulatePath function is wrtitten.
@joneshf: Once again, I'm too tired to think this through properly, but does it feel strange to you too? It's that same "whaaaat?" feeling I got on first realizing that List<Subtype> is not a subtype of List<Type>. "Ok, I get it, damn it all, but it's still wrong!"
Kibin
@kibin
Dec 15 2015 15:46 UTC
@CrossEye thanks! Yeah, I tried to solve that with reduce at first, but wasn’t able to do it elegantly, then @urmastalimaa offered the solution with chain and compose and it became obvious to me
Aldwin Vlasblom
@Avaq
Dec 15 2015 15:54 UTC
@kibin I too find it a really neat implementation! Though I think this is one of those cases where you might want to process the path into its pipeline as soon as you have it, rather than waiting until you have the other argument. Like this http://goo.gl/DnFTVa. This allows code like this to be efficient:
const acc = accumulatePath(['dossiers', 'resultats', 'id']);
while(aLotOfTimes()) acc(item)
Kibin
@kibin
Dec 15 2015 15:59 UTC
@Avaq thanks! Doesn’t curry solve this for me?
Kibin
@kibin
Dec 15 2015 16:06 UTC
Ah, I see now, I don’t need data at all, so as curry. I think I wanted this questionable possibility to write all arguments at once
Hardy Jones
@joneshf
Dec 15 2015 16:08 UTC
@CrossEye you just showed a counter example of how it doesn't hold. That's a pretty solid answer.
Aldwin Vlasblom
@Avaq
Dec 15 2015 16:22 UTC

@kibin It's a pitfall with curry and a heavy process on the initial arguments I think, because it's not that obvious. curry() takes a single function, which it calls once it has accumulated the amount of arguments it needs. This means the code-body of your function executes every time all arguments have been accumulated. So in my aLotOfTimes-example, the code body is executed.. a lot of times. In most cases that's what you want, but in some cases you can save on a lot of extra cycles by pre-computing bits of your computation as arguments come in. Kind of like:

const accumulatePath = path => {
  const get = precomputeGetter(path); //<-- a computation in between your curry
  return data => get(data);
}

It's a function that returns a function. Which is basically what I did in my version of accumulatePath that I linked.

I think this behaviour is something important to keep in mind when you're using Ramda's curry, so I like to talk about it. :P

Aldwin Vlasblom
@Avaq
Dec 15 2015 16:27 UTC
The downside is that you can't pass more than one argument any more: accumulatePath(path) /*meh*/ (data)
Steve Coffman
@StevenACoffman
Dec 15 2015 16:47 UTC
Has anyone done any coding katas or exercises (such as exercism.io) using Ramda? I've seen FizzBuzz, but that's it.
Kibin
@kibin
Dec 15 2015 17:25 UTC
@Avaq that’s really informative, I didn’t know about the re-execution
Scott Sauyet
@CrossEye
Dec 15 2015 17:31 UTC
@Avaq: That's always a concern. At some point, we rewrote where because of this. Then we rewrote all our functions to be manually curried rather than use a curry wrapper until we could write more efficient curry wrappers. Somewhere along the way, we lost the changes to when, but that's a function that (at least until it was slit into where and whereEq) is definitely helped by this same technique.
@joneshf: I'm a mathematician by training. (Non-practicing, of course.) I do recognize that a counterexample is the best possible refutation of a notion. But I also know that it sometimes takes my intuition ages to catch up with the evidence.
Scott Sauyet
@CrossEye
Dec 15 2015 17:45 UTC
@StevenACoffman: I've never seen exercism.io (great name!) But I've done perhaps the first 40 or so of the problems on Project Euler using Ramda (or its predecessor, Eweda). Those are meant not to be shared publicly, although if anyone really wants them, I'll email links to the gists. The funny thing is that I'm doing a week of training at the moment, and one of the exercise's I'm using is the Gilded Rose Kata. But when I did my own version of this refactoring, I didn't really consider using Ramda for it (except that I borrowed a function or two, just from habit.) Your question makes me want to try another version with Ramda at its core. The people I'm working with are very junior, but they know about my work on Ramda, and some of them are at least curious about it.
Brandon Kite
@Voxelot
Dec 15 2015 18:28 UTC
Hey Rams, I'm fairly new to FP and am trying to learn me a ramda. Here's a simple use case I've been working on and would like some feedback on how to make this more readable. Say you have a list of objects and a list of ids, and want to remove any objects from the list that have their id contained in the id list.
var objs = [{id:1}, {id:2}, {id:3}];
var ids = ['1', '3'];
//insert filter logic
console.log(newObjs) // prints [{id: 2}]
//original version
var newObjs = objs.filter(function filterExisting(obj) {
    return ids.indexOf(obj.id.toString()) == -1;
});
//ramda version
var newObjs = R.filter(R.compose(R.not, R.contains(R.__, ids), R.toString, R.prop('id')))(objs);

I know I should abstract out the function passed into filter like so:

var isObjectNotContained = function(idList) {
    return R.compose(R.not, R.contains(R.__, idList), R.toString, R.prop('id'));
}

var filterObjects = function(idList) {
    return R.filter(isObjectNotContained(idList));
}

var newObjs = filterObjects(ids)(objs);

But I'm thinking there's probably a better way to do this?

Scott Barrow
@scottbarrow
Dec 15 2015 18:36 UTC
hey, is anyone aware of an issue with use memoize in minified js? (rails)
for some reason in production(minified) memoized is losing the fn, however in development the function is passed
Steve Coffman
@StevenACoffman
Dec 15 2015 19:03 UTC
@CrossEye I would dearly love to look at your Project Euler Ramda solutions. Please mail gears@umich.edu if you don't mind. Thank you!
Scott Christopher
@scott-christopher
Dec 15 2015 19:13 UTC
@scottbarrow: I'm not aware of any issues. Are you able to share the minified version of the R.memoize function that is getting produced?
Scott Christopher
@scott-christopher
Dec 15 2015 19:32 UTC
@Voxelot: my only suggestion would be to make use of R.reject rather than R.filter and R.not.
R.curry((ids, objs) => R.reject(R.compose(R.contains(R.__, ids), R.toString, R.prop('id')))(objs));
Scott Christopher
@scott-christopher
Dec 15 2015 19:39 UTC
You could alternatively try something like R.differenceWith:
R.differenceWith((obj, id) => R.equals(R.toString(obj.id), id));
Brandon Kite
@Voxelot
Dec 15 2015 19:50 UTC
differenceWith looks great, thanks!
Scott Christopher
@scott-christopher
Dec 15 2015 20:24 UTC
And if your list of objects or IDs are largish, you could give it a little boost with something like this which I believe should be O(N+M) rather than O(N*M) in the previous:
var groupByIds = R.groupBy(R.compose(R.toString, R.prop('id')));
var allValues = R.compose(R.flatten, R.values);
var removeIds = R.curry((ids, objs) =>
    allValues(R.reduce(R.flip(R.dissoc), groupByIds(objs), ids)));
Drew
@dtipson
Dec 15 2015 22:09 UTC
Loving the Arrow function syntax for functions that return functions: fn => (arr,acc) => arr.reduce(fn,acc)
Robert Monfera
@monfera
Dec 15 2015 23:09 UTC
@CrossEye I second the suggestion from @Freyert w.r.t. supporting rollup.js because d3.js 4.0 is also on rollup and ramda pairs very well with declarative d3, but people might be reluctant to pair a lightweight, tree-shaken, mobile friendly d3 with a much larger ramda utility. Does your Nov 2 msg imply that ramda might work with rollup out of the box? 'Rollup claims to have plug-ins to work with other module syntaxes, so I would expect it just to work with Ramda's src output.' Anyone tried it yet?