These are chat archives for ramda/ramda

18th
Jan 2017
Adam Szaraniec
@mimol91
Jan 18 2017 09:32

Hey
I need small help
I want to convert
const data = ["operationC","operationD"]
to
const result = {operationC: true, operationD:true}

Which function should I use?

I've tried with reduce, and I could to convert it to object in array, and then, but then I need to use head,
Wondering if its better solution
James Forbes
@JAForbes
Jan 18 2017 09:38

@mimol91 is this ok?

R.pipe(
  R.indexBy(R.identity) //=> { operationC: 'operationC', operationD: 'operationD'}
  ,R.map(Boolean) //=> { operactionC: true, operationD: true }
)

Depending on your requirements (E.g. truthyness) indexBy might be enough on its own

Sudarsan Balaji
@artfuldev
Jan 18 2017 09:38
I was just trying to paste that :)
James Forbes
@JAForbes
Jan 18 2017 09:38
:)
Aldwin Vlasblom
@Avaq
Jan 18 2017 09:39
Those solutions where you need to use head ;)
Adam Szaraniec
@mimol91
Jan 18 2017 09:39
Nice, thanks
James Forbes
@JAForbes
Jan 18 2017 09:39
Hope it helps
Adam Szaraniec
@mimol91
Jan 18 2017 09:39
Smart one
James Forbes
@JAForbes
Jan 18 2017 09:39
And people say identity isn't useful, I'll never understand it
Adam Szaraniec
@mimol91
Jan 18 2017 09:41
I was also thinking about zipObject, but this solution with identity is much better
Aldwin Vlasblom
@Avaq
Jan 18 2017 09:42
You can also map your keys into pairs, and then fromPairs.
Denis Stoyanov
@xgrommx
Jan 18 2017 09:44
zipObj(["operationC","operationD"], [true, true])
@mimol91 :point_up: January 18, 2017 11:44 AM
Adam Szaraniec
@mimol91
Jan 18 2017 09:46
It could work, but I got dynamic array with operations. But I think about it =)
James Forbes
@JAForbes
Jan 18 2017 09:46

@xgrommx yeah that was my first though too, but then if its variable it gets a bit trickier, could still work though

Maybe

converge(zipObj, [identity, pipe(length, repeat(true))])

But I don't know

