These are chat archives for ramda/ramda

18th
Jan 2018
James Gardner
@james-gardner
Jan 18 2018 11:24 UTC
any nifty shorthand function to check if the elements in array x all occur in array y ?
thanks @franciscotln
Are
@are1000
Jan 18 2018 11:41 UTC
@james-gardner so you are asking if array X is a subset of array Y?
James Gardner
@james-gardner
Jan 18 2018 11:44 UTC
yes
R.compose(
R.flip(R.all)(permissions),
R.flip(R.contains),
R.prop('permissions')
)
is what I came up with
but it seems ott
Are
@are1000
Jan 18 2018 11:45 UTC
it is as easy as this: let isSuperset = (x, y) => R.equals(R.intersection(x, y), x)
isSuperset(A, B) === true means that B is a superset of A
Francisco
@franciscotln
Jan 18 2018 12:43 UTC
@are1000 this works under one important condition: no repeated elements
Are
@are1000
Jan 18 2018 12:44 UTC
@franciscotln which is obvious (I hope) because we are talking about sets!
but it's good that you mentioned it
Francisco
@franciscotln
Jan 18 2018 12:44 UTC
I read array, not set :-) sorry, took it literally
Are
@are1000
Jan 18 2018 12:45 UTC
I mean, I was talking about sets :P
Francisco
@franciscotln
Jan 18 2018 12:45 UTC
Francisco
@franciscotln
Jan 18 2018 12:55 UTC
this allows repeated elements:
const xs = [ {id: 1}, {id: 2}, {id: 4}, {id: 4} ];
const ys = [ {id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 5} ];

R.equals(R.innerJoin(R.eqProps('id'), xs, ys), xs); // true

const ws = [5, 5, 4, 3, 2, 1];
const zs = [1 ,2 ,3 ,4 , 5, 6];

R.equals(R.innerJoin(R.equals, ws, zs), ws); // true
Francisco
@franciscotln
Jan 18 2018 15:13 UTC
alternative:
const xs = [ {id: 1}, {id: 2}, {id: 3}, {id: 4} ];
const ys = [ {id: 5}, {id: 4}, {id: 3}, {id: 2}, {id: 1}, {id: 0} ];

R.all(R.contains(R.__, ys), xs); // true
James Gardner
@james-gardner
Jan 18 2018 15:20 UTC
Does it go against the theme of things to try and bind a data pipeline to a specific list?
by bind I mean generate a function that always uses the same data in conjunction with a pipeline

For example:

const segment = getRole('USER_ADMIN')(acl);

The 'acl' argument

