These are chat archives for ramda/ramda

2nd
Dec 2015
Scott Christopher
@scott-christopher
Dec 02 2015 01:33
@asaf-romano This should do it:
R.useWith(R.map, [R.flip(R.call), R.identity]);
David Chambers
@davidchambers
Dec 02 2015 01:48
R.useWith(R.ap, [R.identity, R.of]) seems nicer to me. ;)
Hardy Jones
@joneshf
Dec 02 2015 03:45
@brian-gates I'd say you can try to break it down into simple functions
then compose the functions together
Start by looking at your object.
filters
each key k v pair becomes k_i v[i]
make that conversion first
The rest of the function is much simpler than that
Hardy Jones
@joneshf
Dec 02 2015 03:56
So like, if you had the key, index, and element corresponding to that value, you could make a new object
function mkObj(key, val, i) {
  return {[`key_${i}`]: val};
}
or some ramda-y way
function mkObj(key, val, i) {
  return R.objOf(`key_${i}`, val);
}
probably you want to curry it though, so it's easier to work with
const mkObj = R.curry((key, val, i) => ({[`key_${i}`]: val}))
Then if you can just shove the values and their indexes together, you can call that function
const valIndices = xs => R.zip(xs, R.range(0, R.length(xs)))
So that would give you an array of arrays
Hardy Jones
@joneshf
Dec 02 2015 04:02
and you might see that mkObj would be better with a different type...
const mkObj = R.curry((key, [val, i]) => ({[`key_${i}`]: val}))
So then you should be able to map over that bad boy with your indices array, and things work out.
const mkObjs = key => R.map(mkObj(key))
So you end up with an array of objects from that thing
assuming you can get an array of arrays in there somehow
Then, given a key and an array of values, you can call it on that.
const indexKeys = (key, vals) => mkObjs(key, valIndices(vals))
How do you get those key vals? You can use toPairs.
At which point you realize indexKeys should have a different type as well...
Hardy Jones
@joneshf
Dec 02 2015 04:07
const indexKeys = ([key, vals]) => mkObjs(key, valIndices(vals))
So you can turn an object into an array of objects somehow
const indexObjs = obj => R.map(indexKeys, R.toPairs(obj))
So that gives you an array of array of objects
oh
don't map, chain
const indexObjs = obj => R.chain(indexKeys, R.toPairs(obj))
Then you can merge those all into one object with mergeAll
const indexed = obj => R.mergeAll(indexObjs(obj))
Then you go open the cookbook, and find this little gem: https://github.com/ramda/ramda/wiki/Cookbook#map-keys-of-an-object
and realize that given your node, you can use mapKeys to prepend all that stuff.
Hardy Jones
@joneshf
Dec 02 2015 04:12
const prependFilter = node => mapKeys(R.add(`filter_${node}__`))
and so, you can take indexed and prependFilter and use them to get what you want.
const filterParams = (node, filters) => prependFilter(node, indexed(filters))
All together now:
const mapKeys = R.curry((fn, obj) =>
  R.fromPairs(R.map(R.adjust(fn, 0), R.toPairs(obj)))
);
const mkObj = R.curry((key, [val, i]) => ({[`${key}_${i}`]: val}));
const valIndices = xs => R.zip(xs, R.range(0, R.length(xs)));
const mkObjs = key => R.map(mkObj(key));
const indexKeys = ([key, vals]) => mkObjs(key)(valIndices(vals));
const indexObjs = obj => R.chain(indexKeys, R.toPairs(obj));
const indexed = obj => R.mergeAll(indexObjs(obj));
const prependFilter = node => mapKeys(R.add(`filter_${node}__`));

const filterParams = (node, filters) => prependFilter(node)(indexed(filters));
roughly the same size as your original thing there.
I think it's not clearer as a whole
it's much more convoluted what is happening
Hardy Jones
@joneshf
Dec 02 2015 04:17
however, each function is worlds more understandable in isolation
which means, much easier to test and maintain
You can throw together some property based tests that give you a huge amount of confidence you're doing the right thing.
also, those names are kind of bad
I'm not very imaginative
Hardy Jones
@joneshf
Dec 02 2015 04:24
Also, I haven't tested that that actually works at all.
Scott Christopher
@scott-christopher
Dec 02 2015 04:24
:shipit:
Hardy Jones
@joneshf
Dec 02 2015 04:25
:)
there
seems like the right output anyway
@brian-gates anyway, that's my thought process on how I'd approach it. There's different ways
hope that helped though
Asaf
@asaf-romano
Dec 02 2015 05:21
@scott-christopher what @davidchambers said :). My first enemy is useWith, but it's only marginally worse than flip.
Scott Christopher
@scott-christopher
Dec 02 2015 05:23
I don't seem to have the same objections to flip as others do. :)
Asaf
@asaf-romano
Dec 02 2015 05:28
I don't mind flip, useWith, etc in "utility-belt" code. There I use it a lot. But using such functions in pure-business-logic pipelines always seem wrong.
speaking of utility belt code, for those of us using moment.js, here's something useful I had to introduce recently: http://pastebin.com/YnWgphhx
Hardy Jones
@joneshf
Dec 02 2015 06:25
I can't wait until someone makes a better date library
I don't know what I'll do with myself
Asaf
@asaf-romano
Dec 02 2015 07:28
I'm a big fan of moment, actually, putting the immutability issue aside. And the above utility modules solved the immutability issue for me for the most part
asaf-romano @asaf-romano should put it in the cookbook
Brian Gates
@brian-gates
Dec 02 2015 19:28
@joneshf <3 best examples ever, love the thought process narration. Still getting my head around Ramda, and that was fantastic. Thanks so much!
Ivan Demchenko
@raqystyle
Dec 02 2015 19:59
@joneshf moment.js is a good option with lots of perks
Ivan Demchenko
@raqystyle
Dec 02 2015 20:15
Hi guys! I'd love to get your opinion on a problem. Imagine we have a list of strings and we want to transform it to the list of option tags (with value and innerText set as a string from the array). I tried to do it like this http://pastebin.com/mFE8wB6Q however, it seems to me that my solution is rather ugly. Of course, it's possible to just write a function that will a take string and create an element, set properties and return the element. However, I'd love to have something more versatile.
Fulton Byrne
@Freyert
Dec 02 2015 21:50
What's the best way to work with streams and still be mildly functional.
Scott Sauyet
@CrossEye
Dec 02 2015 22:04
@raqystyle: sorry, on my phone, and can't do it proper justice. I'll try to look a little later.
@Freyert: the FRP libraries are pretty good at this. Have you looked into Highland, Flyd, Bacon, Kefir, or RxJs?
Keith Alexander
@kwijibo
Dec 02 2015 22:16
(implements fantasy land spec)
Scott Christopher
@scott-christopher
Dec 02 2015 22:30

@raqstyle: One of the nice things about map, is that compose(map(f), map(g)) is equivalent to map(compose(f, g)) (providing f and g are pure)

So your example could be modified to something like so:

map(x => compose(setText(x), setElemValue(x))(mkElem('option')));
Scott Christopher
@scott-christopher
Dec 02 2015 22:51
You would need to curry setText and setElemValue if they weren't already.
Brian Gates
@brian-gates
Dec 02 2015 22:55
where does Just come from in the docs? http://ramdajs.com/0.18.0/docs/#empty
David Chambers
@davidchambers
Dec 02 2015 22:57
@brian-gates, see S.Just for one implementation of this data constructor.
See also ramda-fantasy.
Brian Gates
@brian-gates
Dec 02 2015 23:01
ty @davidchambers