Oh maybe ap!?
Adam Szaraniec
@mimol91
Jan 18 2017 09:49
I've never used converge :( Need to learn how it works. same for ap :(
James Forbes
@JAForbes
Jan 18 2017 09:51
I can't quite ap to work anyway.
@mimol91 converge takes a function, and a list of functions that transforms the argument with the same index
Denis Stoyanov
@xgrommx
Jan 18 2017 09:52
converge ~ lift
James Forbes
@JAForbes
Jan 18 2017 09:52
so the first argument, we apply identity to it, which does nothing
Aldwin Vlasblom
@Avaq
Jan 18 2017 09:53
@JAForbes ap(zipObj, pipe(length, repeat(true))) seems to work fine.
James Forbes
@JAForbes
Jan 18 2017 09:53
the second argument we apply pipe(length, repeat(true)) which will get the length of the list (2) and repeat true as many times, so we end up with zipObj(['conditionC', 'conditionD'], [true, true])
Adam Szaraniec
@mimol91
Jan 18 2017 09:53
I m start reading about it on doc, cos I saw some videos, and I think ap and coverage are quite popular
I like example with numbers
James Forbes
@JAForbes
Jan 18 2017 09:53
@Avaq nice!
Aldwin Vlasblom
@Avaq
Jan 18 2017 09:54
converge(f, [identity, g]) === ap(f, g) always, I think.
James Forbes
@JAForbes
Jan 18 2017 09:54
I was trying to do something like: ap([I,T]) but that ends up with a flat list :(
Denis Stoyanov
@xgrommx
Jan 18 2017 09:56
or :smile:
ap(zipObj, compose(repeat(true), length))(["operationC","operationD"])
Aldwin Vlasblom
@Avaq
Jan 18 2017 09:56
That's the same but pipe switched for compose.
James Forbes
@JAForbes
Jan 18 2017 09:56
@mimol91 here's a better example of converge
converge( concat, [toUpper, toLower])( 'hi' ) //=> 'Hihi' 

// equivalent to

concat( toUpper('hi'), toLower('hi') )
this is a fun problem, could make a good blog post
Denis Stoyanov
@xgrommx
Jan 18 2017 09:57
yes, but compose more fp stuff than pipe.
Aldwin Vlasblom
@Avaq
Jan 18 2017 09:57
Ye
Adam Szaraniec
@mimol91
Jan 18 2017 09:57
ahh, do not like compose :( Its force me to thinking from left to right :)
James Forbes
@JAForbes
Jan 18 2017 09:57
more fp?
Adam Szaraniec
@mimol91
Jan 18 2017 09:58
Which function expect the common ones should I learn ?
It would be nice to get some info about 'popularity' of given function
Denis Stoyanov
@xgrommx
Jan 18 2017 09:58
@mimol91 where u apply arguments to function? (left, right)
Aldwin Vlasblom
@Avaq
Jan 18 2017 09:58
@xgrommx Not in the case of Ramda's compose though. That's just as useless as its pipe when it comes to "real FP".
Denis Stoyanov
@xgrommx
Jan 18 2017 09:58
f <- f2 <- f3 <- arg
Adam Szaraniec
@mimol91
Jan 18 2017 09:59
ye, but I read from left to right :) its much more cleaner for me
Denis Stoyanov
@xgrommx
Jan 18 2017 09:59
@Avaq yeah)) real compose is B combinator =)
Adam Szaraniec
@mimol91
Jan 18 2017 09:59
I m not a 'mathematician'
Denis Stoyanov
@xgrommx
Jan 18 2017 10:00
@mimol91 f(g(x)) <- f . g $ x
Aldwin Vlasblom
@Avaq
Jan 18 2017 10:00
Real FP would look more like S(zipObj)(B(repeat(true))(length)).. But practically I think our previous solution was better. ;)
Denis Stoyanov
@xgrommx
Jan 18 2017 10:00
yep
@Avaq for js better but it isn't better for autocurried languages :smile:
Aldwin Vlasblom
@Avaq
Jan 18 2017 10:02
@mimol91 You can't quite read ap(zipObj, pipe(length, repeat(true))) from left to right, because of the argument order of ap. So you read from middle to right, jump to left.
Adam Szaraniec
@mimol91
Jan 18 2017 10:02
yeah, could convert coverage to ap
join('', ap([toUpper, toLower], ['hi']))
Aldwin Vlasblom
@Avaq
Jan 18 2017 10:03
So if we would use compose, it would be a simple right-to-left.
And you'll find that a lot.
Denis Stoyanov
@xgrommx
Jan 18 2017 10:04
or compose(join(''), sequence(always, [toUpper, toLower]))('hi')
Adam Szaraniec
@mimol91
Jan 18 2017 10:05
but if you split it from right-to-left to bottom-to-up it is unintuitive
hmm I dont like the example for sequence on ramda doc,
Cos it use monads, I would like to see some 'easy' exmple
James Forbes
@JAForbes
Jan 18 2017 10:07

But pipe isn't lesser, its equivalent functionality, just reversed. Part of the power of FP is the ability to safely replace components when composing and being able to reason about it. So if you want to use pipe, you can, and you can always change it to compose later if you want. There is no objective merit in using one over the other.

Sometimes I use compose, sometimes I use pipe. Its always subjective. E.g. I use pipe when I'm in a unix pipe frame of mind, I use compose when I'm more interested in highlighting the resulting data structure, not the original.

If I want to highlight something ends up being a maybe, I'd use compose compose(Just, f), if I am more interested in highlighting how the source is immediately being handled, I'd use pipe: pipe( escapeSQL, f)