James Gardner
@james-gardner
Jan 18 2018 15:27 UTC
"The parameters to Ramda functions are arranged to make it convenient for currying. The data to be operated on is generally supplied last"
I'd otherwise have to write functions for every possible role, or something that generated them for me.
Mike Lambert
@lax4mike
Jan 18 2018 15:29 UTC
do you just mean, partially apply getRole?
James Gardner
@james-gardner
Jan 18 2018 15:30 UTC
I tried partialRight
thinking along similar lines
Mike Lambert
@lax4mike
Jan 18 2018 15:30 UTC
you can wrap getRole in R.curry
then you can make a new function via const getAdmin = getRole("USER_ADMIN")
James Gardner
@james-gardner
Jan 18 2018 15:31 UTC
Here's the implementation of getRole:
const getRole = (role) => R.find(
R.where({ roles: R.contains(role) })
);
getAdmin would mean I would need getXXXX for every role
Mike Lambert
@lax4mike
Jan 18 2018 15:33 UTC
what are you trying to accomplish?
you can also define getRole with the list as an argument
const getRole = R.curry((role, list) => R.find(
R.where({ roles: R.contains(role) })
)(list));
then you can do getRole("USER_ADMIN", acl)
and also create getAdmin by partially applying it, like above
or, do want getRole partially applyed with acl?
with the curried version above, you can use R.__
const getRoleFromAcl = getRole(R.__, acl);
James Gardner
@james-gardner
Jan 18 2018 15:39 UTC
oh, I like that :D
Dennie de Lange
@tkvw
Jan 18 2018 18:20 UTC
How would I go about to generate a diff between an original object and changed object? Any steps/hints?
Mike Lambert
@lax4mike
Jan 18 2018 18:21 UTC
there's a function for that!
http://ramdajs.com/docs/#difference
Dennie de Lange
@tkvw
Jan 18 2018 18:22 UTC
I have two objects, not two lists
Mike Lambert
@lax4mike
Jan 18 2018 18:22 UTC
i think it still works
R.difference([{a: 1}, {b: 2}], [{a: 1}, {c: 3}]) //=> [{b: 2}]
Dennie de Lange
@tkvw
Jan 18 2018 18:23 UTC
That are two lists
Mike Lambert
@lax4mike
Jan 18 2018 18:24 UTC
ah, you're right...
Dennie de Lange
@tkvw
Jan 18 2018 18:25 UTC
so I think the deep comparison is going to be a bit of a problem, or at least, I can't wrap my head arround it
Mike Lambert
@lax4mike
Jan 18 2018 18:26 UTC
yeah, you might need something recursive
Dennie de Lange
@tkvw
Jan 18 2018 18:26 UTC
there are really to much functions for a beginner, these should be prioritized or something
Mike Lambert
@lax4mike
Jan 18 2018 18:27 UTC
what do you mean?
Denis Stoyanov
@xgrommx
Jan 18 2018 18:28 UTC
ahah
my ugly solution for objects
useWith(
compose(
mergeAll,
map(apply(objOf)),
difference
), [toPairs, toPairs])({a: 10, b: 20}, {a: 10, b: 30})
Dennie de Lange
@tkvw
Jan 18 2018 18:28 UTC
all those functions in the api..
that looks impressive, let me analyze :smile:
@xgrommx : at first glance this only works for flat objects right ? ([toPairs,toPairs])
Denis Stoyanov
@xgrommx
Jan 18 2018 18:30 UTC
yes, do u need compare nested objects?
Dennie de Lange
@tkvw
Jan 18 2018 18:31 UTC
yeah, I have this form which renders fields from a rest api, and I want to send a sparse update back. I have a function for it, but I thought this would be a good starting function for FP
it has some specific needs, like it requires the id of nested objects when a subproperty changes, etc.
Denis Stoyanov
@xgrommx
Jan 18 2018 18:32 UTC
oh) I had the same problem on my project

take a look on

const isObject = compose(equals('Object'), type)

const isNumeric = v => !isNaN(v - parseFloat(v))

const groupObjBy = curry(compose(
map(fromPairs),
useWith(groupBy, [useWith(__, [last]), toPairs]),
))

const diffObj = compose(
evolve({
difference: map(({leftValue, rightValue}) => {
if (isObject(leftValue) && isObject(rightValue)) {
return diffObj(leftValue, rightValue)
} else {
return {leftValue, rightValue}
}
}),
common: map(prop("leftValue")),
onlyOnLeft: map(prop("leftValue")),
onlyOnRight: map(prop("rightValue"))
}),
groupObjBy(cond([
[
both(has("leftValue"), has("rightValue")),
compose(ifElse(apply(equals), always("common"), always("difference")), values)
],
[has("leftValue"), always("onlyOnLeft")],
[has("rightValue"), always("onlyOnRight")],
])),
useWith(mergeWith(merge), [map(objOf("leftValue")), map(objOf("rightValue"))])
)

This is advanced version of https://github.com/ramda/ramda/wiki/Cookbook#diffobjs---diffing-objects-similar-to-guavas-mapsdifference
My version works correctly with nested objects

