These are chat archives for ramda/ramda

10th
Mar 2017
Gabe Johnson
@gabejohnson
Mar 10 2017 01:20
@piet-v have you looked at https://github.com/blakeembrey/change-case ?
Piet Vandeput
@piet-v
Mar 10 2017 08:20
@gabejohnson looks good, thanx!
Julio Borja Barra
@juboba
Mar 10 2017 08:38
also check out this: https://www.npmjs.com/package/case
Anton Strömkvist
@ahstro
Mar 10 2017 09:47
Is there something in Ramda that does somethign similar to what Recompose's flattenProp does? I.e., R.flattenProp("foobar", { hello: 1, foobar: { hi: 2, hey: 3 } }) // => { hello: 1, hi: 2, hey: 3 }
Anton Strömkvist
@ahstro
Mar 10 2017 10:26
Ended up writing it myself and added to cookbook
Bravi
@Bravilogy
Mar 10 2017 10:30
@ahstro I had to create something similar yesterday. And I came up with this solution:
const spread = converge(merge, [dissoc, prop]);
spread('b', { a: 1, b: { id: 2 } } );
Anton Strömkvist
@ahstro
Mar 10 2017 10:33
Ooh, that's way nicer than what I did! Thanks
Bravi
@Bravilogy
Mar 10 2017 11:32
@ahstro I added this example as well :D
to the repo
Jonas Windey
@jonaswindey
Mar 10 2017 11:56
any know why add() doesn't work when you specify a reference instead of a value?
Denis Stoyanov
@xgrommx
Mar 10 2017 11:59
@ram-bot
var flattenObj = o => {
  var innerFlatten = o => {
    return reduce((a, x) => [].concat(a, x), [], 
                  compose(map(k => is(Object, o[k]) ? innerFlatten(o[k]) : {[k]: o[k]}), keys)(o))
  }
  return mergeAll(innerFlatten(o));
};

flattenObj({ a: 1, b: { id: 2, c:{x:300}} })
ram-bot
@ram-bot
Mar 10 2017 11:59
{ a: 1, id: 2, x: 300 }
Denis Stoyanov
@xgrommx
Mar 10 2017 11:59
deep flatten =)
Denis Stoyanov
@xgrommx
Mar 10 2017 12:09
@ram-bot
var flattenObj = o => {
  var innerFlatten = o => {
    return reduce((a, x) => [].concat(a, x), [], 
                  compose(map(
      ifElse(
        compose(is(Object), flip(prop)(o)), 
        compose(innerFlatten, flip(prop)(o)), 
        ap(objOf, flip(prop)(o)))), keys)(o))
  }
  return mergeAll(innerFlatten(o));
};

flattenObj({ a: 1, b: { id: 2, c:{x:300}} })
ram-bot
@ram-bot
Mar 10 2017 12:09
{ a: 1, id: 2, x: 300 }
Jonas Windey
@jonaswindey
Mar 10 2017 12:17
can anyone check my repl above?
Denis Stoyanov
@xgrommx
Mar 10 2017 12:18
@jonaswindey lens + compose
@ram-bot
var result = {yearTotal: 100}
var value = 100

evolve({yearTotal: add(value)})(result)
ram-bot
@ram-bot
Mar 10 2017 12:21
{ yearTotal: 200 }
Denis Stoyanov
@xgrommx
Mar 10 2017 12:22
@ram-bot
var result = {yearTotal: 100}
var value = 100