Denis Stoyanov
@xgrommx
Jan 18 2017 10:07
@mimol91 Applicaitve and Foldable need for sequence
James Forbes
@JAForbes
Jan 18 2017 10:08
But that's just for me, they're not objective reasons.
Adam Szaraniec
@mimol91
Jan 18 2017 10:08
is always Applicative ?
I 've heard about Foldable but I have no clue what Applicaitve is
Denis Stoyanov
@xgrommx
Jan 18 2017 10:09
@mimol91 always is of for Function or just Pointed Functor
also always is K combinator from SKI
Adam Szaraniec
@mimol91
Jan 18 2017 10:12
ahh. its so hard... :)
Any good materials (the best will be some videos) about FP?
I've saw some 'puppets' talking about it, and it was nice explained
Adam Szaraniec
@mimol91
Jan 18 2017 10:14
Wow a lot of stuff
i've tried a little bit with closure, but after some time by mind just exploded
Adam Szaraniec
@mimol91
Jan 18 2017 10:16
yee I saw his video
Denis Stoyanov
@xgrommx
Jan 18 2017 10:16
latest book is awesome for js and fp together
Denis Stoyanov
@xgrommx
Jan 18 2017 10:17
@mimol91 also https://github.com/xgrommx/practical-functional-programming (just my experiments with Applicative, Traversable, Monad, Monoid, Combinators etc)
@mimol91 will be updated in future
Adam Szaraniec
@mimol91
Jan 18 2017 10:19
I ll need some time to catch the basics of FP
Tushar Mathur
@tusharmath
Jan 18 2017 10:20
R.assoc what does assoc mean?
Denis Stoyanov
@xgrommx
Jan 18 2017 10:21
@tusharmath
Makes a shallow clone of an object, setting or overriding the specified property with the given value. Note that this copies and flattens prototype properties onto the new object as well. All non-primitive properties are copied by reference.
Tushar Mathur
@tusharmath
Jan 18 2017 10:21
I mean the word.
:)
Adam Szaraniec
@mimol91
Jan 18 2017 10:21
to associate?
I guess
Tushar Mathur
@tusharmath
Jan 18 2017 10:24
:thumbsup:
Adam Szaraniec
@mimol91
Jan 18 2017 10:28

One more question,
How can I merge 2 objects (2 level deep)

const a = {
 groupA: {
   operationA: false,
   operationB: true
},
 groupB: {
   operationC: false,
   operationD: true
 },
}

const b = {
 groupA: {
   operationA: true,
   operationB: true
},
 groupB: {},
}

const expected = {
 groupA: {
   operationA: true,
   operationB: true
},
 groupB: {
   operationC: false,
   operationD: true
 },
}

Sorry, not sure if has to do with ramda

Tushar Mathur
@tusharmath
Jan 18 2017 10:29
@mimol91 You could use lenses
Denis Stoyanov
@xgrommx
Jan 18 2017 10:29
@mimol91 I'm not sure, but try mergeWith(merge)
@ram-bot
const a = {
 groupA: {
   operationA: false,
   operationB: true
},
 groupB: {
   operationC: false,
   operationD: true
 },
}

const b = {
 groupA: {
   operationA: true,
   operationB: true
},
 groupB: {},
}

R.mergeWith(R.merge)(a, b)
ram-bot
@ram-bot
Jan 18 2017 10:30
{ groupA: { operationA: true, operationB: true },
  groupB: { operationC: false, operationD: true } }
Denis Stoyanov
@xgrommx
Jan 18 2017 10:30
@tusharmath lenses is a problematic stuff regarding perf in js
Tushar Mathur
@tusharmath
Jan 18 2017 10:31
Ok
Adam Szaraniec
@mimol91
Jan 18 2017 10:31
Thanks @xgrommx
Ramda is a new 'jquery' you can do everything :) and has great community <3
Adam Szaraniec
@mimol91
Jan 18 2017 10:46