Dennie de Lange
@tkvw
Jan 18 2018 18:35 UTC
that just looks like magic... how did you wrap your head arround all those small steps? Is there a good read about this, or just practice, practice, practice?
Denis Stoyanov
@xgrommx
Jan 18 2018 18:36 UTC
Dennie de Lange
@tkvw
Jan 18 2018 18:36 UTC
that's a FP language right?
Denis Stoyanov
@xgrommx
Jan 18 2018 18:36 UTC
yes, exactly
Mike Lambert
@lax4mike
Jan 18 2018 18:37 UTC
elm is a frontend FP language that is very similar to haskell
an ML language
Denis Stoyanov
@xgrommx
Jan 18 2018 18:37 UTC
hm
I don't like elm
Dennie de Lange
@tkvw
Jan 18 2018 18:37 UTC
damn, have to get me one of those some day
Denis Stoyanov
@xgrommx
Jan 18 2018 18:37 UTC
more better purescript
Mike Lambert
@lax4mike
Jan 18 2018 18:39 UTC
i haven't used purescript, but elm is designed to be really friendly to beginners
Dennie de Lange
@tkvw
Jan 18 2018 18:40 UTC
I come from oo and am working with React now and learn more about FP, and I really hate the way I got accustomed to solve tasks. FP looks so ellegant
Jan 18 2018 18:40 UTC
@tkvw I start with writing small functions I know I will need in the final solution. Then I look at how I can build those together into composites that will solve my issue
The beauty (to me) in functional approaches is how composable everything is. You write small focused functions that do something you want, and then you can mix and match those with functions that manipulate the structure you are working with
Denis Stoyanov
@xgrommx
Jan 18 2018 18:42 UTC
@tkvw take a look on difference between my and cookbook version https://goo.gl/8wNsNC
Dennie de Lange
@tkvw
Jan 18 2018 18:42 UTC
@Bradcomp : yeah, well.. experience is key probably, that solution @xgrommx would have taken me till the end of the month :smile:
Jan 18 2018 18:43 UTC
Definitely practice helps, but it's nice to have some direction.
Dennie de Lange
@tkvw
Jan 18 2018 18:43 UTC
@xgrommx : Yeah, I am going to play arround with it, thanks for the toy!
@Bradcomp : Exactly, that's what I am missing in the docs, something like a structurual flow to use (and which functions belong with these flows) for obvious use cases.
I need to spend some more time in the Cookbook
Denis Stoyanov
@xgrommx
Jan 18 2018 18:46 UTC
Jan 18 2018 18:46 UTC
There's also the 'What function should I use' part of the wiki, which may help
Dennie de Lange
@tkvw
Jan 18 2018 18:47 UTC
Yes, that's a functional list (too long for my taste, but Ctrl+F able, so helpful
Jan 18 2018 18:48 UTC
Honestly, it's nice to start with a dozen or so basic building blocks - map, filter, reduce, prop,path,pipeandcompose, etc...
You can go a long way with just a few functions, and the more esoteric ones will start to make sense as you see the recurring patterns you're dealing with
Alec
@alavkx
Jan 18 2018 18:48 UTC
The api is broken in to categories you'll see along the right of the function names (Math, List, Object, etc..). And you can use the search to search by the categories. I use that quite often
Dennie de Lange
@tkvw
Jan 18 2018 18:49 UTC
@xgrommx : Is your daytime job maintaining a list of links ? :wink: Impressive!
Alec
@alavkx
Jan 18 2018 18:49 UTC
This is a great article series for getting started http://randycoulman.com/blog/categories/thinking-in-ramda/
Denis Stoyanov
@xgrommx
Jan 18 2018 18:49 UTC
@tkvw yes, sometime I have time for update it =)
Dennie de Lange
@tkvw
Jan 18 2018 18:50 UTC
Thanks guys, enough info for now
Dennie de Lange
@tkvw
Jan 18 2018 19:06 UTC
Wow, it's already so much fun to understand map(objOf("leftValue")) and why you would even think of it, nice
Denis Stoyanov
@xgrommx
Jan 18 2018 19:13 UTC
@tkvw map(x => ({"leftValue": x})) the same
Dennie de Lange
@tkvw
Jan 18 2018 19:14 UTC
yeah, it has landed already, now looking at the groupObjBy beast
those placeholder thingies make it hard to wrap my head arround it, but I'll get there
Dennie de Lange
@tkvw
Jan 18 2018 19:38 UTC
@alavkx : Good tip on filtering on category, that really sanitizes the list
Alec
@alavkx
Jan 18 2018 19:43 UTC
:)
groupObjBy is an awesome function
Mike Lambert
@lax4mike
Jan 18 2018 20:02 UTC
what's the deal with R.is, can we use this with Array?
i don't see it in the examples: http://ramdajs.com/docs/#is
i wondering if there is a weird edge case, kind of like R.is(Object, new String('')); //=> true
Jan 18 2018 20:07 UTC
R.is
ram-bot
@ram-bot
Jan 18 2018 20:07 UTC
Jan 18 2018 20:08 UTC
Looks like it just does an instance check according to the source
Also, the source links Rambot provides need to be updated
Mike Lambert
@lax4mike
Jan 18 2018 20:11 UTC
i'm a little wary of R.is because of .constuctor and instanceOf. I know there are gotcha's with those and i don't fully understand them
Jan 18 2018 20:53 UTC
I would agree to some extent.
It would definitely be worthwhile to test it for your use case before just relying on it
Aldo Velasco
@aldovelco
Jan 18 2018 21:19 UTC
const input = {
first: [
{id: 'a'},
{id: 'b'},
{id: 'c'}
],
second: [
{id: 'a'},
{id: 'b'},
{id: 'c'}
],
third: [
{id: 'a'},
{id: 'b'},
{id: 'c'}
],
};