over(lensProp('yearTotal'), add(value))(result)
ram-bot
@ram-bot
Mar 10 2017 12:22
{ yearTotal: 200 }
Jonas Windey
@jonaswindey
Mar 10 2017 12:33
cool, finally an example to use lens, thanks ;)
Galileo Sanchez
@galileopy
Mar 10 2017 14:49
I want to apply a function to every element of a list I would use map, but what if I want to apply one different function per each element of a list? is there a name for that?
Drew
@dtipson
Mar 10 2017 14:50
ap on lists will do that
@ram-bot ap([x=>x+1,x=>x*100],[1,2])
ram-bot
@ram-bot
Mar 10 2017 14:51
[ 2, 3, 100, 200 ]
Galileo Sanchez
@galileopy
Mar 10 2017 14:51
ap would apply all elements of the function list to every element of the argumetns list
Drew
@dtipson
Mar 10 2017 14:51
ohhh
so more like a zip?
Galileo Sanchez
@galileopy
Mar 10 2017 14:52
yeah, something like that
zipAp? xD
what useWith does with its argumetns, per every fn on the first list apply it only on the corresponding argument of the other list
Drew
@dtipson
Mar 10 2017 14:55
@ram-bot map(([f,x])=>f(x),zip([x=>x+1,x=>x*100],[1,2]))
ram-bot
@ram-bot
Mar 10 2017 14:55
[ 2, 200 ]
Drew
@dtipson
Mar 10 2017 14:55
probably not the cleanest/right way to do it though, very positional/bespoke
Galileo Sanchez
@galileopy
Mar 10 2017 14:56
@dtipson exactly that, I was wondering if that pattern has a name?
Drew
@dtipson
Mar 10 2017 14:56
yeah idk: I suspect that there's probably a more fundamental, general pattern there
Galileo Sanchez
@galileopy
Mar 10 2017 14:57
is there a function that takes a function and a argument and applies the function to the argument?
Johnny Hauser
@m59peacemaker
Mar 10 2017 15:04
How would I do this point free with Ramda?
const needsBuild = service => service.image && typeof service.image === 'object' && !isNil(service.image.tags)
Galileo Sanchez
@galileopy
Mar 10 2017 15:06
@dtipson const zipAP = compose(map(apply(call)), zip);
@ram-bot xprod([1,2],[1,2])
Stefano Vozza
@svozza
Mar 10 2017 15:09
@m59peacemaker
const needsBuild = R.both(R.compose(R.not, R.isNil, R.path(['image', 'tags'])), R.compose(R.is(Object), R.prop('image')))
Galileo Sanchez
@galileopy
Mar 10 2017 15:09
This message was deleted
Jack Leigh
@leighman
Mar 10 2017 15:12
@galileopy zipWith(call)(fns)(xs)
Gabe Johnson
@gabejohnson
Mar 10 2017 15:13
@piet-v :thumbsup:
Drew
@dtipson
Mar 10 2017 15:15
nice
Johnny Hauser
@m59peacemaker
Mar 10 2017 15:16
@svozza ahh so obvious now that I see it
and the second part is kind of redundant, unless someone does var x = {image: 'some-string'}; x.image.tags = whatever
Drew
@dtipson
Mar 10 2017 15:21
@ram-bot zipWith(call)([x=>x+1,x=>x*100])([1,2])
ram-bot
@ram-bot
Mar 10 2017 15:21
[ 2, 200 ]
Johnny Hauser
@m59peacemaker
Mar 10 2017 15:22
nm, that's invalid (thankfully). I thought I remember it being possible to add properties to strings like that (which would evil).
oh yeah, I was thinking of new String('foo').bar = 'fail'
Stefano Vozza
@svozza
Mar 10 2017 15:25
i always find myself vacilating between wanting x => x != null in core. it seems so simple but R.compose(R.not, R.isNil) is a lot of cruft just to check whether something exists or not
but then i think that there's enough functions in ramda as it is
without adding something like R.exists
Johnny Hauser
@m59peacemaker
Mar 10 2017 15:26
I think it would be good for there to be an npm namepsace for ramda, and then make it all super modular
@r/exists
@r/not @r/isNil
and have all the cookbook recipes as modules
Galileo Sanchez
@galileopy
Mar 10 2017 15:31
@leighman cool
Galileo Sanchez
@galileopy
Mar 10 2017 15:36
I have a hexstring parser that currently defines fields and the transformations to perform on those fields, something like const name = field(start, size, hexToAscii) (message), I wonder if I should separate the transformation function and just use compose( hexToAscii, slice(start, end)), I don't have any good criteria to see which one is more flexible
I'm actually working on buffers, but the idea still holds, instead of complecting the field definition with a transformation, I think it is simpler to just define the offset, length, and let the transformation appear later?
Rónán
@ronanyeah
Mar 10 2017 16:36
@svozza or R.complement(R.isNil). still pretty crufty :)
Brad Compton (he/him)
@Bradcomp
Mar 10 2017 16:42
For the obvious case of filtering, you can alwayse just:
R.reject
Brad Compton (he/him)
@Bradcomp
Mar 10 2017 16:42
instead. Of course that's only one use case...
Johnny Hauser
@m59peacemaker
Mar 10 2017 16:42
Oh yeah!
Robert Mennell
@skatcat31
Mar 10 2017 17:10