Tricky question (JS)

const shallowMergePemrission = (a,b) => {
  return {
    ...a,
    ...b
  }
}

How can I change this function to accept any number of arguments ?

Probably need to use object.assign ?
Denis Stoyanov
@xgrommx
Jan 18 2017 10:50
@mimol91 ? (...args) => Object.assign({}, ...args)
@mimol91 or unapply(mergeAll)
Marc Grabanski
@1Marc
Jan 18 2017 14:38
I have an array of objects. ["key1":{foo:"baz"}, "key2":{foo:"bar}, ...] -- I'm trying to figure out how to merge them into a shallow array of objects where the key is a property. Like [{id: "key", foo:"baz"}, ...]
I need to assign it's key to a property on each object in the set to make one shallow array of objects. But I'm stumped.
Denis Stoyanov
@xgrommx
Jan 18 2017 14:43
@1Marc need more info
Aldwin Vlasblom
@Avaq
Jan 18 2017 14:43
@ram-bot ["key1":{foo:"baz"}] // what do you mean - array of objects, or object?
ram-bot
@ram-bot
Jan 18 2017 14:43
Unexpected token :
Marc Grabanski
@1Marc
Jan 18 2017 14:44
{"key1":{foo:"baz"}, "key2":{foo:"bar}, ...} sorry... looks like nested objects
I want {"key1":{foo:"baz"}, "key2":{foo:"bar}, ...} to turn into [{id: "key1", foo:"baz"}, {id: "key2", foo:"bar}]
James Forbes
@JAForbes
Jan 18 2017 14:45
@1Marc could you post a subset of some sample data and describe the expected output?
Marc Grabanski
@1Marc
Jan 18 2017 14:45
k
Brad Compton (he/him)
@Bradcomp
Jan 18 2017 14:48
:point_up_2: Like this?
Marc Grabanski
@1Marc
Jan 18 2017 14:49
whoa that looks right. yeah I'm going to try it
Denis Stoyanov
@xgrommx
Jan 18 2017 14:49
@1Marc zipWith((v, k) => ({id: k, ...v}))(values(x), keys(x))
converge(zipWith((v, k) => ({id: k, ...v})), [values, keys])
Aldwin Vlasblom
@Avaq
Jan 18 2017 14:51
or compose(values, mapObjIndexed(useWith(merge, [identity, objOf('id')])))
Marc Grabanski
@1Marc
Jan 18 2017 14:52
geez you guys -- I'm going to try to wrap my head around all of these possible solutions lol
ram-bot
@ram-bot
Jan 18 2017 14:52
Unexpected token ...
Denis Stoyanov
@xgrommx
Jan 18 2017 14:52
:smile:
ram-bot
@ram-bot
Jan 18 2017 14:53
missing ) after argument list
Denis Stoyanov
@xgrommx
Jan 18 2017 14:53
@ram-bot
var x = { 'Jon': { '7/2016': 11026, '8/2016': 10793, '9/2016': 5526 },
  'Max': { '7/2016': 62911, '8/2016': 59902, '9/2016': 46801 },
  'Phil': { '7/2016': 40233, '8/2016': 45060, '9/2016': 44902 },
  'Tim': { '7/2016': 61083, '8/2016': 68584, '9/2016': 70511 }}

R.converge(R.zipWith((v, k) => Object.assign({}, {Author: k}, v)), [R.values, R.keys])(x)
ram-bot
@ram-bot
Jan 18 2017 14:53
[ { Author: 'Jon',
    '7/2016': 11026,
    '8/2016': 10793,
    '9/2016': 5526 },
  { Author: 'Max',
    '7/2016': 62911,
    '8/2016': 59902,
    '9/2016': 46801 },
  { Author: 'Phil',
    '7/2016': 40233,
    '8/2016': 45060,
    '9/2016': 44902 },
  { Author: 'Tim',
    '7/2016': 61083,
    '8/2016': 68584,
    '9/2016': 70511 } ]
Marc Grabanski
@1Marc
Jan 18 2017 14:57
so far @Bradcomp 's solution is making the most sense to me
I'm going to look at converge + zipWith and compose + mapObjIndexed thanks @xgrommx and @Avaq
R.pipe(R.toPairs, R.map(([key, val]) => {val.Author = key; return val}))(obj) is doing the trick
Aldwin Vlasblom
@Avaq
Jan 18 2017 15:01
compose(values, mapObjIndexed(useWith(merge, [identity, objOf('id')]))) can also be written as:
compose(values, mapObjIndexed((v, k) => merge(v, {id: k})))
Marc Grabanski
@1Marc
Jan 18 2017 15:02
🤔 that looks simpler
Aldwin Vlasblom
@Avaq
Jan 18 2017 15:03
or better yet:
compose(values, mapObjIndexed((v, k) => assoc('id', k, v))) or for that matter:
compose(values, mapObjIndexed(flip(assoc('id'))))
val.Author = key is a mutation, which is discouraged in functional programming.
Marc Grabanski
@1Marc
Jan 18 2017 15:05
how do you not mutate if you need to output in a certain format
Aldwin Vlasblom
@Avaq
Jan 18 2017 15:05
You return new output.
Marc Grabanski
@1Marc
Jan 18 2017 15:06
the rest of my program does this, but I guess I'm getting impatient lol
when I run R.compose(data, R.mapObjIndexed(R.flip(R.assoc('Author')))) the output is a function
Aldwin Vlasblom
@Avaq
Jan 18 2017 15:07
So you might do this: const lookAt = (o) => { o.viewed = true; return o }, which mutates the input data, or: const lookAt = (o) => Object.assign({viewed: true}, o), which copies all of os properties into a brand-new object.
All of Ramda's internal functions use the latter strategy, ensuring it never mutates your input.
Marc Grabanski
@1Marc
Jan 18 2017 15:08
yeah makes sense
Aldwin Vlasblom
@Avaq
Jan 18 2017 15:08
That's why we have assoc for assigning new properties to objects.
Marc Grabanski
@1Marc
Jan 18 2017 15:10
n/m I got it working
R.compose(R.values, R.mapObjIndexed(R.flip(R.assoc('Author')))) is a tricky bit of code going to have to mess around with it to understand
Aldwin Vlasblom
@Avaq
Jan 18 2017 15:11

the output is a function

That's correct. A function you can enter your input data into

Marc Grabanski
@1Marc
Jan 18 2017 15:11
yea I did that
It's working fine now
so you're pushing the object index into assoc method which would be {key: Author} and then flipping them. 🤔 cool I wouldn't have thought of that
Marc Grabanski
@1Marc
Jan 18 2017 15:21
@Avaq here's the whole working program -- no mutation! https://gist.github.com/1Marc/6e9cb625205e8d28ff52df2298004310
Thanks for the tip. :+1:
That's the first time I've written an entire data transformation / import script entirely with composing Ramda methods
I guess .sort() is technically a mutation?
😤
Aldwin Vlasblom
@Avaq
Jan 18 2017 15:26
And so is acc += ...
You meant to type: acc + ..., it doesn't matter much since it's isolated
Brenton Alker
@tekerson
Jan 18 2017 15:28
heh :) noticed that too - and it's not needed acc + ... would work anyway
Marc Grabanski
@1Marc
Jan 18 2017 15:31
ok so switch += to + 🤔 k
Denis Stoyanov
@xgrommx
Jan 18 2017 15:32
Marc Grabanski
@1Marc
Jan 18 2017 15:32
because whatever reduce method returns goes into the accumulator anyways
makes sense
tekerson @tekerson nods
Denis Stoyanov
@xgrommx
Jan 18 2017 15:35
@1Marc a += 10 => b = a + 10, o.x = 10 => Object.assign({}, {x: 10}, o) or {x: 10, ...o}
Marc Grabanski
@1Marc
Jan 18 2017 15:36
you all are crazy coding this way
I guess I am too now that I've done it..haha
Denis Stoyanov
@xgrommx
Jan 18 2017 15:37
no mutations)) only a new data
Marc Grabanski
@1Marc
Jan 18 2017 15:37
yeah
I've been messing around with Rx which is the same concepts -- helped me stumble through this script
thanks all for your help! 😀
Denis Stoyanov
@xgrommx
Jan 18 2017 15:41
@1Marc also your case will be solved with plain js
ram-bot
@ram-bot
Jan 18 2017 15:42
Reflect is not defined
Denis Stoyanov
@xgrommx
Jan 18 2017 15:42
:smile:
@ram-bot
var x = { 'Jon': { '7/2016': 11026, '8/2016': 10793, '9/2016': 5526 },
  'Max': { '7/2016': 62911, '8/2016': 59902, '9/2016': 46801 },
  'Phil': { '7/2016': 40233, '8/2016': 45060, '9/2016': 44902 },
  'Tim': { '7/2016': 61083, '8/2016': 68584, '9/2016': 70511 }}