const output = [
{ first: 'a', second: 'b', third: 'c' },
{ first: 'a', second: 'b', third: 'c' },
{ first: 'a', second: 'b', third: 'c' },
];
I've been reading about some of the functions like toPairs but I'm not sure how I can merge the objects to get my desired output
Jan 18 2018 21:24 UTC
what is the transformation you're trying to make? It isn't really clear to me from the example
Aldo Velasco
@aldovelco
Jan 18 2018 21:31 UTC
I have an object with 3 different arrays (first, second and third). I need to to merge there 3 arrays by property
Mike Lambert
@lax4mike
Jan 18 2018 21:33 UTC
would the first item in the output be { first: 'a', second: 'a', third: 'a' }?
Aldo Velasco
@aldovelco
Jan 18 2018 21:34 UTC
yes, @lax4mike
I painfully failed at my example
Jan 18 2018 21:36 UTC
Ok that makes more sense
Aldo Velasco
@aldovelco
Jan 18 2018 21:36 UTC
This is what I'm actually trying to achieve:
const output = [
{ first: 'a', second: 'a', third: 'a' },
{ first: 'b', second: 'b', third: 'b' },
{ first: 'c', second: 'c', third: 'c' },
];
Mike Lambert
@lax4mike
Jan 18 2018 21:37 UTC
that's still a little weird, your array needs to have the same number of elements as each of the objects
what if there is {id: "d"}?
Jan 18 2018 21:39 UTC
this is just a basic first attempt. It works, but could probably be cleaned up.
Aldo Velasco
@aldovelco
Jan 18 2018 21:41 UTC
@lax4mike it's always guaranteed that I'll have the same number of times in each array, at least in my situation
Jan 18 2018 21:41 UTC
using toPairs and pulling out the keys and values that way would technically be safer than using keys and values, but every implementation preserves object ordering so that will work fine
converge(compose(fromPairs, zip), [keys, o(transpose, values)])(input) is a tacit version if you're into that sort of thing
Aldo Velasco
@aldovelco
Jan 18 2018 21:45 UTC
@Bradcomp thank you man, I didn't even know about zip. Still need so much practice until I can be proficient with Ramda
Jan 18 2018 21:46 UTC
:bowtie: I think zip and transpose are probably the two keys to that problem
Aldo Velasco
@aldovelco
Jan 18 2018 21:48 UTC
what is the 'o' in o(transpose, values) referring to?
Jan 18 2018 21:48 UTC
R.o
ram-bot
@ram-bot
Jan 18 2018 21:48 UTC
Jan 18 2018 21:48 UTC
You can sub it out for compose and it would work the same, it's just shorter
o is more restrictive than compose though
Mike Lambert
@lax4mike
Jan 18 2018 21:49 UTC
R.o confuses me, sometimes it doesn't work the same as R.compose even when it's passed a single param
for instance, o(fromPairs, zip) would break the function because zip` takes 2 parameters