These are chat archives for ramda/ramda

18th
Jan 2018
James Gardner
@james-gardner
Jan 18 2018 11:24
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
@james-gardner so you are asking if array X is a subset of array Y?
James Gardner
@james-gardner
Jan 18 2018 11:44
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
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
@are1000 this works under one important condition: no repeated elements
Are
@are1000
Jan 18 2018 12:44
@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
I read array, not set :-) sorry, took it literally
Are
@are1000
Jan 18 2018 12:45
I mean, I was talking about sets :P
Francisco
@franciscotln
Jan 18 2018 12:45
Yeah, I just read his question and your answer
Francisco
@franciscotln
Jan 18 2018 12:55
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
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
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
"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
do you just mean, partially apply getRole?
James Gardner
@james-gardner
Jan 18 2018 15:30
I tried partialRight
thinking along similar lines
Mike Lambert
@lax4mike
Jan 18 2018 15:30
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
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
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
oh, I like that :D
Dennie de Lange
@tkvw
Jan 18 2018 18:20
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
there's a function for that!
http://ramdajs.com/docs/#difference
Dennie de Lange
@tkvw
Jan 18 2018 18:22
I have two objects, not two lists
Mike Lambert
@lax4mike
Jan 18 2018 18:22
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
That are two lists
Mike Lambert
@lax4mike
Jan 18 2018 18:24
ah, you're right...
Dennie de Lange
@tkvw
Jan 18 2018 18:25
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
yeah, you might need something recursive
Dennie de Lange
@tkvw
Jan 18 2018 18:26
there are really to much functions for a beginner, these should be prioritized or something
Mike Lambert
@lax4mike
Jan 18 2018 18:27
what do you mean?
Denis Stoyanov
@xgrommx
Jan 18 2018 18:28
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
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
yes, do u need compare nested objects?
Dennie de Lange
@tkvw
Jan 18 2018 18:31
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
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
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
@tkvw haskell :D
Dennie de Lange
@tkvw
Jan 18 2018 18:36
that's a FP language right?
Denis Stoyanov
@xgrommx
Jan 18 2018 18:36
yes, exactly
Mike Lambert
@lax4mike
Jan 18 2018 18:37
elm is a frontend FP language that is very similar to haskell
an ML language
Denis Stoyanov
@xgrommx
Jan 18 2018 18:37
hm
I don't like elm
Dennie de Lange
@tkvw
Jan 18 2018 18:37
damn, have to get me one of those some day
Denis Stoyanov
@xgrommx
Jan 18 2018 18:37
more better purescript
Mike Lambert
@lax4mike
Jan 18 2018 18:39
i haven't used purescript, but elm is designed to be really friendly to beginners
Dennie de Lange
@tkvw
Jan 18 2018 18:40
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
Brad Compton (he/him)
@Bradcomp
Jan 18 2018 18:40
@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
@tkvw take a look on difference between my and cookbook version https://goo.gl/8wNsNC
Dennie de Lange
@tkvw
Jan 18 2018 18:42
@Bradcomp : yeah, well.. experience is key probably, that solution @xgrommx would have taken me till the end of the month :smile:
Brad Compton (he/him)
@Bradcomp
Jan 18 2018 18:43
Definitely practice helps, but it's nice to have some direction.
Dennie de Lange
@tkvw
Jan 18 2018 18:43
@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
Brad Compton (he/him)
@Bradcomp
Jan 18 2018 18:46
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
Yes, that's a functional list (too long for my taste, but Ctrl+F able, so helpful
Brad Compton (he/him)
@Bradcomp
Jan 18 2018 18:48
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
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
@xgrommx : Is your daytime job maintaining a list of links ? :wink: Impressive!
Alec
@alavkx
Jan 18 2018 18:49
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
@tkvw yes, sometime I have time for update it =)
Dennie de Lange
@tkvw
Jan 18 2018 18:50
Thanks guys, enough info for now
Dennie de Lange
@tkvw
Jan 18 2018 19:06
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
@tkvw map(x => ({"leftValue": x})) the same
Dennie de Lange
@tkvw
Jan 18 2018 19:14
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
@alavkx : Good tip on filtering on category, that really sanitizes the list
Alec
@alavkx
Jan 18 2018 19:43
:)
groupObjBy is an awesome function
Mike Lambert
@lax4mike
Jan 18 2018 20:02
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
Brad Compton (he/him)
@Bradcomp
Jan 18 2018 20:07
R.is
Brad Compton (he/him)
@Bradcomp
Jan 18 2018 20:08
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
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
Brad Compton (he/him)
@Bradcomp
Jan 18 2018 20:53
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
Guys how would go about this?
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
Brad Compton (he/him)
@Bradcomp
Jan 18 2018 21:24
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
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
would the first item in the output be { first: 'a', second: 'a', third: 'a' }?
Aldo Velasco
@aldovelco
Jan 18 2018 21:34
yes, @lax4mike
I painfully failed at my example
Brad Compton (he/him)
@Bradcomp
Jan 18 2018 21:36
Ok that makes more sense
Aldo Velasco
@aldovelco
Jan 18 2018 21:36
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
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"}?
Brad Compton (he/him)
@Bradcomp
Jan 18 2018 21:39
this is just a basic first attempt. It works, but could probably be cleaned up.
Aldo Velasco
@aldovelco
Jan 18 2018 21:41
@lax4mike it's always guaranteed that I'll have the same number of times in each array, at least in my situation
Brad Compton (he/him)
@Bradcomp
Jan 18 2018 21:41
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
@Bradcomp thank you man, I didn't even know about zip. Still need so much practice until I can be proficient with Ramda
Brad Compton (he/him)
@Bradcomp
Jan 18 2018 21:46
:bowtie: I think zip and transpose are probably the two keys to that problem
Aldo Velasco
@aldovelco
Jan 18 2018 21:48
what is the 'o' in o(transpose, values) referring to?
Brad Compton (he/him)
@Bradcomp
Jan 18 2018 21:48
R.o
Brad Compton (he/him)
@Bradcomp
Jan 18 2018 21:48
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
R.o confuses me, sometimes it doesn't work the same as R.compose even when it's passed a single param
Brad Compton (he/him)
@Bradcomp
Jan 18 2018 21:50
for instance, o(fromPairs, zip) would break the function because zip takes 2 parameters
Sorry, shouldn't have introduced the confusion :(
Mike Lambert
@lax4mike
Jan 18 2018 21:51
actually, i can't find an example now...