These are chat archives for ramda/ramda

16th
Feb 2018
joao@kapmug
@jay-jlm
Feb 16 2018 13:38
Hi, how can I do the same thing using Ramda's pipe?
const myPaths = [ { path: 'foo', type: 'fruit' }, { path: 'bar', type: 'job' }]
const ids = ['fruit:banana:111', 'fruit:apple:222', 'job:waiter:333']
R.filter(R.propEq('type',R.head(R.split(':', ids[0]))), myPaths).map(el=>console.log(el))
basically I need to iterate over 2 lists, however the second one needs to be filtered based on a property the current item of the first list
joao@kapmug
@jay-jlm
Feb 16 2018 13:44
in other words I have a third method that receives say an id of fruit and an array of paths with are relevant to fruits only. So i need to pass each fruit Id with an array of only "fruit paths" to this method that I'm calling
Mike Lambert
@lax4mike
Feb 16 2018 14:00
you have 2 different operations here, R.head(R.split(':', ids[0])) and R.filter(R.propEq("type", "fruit"))
the first can be done like this
const getFirstId = R.compose(
  R.head,
  R.split(":"),
  R.head  
);
console.log(getFirstId(ids))
pipe and compose are the same, except the order
joao@kapmug
@jay-jlm
Feb 16 2018 14:07
hmm
Mike Lambert
@lax4mike
Feb 16 2018 14:08
pipe and compose are for linear compositions
joao@kapmug
@jay-jlm
Feb 16 2018 14:08
I see. since I'm operating on 2 lists I'm not sure if pipe will be able to handle all that.. Here's how I solved with groupBy:
const pathsByType = R.groupBy(el =>  R.prop('type', el))(myPaths) //  mapping of paths to types can be generated upfront, runs only once
const getIdType = id => R.head(R.split(':', id)) //  gets the type from the id
R.map(id => console.log(id, pathsByType[getIdType(id)]))(ids)  //  iterates on ids  and passes the id with the paths that were already mapped to that type
Mike Lambert
@lax4mike
Feb 16 2018 14:12
you can do the first point free
const pathsByType = R.groupBy(R.prop('type'))(myPaths)
joao@kapmug
@jay-jlm
Feb 16 2018 14:12
really?, tried it and it did not seem to work
cool, it worked thanks
Mike Lambert
@lax4mike
Feb 16 2018 14:17
if you want to compose all the things, that last line can be done like this:
R.map(R.compose(
  R.prop(R.__, pathsByType),
  getIdType
));
may or may not be more clear...
joao@kapmug
@jay-jlm
Feb 16 2018 14:20
sure, but I've seen R.map moved to inside the compose/pipe flow before.. can it be done?
Mike Lambert
@lax4mike
Feb 16 2018 14:21
in this case, we want to apply 2 functions to each item, that's why the compose is inside the map
joao@kapmug
@jay-jlm
Feb 16 2018 14:21
I guess with R.pipe( R.map... [and later... ] apply(x))
i think this is what apply/unapply is about... when you functions that operates on a single argument and functions that operate over lists (such as map) and you want to add them into the same data flow?
Mike Lambert
@lax4mike
Feb 16 2018 14:24
hmm
R.apply is a way to apply an array of values as arguments to a function
yeah, i guess if your R.map did some processing to generated arguments that can be used as inputs to another function
R.apply(Math.max, [1, 2, 3])
normally, it's Math.max(1, 2, 3)
but you can also used es6 spread notation to do the same thing Math.max(...[1, 2, 3])
which would make more sense if that array was a variable
joao@kapmug
@jay-jlm
Feb 16 2018 14:29
ok but what about unapply.. for what I can see it makes an unary method accept a list instead? http://ramdajs.com/docs/#unapply
Mike Lambert
@lax4mike
Feb 16 2018 14:31
hmm, i don't thinks so, that's a job for map
unapply requires a function that takes a list, and you can pass in arguments instead const getFirstArg = R.unapply(R.head); getFirstArg(1, 2, 3);
instead of
R.head([1, 2, 3])
joao@kapmug
@jay-jlm
Feb 16 2018 14:33
basically what bothers me is that you two data flow patterns there, one is nested calls map(stuff()) and the other is pipelining/composition... and I've seen some pretty complex data flow which do everything just with composition
without ever resorting to nested function calls, but what do I know :P
Mike Lambert
@lax4mike
Feb 16 2018 14:34
haha yeah, it depends on what your data looks like
there are other combinators, like R.juxt
i guess if your case, you have 2 inputs, so you might be able to leverage R.unapply for something
joao@kapmug
@jay-jlm
Feb 16 2018 14:36
exactly, and zippers.. I was actualy trying to learn about juxt just a couple of days ago, if you scroll back a bit you'll see it.
joao@kapmug
@jay-jlm
Feb 16 2018 17:37
juxt doesn't seem to do what I want.. btw.. it looks like you can only pass as much arguments as the function's arity expects.. I want something like R.app, however i want it to apply the transformation of first function on top of the transformation of the other
oops that may be pipe itself, :D
joao@kapmug
@jay-jlm
Feb 16 2018 17:59
btw, here's a way that I'm using to not lose the initial "id" property as this data goes thru the function pipeline. If there's a more semantic way to do this , please let me know:
R.map(
  R.pipe(
  id => [id, getIdType(id)],
  arr => [arr[0], pathsByType[arr[1]]],
  apply(myMethod)
 )
)(ids)
Brad Compton (he/him)
@Bradcomp
Feb 16 2018 18:02
You could use destructuring, or a data structure to make things clearer. You could also use converge here
joao@kapmug
@jay-jlm
Feb 16 2018 18:02
the goal is to add information along the data flow, but without losing the initial information.. too bad I can only do it with custom functions :-(
ok, looking at converge..
Brad Compton (he/him)
@Bradcomp
Feb 16 2018 18:04
converge(myMethod, [identity, pipe(getTypeId, pathsByType)])
joao@kapmug
@jay-jlm
Feb 16 2018 18:05
whoa, that looks like exactly what I was looking for :D
joao@kapmug
@jay-jlm
Feb 16 2018 18:18
@Bradcomp , pathsByType is not a function thou, it's a map
I wil try with R.prop(R.__, pathsByType)
joao@kapmug
@jay-jlm
Feb 16 2018 18:24
this works... can`t seem to be able to scape the nasty ouside R.map thou, which was my initial goal :-(
R.map(
  R.converge(
    myMethod,
    [R.identity, R.pipe(getIdType, R.prop(R.__, pathsByType))]
  ))(ids)
Mike Lambert
@lax4mike
Feb 16 2018 18:25
the idea behind map is that you can define a function that works on a single item, then you can use map to apply it to a list
joao@kapmug
@jay-jlm
Feb 16 2018 18:25
my idea was to zip the data in a format like this [ [id1, arrOfPaths1], [id2, arrayOfPaths2] ]
this would make the data flow more seamless . So the data follows these formats along the pipeline --> [ id1, id2, id2 ] --- > [ [id1, arrOfPaths1], [id2, arrayOfPaths2] ] ---> [ finalValue1, finalValue2 ]
if I can work with a single list all along, don`t understand why a single compose/pipe cannot do this. without it being nested in a map
well but cant I just call a map in the end, inside the pipe? as long as it's part main outer pipeline I'm fine with calling map
Mike Lambert
@lax4mike
Feb 16 2018 18:31
you have 2 lists
ids and myPaths
joao@kapmug
@jay-jlm
Feb 16 2018 18:32
not really. I have list of pairs
at least that`s what I plan to have :D
joao@kapmug
@jay-jlm
Feb 16 2018 18:39
I wonder why this doesnt work and how to fix it:
R.pipe(
R.zip(R.identity, R.identity)
)(ids)   //  n.apply is not a function
ok, zip is not unary.. so that makes sense
joao@kapmug
@jay-jlm
Feb 16 2018 18:44
hmm... how can I get zip to work out of a single argument?
Mike Lambert
@lax4mike
Feb 16 2018 18:46
R.zip(ids, ids)
zip takes 2 arrays
joao@kapmug
@jay-jlm
Feb 16 2018 18:46
yes but that wont work inside of a composing workflow
Mike Lambert
@lax4mike
Feb 16 2018 18:47
partially apply it with the first array
joao@kapmug
@jay-jlm
Feb 16 2018 18:47
all inside the pipe? how so?
Mike Lambert
@lax4mike
Feb 16 2018 18:47
R.pipe(
  R.zip(ids)
)(ids);
joao@kapmug
@jay-jlm
Feb 16 2018 18:47
hmm
interesting :)
joao@kapmug
@jay-jlm
Feb 16 2018 19:07
@lax4mike , this is a working example of all the data flowing inside the pipeline.. like I mentioned above:
R.pipe(
R.zip(R.map(getIdType, ids)),
R.map(([type, id]) => [id, pathsByType[type]])
)(ids)
so all the operations , including any mapping occur inside the pipe. However, what I still don`t like is how I have to resort to a custom function in step 2 of the pipe :cry:
Mike Lambert
@lax4mike
Feb 16 2018 19:10
looks good :thumbsup:
it's perfectly set up to use R.fromPairs if you want
joao@kapmug
@jay-jlm
Feb 16 2018 19:11
oh of course, forgot about that guy for a sec. So many functions :laughing:
Mike Lambert
@lax4mike
Feb 16 2018 19:12
i wouldn't worry about the custom function, often times, they're much more clear
R.pipe(
  R.zipObj(R.__, R.map(getIdType, ids)),
  R.map(R.prop(R.__, pathsByType)),
)(ids);
something like that
Mike Lambert
@lax4mike
Feb 16 2018 19:21
or maybe something like this:
const getType = R.pipe(getIdType, R.prop(R.__, pathsByType));

const res = R.pipe(
  R.juxt([R.identity, R.map(getType)]),
  R.transpose
)(ids)
a million ways to skin the cat
joao@kapmug
@jay-jlm
Feb 16 2018 19:22
I like it ! I will take a look at how it works
now , how can I do this with ramda??
now, how can I do this with Ramda?
const toPairs( [a, b] ) =>  { path: a,  type:  b }  // R.toPairs doesnt work because I have a list and it's throwing off the duplicated values!
Mike Lambert
@lax4mike
Feb 16 2018 19:26
R.zipObj(["path", "type"], [a, b])
joao@kapmug
@jay-jlm
Feb 16 2018 19:49
:clap:
Andy
@andys8
Feb 16 2018 22:23
Hi, from the documentation of ramdas sourced I'd guess the website is generated. Can somebody hint me to description or the part of the build which generates the site? Thx
Brad Compton (he/him)
@Bradcomp
Feb 16 2018 23:06
I think it's all in here: https://github.com/ramda/ramda.github.io
Shane Keulen
@SeeThruHead
Feb 16 2018 23:07

is there some elegant way of doing this

const blah = res.results
  .reduce((a, b) => [...a, ...b.lexicalEntries], [])
  .reduce((a, b) => [...a, ...b.entries], [])
  .reduce((a, b) => [...a, ...b.senses], [])
  .reduce((a, b) => [...a, ...b.synonyms], [])
  .map(syn => syn.id)

i came up with this but something is nagging me about there being a better way:

const unnestKey = key => R.pipe(pluck(key), unnest);

const trans = R.pipe(
  unnestKey('lexicalEntries'),
  unnestKey('entries'),
  unnestKey('senses'),
  unnestKey('synonyms'), 
  pluck('id')
);

can copy to ramda repl if you want to try it out https://hastebin.com/suluhunogi.js

Shane Keulen
@SeeThruHead
Feb 16 2018 23:24
const R = require('ramda');

const path = [
  'lexicalEntries',
  'entries',
  'senses',
  'synonyms'
];

const flatPath = R.reduce((acc, curr) => R.pipe(acc, R.chain(R.prop(curr))), R.identity);
const trans = R.pipe(flatPath(path), R.pluck('id'));
possibly this