const f = x => Object.keys(x).reduce((a, v) => a.concat(Object.assign({}, {Author: v}, x[v])), [])

f(x)
ram-bot
@ram-bot
Jan 18 2017 15:42
[ { Author: 'Jon',
    '7/2016': 11026,
    '8/2016': 10793,
    '9/2016': 5526 },
  { Author: 'Max',
    '7/2016': 62911,
    '8/2016': 59902,
    '9/2016': 46801 },
  { Author: 'Phil',
    '7/2016': 40233,
    '8/2016': 45060,
    '9/2016': 44902 },
  { Author: 'Tim',
    '7/2016': 61083,
    '8/2016': 68584,
    '9/2016': 70511 } ]
Marc Grabanski
@1Marc
Jan 18 2017 15:49
whoa crazy!
I guess I don't know js as much as I thought I did @xgrommx
Aldwin Vlasblom
@Avaq
Jan 18 2017 15:51
Don't need that first {} in Object.assign @xgrommx - your second argument is a new Object anyway. :)
Denis Stoyanov
@xgrommx
Jan 18 2017 16:13
@Avaq yes, but this way don't mutate objects :smile:
for example: a,b objects and I wanna a new object with merge a,b but I don't want mutation for a,b and I can use it like Object.assign({}, a, b)
Aldwin Vlasblom
@Avaq
Jan 18 2017 16:19
I know, but your argument was already a new object ({Author: v}), so you don't need to worry about mutating shared state. Object.assign will always be a mutation of the first argument. So there is no difference between: Object.assign({}, {a: 1}, b) or Object.assign({a: 1}, b) or Object.assign({}, {}, {}, {}, {a: 1}, {}, b).
The only trouble is if you would Object.assign(b, {a: 1})
Denis Stoyanov
@xgrommx
Jan 18 2017 16:20
I know =)
Aldwin Vlasblom
@Avaq
Jan 18 2017 16:21
You could have saved 4 characters! :scream_cat: ;)
Denis Stoyanov
@xgrommx
Jan 18 2017 16:24
:smile: javascript not rescue
Shane Keulen
@SeeThruHead
Jan 18 2017 20:30
hello all, is there a built in recursive pick? or rather a function that will return the common structure of two input objects
same({
  stage: {
    questions: [],
    url: 'stupd'
  }
}, {
  bob: 'ha',
  stage: {
    url: 'bob'
  }
});
// {
//   stage: {
//     url: 'stupd'
//   }
// }
Shane Keulen
@SeeThruHead
Jan 18 2017 20:36
it's basically an object intersection
Aldwin Vlasblom
@Avaq
Jan 18 2017 22:13
@SeeThruHead There's a recipe for diffing objects in the Ramda cookbook: https://github.com/ramda/ramda/wiki/Cookbook#diffobjs---diffing-objects-similar-to-guavas-mapsdifference