any know why add() doesn't work when you specify a reference instead of a value?

https://github.com/ramda/ramda/blob/v0.23.0/src/add.js

As you can see it will take a number, make a new number. This will NOT modify the internal value. You'd have to do

@ram-bot const result = {yearTotal: 100};const value = 100;result.yearTotal = add(prop('yearTotal', result), value);

@ram-bot const result = {yearTotal: 100};const value = 100;result.yearTotal = add(prop('yearTotal', result), value);
ram-bot
@ram-bot
Mar 10 2017 17:11
200
Denis Stoyanov
@xgrommx
Mar 10 2017 17:16
@galileopy probably u need ZipList. This applicative with zipping behavior https://github.com/xgrommx/practical-functional-programming/blob/master/zip-list.js
Galileo Sanchez
@galileopy
Mar 10 2017 17:17
cool, thanks @xgrommx
Denis Stoyanov
@xgrommx
Mar 10 2017 17:17
@skatcat31 he need to modify object
Robert Mennell
@skatcat31
Mar 10 2017 17:19
@xgrommx right, so you'd either need to reassign it, like I did, or use a lense. result.yearTotal = add(prop('yearTotal', result), value) skips the lense to modify it directly.
Denis Stoyanov
@xgrommx
Mar 10 2017 17:20
@skatcat31 lens is a normal approach or evolve
Robert Mennell
@skatcat31
Mar 10 2017 17:21
pretty much. I actually had another response that specified lense as a viable option, but when I noticed it had been answered I was in the process of deletes my responses when I could not longer delete the first 2
Galileo Sanchez
@galileopy
Mar 10 2017 17:23

@xgrommx what woud be your intution in this context ?

I have a hexstring parser that currently defines fields and the transformations to perform on those fields, something like const name = field(start, size, hexToAscii) (message), I wonder if I should separate the transformation function and just use compose( hexToAscii, slice(start, end)), I don't have any good criteria to see which one is more flexible

Denis Stoyanov
@xgrommx
Mar 10 2017 17:24
@galileopy if u like it - please do =)
Galileo Sanchez
@galileopy
Mar 10 2017 17:27
@xgrommx o.O
Stefano Vozza
@svozza
Mar 10 2017 18:18
@ronanyeah that is better but yeah, still feels like overkill
Robert Mennell
@skatcat31
Mar 10 2017 18:50
@svozza compliment(isNil) seems like the best readable version since it tells you you're using the compliment of a null check, which is a not null check. Exist is a slightly different context since I can have Object.hasOwnProperty('isSetNull') that will be true. Sometimes you actively WANT a null property, and in that case exist is very different
Galileo Sanchez
@galileopy
Mar 10 2017 22:18
I was thinking in implementing a buffer parser in a way that allows composition of different kind of parsing functions over the same data input, one way i thought of if, that any function returns an object with a name the function defines for its field and merges it with it's input, and the initial value would be {unparsedMessage: buffer}, so one way of using ti woul be
headerParser = ( compose(lensOver(lensProp('header'), extractData), lensOver(lensProp('unParsedMessage'), slice(headerStart, headerEnd)))
dataParser =  compose(lensOver(lensProp('data'), extractData), lensOver(lensProp('unParsedMessage'), slice(dataStart, dataEnd)))
parser = compose(dataParser, headerParser)
the other way I thought of
is to use an object that specifies the fields, and have a field parser that slices the buffer and process it, and then returns only its value, then write functions to assoc it to its corresponding fields
which is the way I am implementing right now
however I think the other approach might me more flexible in some situations
but I am no sure
since I would need to parse an awful lot if different input buffers all in different formats, I would like this to be as flexible as possible
in a way that I would quickly allow me to define new input formats and the corresponding functions that it would need to run on each field
without affecting readability
Galileo Sanchez
@galileopy
Mar 10 2017 22:24
wich I think the object based approach would be easy to read for other people to understand how to do it or how to alter it
Can I ask this kind of questions to strangers? o.O or is it something I should discuss with my coworkers?
Galileo Sanchez
@galileopy
Mar 10 2017 23:25
https://goo.gl/JqGbY2 an improved version
https://goo.gl/IubwiX sorry had to tidy up some bits