These are chat archives for ramda/ramda

25th
Jul 2017
Artūras Zakrevskis
@AZakrevskis_twitter
Jul 25 2017 13:20
@rickmed thank you, as much as I read about point free now, it seems that most think it is a good practice, but you say that in this case it is not desirable and I do agree with your opinion.
Bravi
@Bravilogy
Jul 25 2017 15:14

looking at
https://github.com/ramda/ramda/blob/master/src/anyPass.js

is there a reason why anyPass takes the first initial parameter first and that we cannot pass both params on an initial call?

i.e. using it like anyPass([fn1, fn2], 'hello')
I'm currently using uncurryN(2, anyPass) to solve this, but just wondering what's the idea behind using _curry1 instead of _curryN as in other functions
Robert Mennell
@skatcat31
Jul 25 2017 16:12
@Bravilogy why would you use any pass with both predicate and data to test? This sounds like a library function, one that doesn't make sense to pass predicates at runtime because you, the developer, will ALWAYS know what the predicate are. It's very improbible that you'd have a predicate supplied by the user.
Bravi
@Bravilogy
Jul 25 2017 16:14
actually, I'm trying to use it with useWith like so:
const smth = useWith(anyPass, [ map(test), identity ]);
I have an array of regexes I wanted to test an input against
but I get I could use compose(anyPass, map(test)) instead
Robert Mennell
@skatcat31
Jul 25 2017 16:21
why wouldn't you anyPass against the regex?
or is the regex transformational?
Robert Mennell
@skatcat31
Jul 25 2017 16:31
const strings = ['abx', 'axx', 'xbx', 'xxx']
const hasAorB = R.anyPass( [ R.test( /a/i ) , R.test( /b/i ) ] )
const stringsWithAorB = strings.filter(hasAorB) // ["abx", "axx", "xbx"]
Bravi
@Bravilogy
Jul 25 2017 16:32
regex is actually dynamic
Robert Mennell
@skatcat31
Jul 25 2017 16:32
is it use supplied?
Bravi
@Bravilogy
Jul 25 2017 16:32
it is read from the config file
Robert Mennell
@skatcat31
Jul 25 2017 16:32
then you know it before hand don't you?
Bravi
@Bravilogy
Jul 25 2017 16:33
yeah, but what I was trying to do was to have it in a compact function :D
Robert Mennell
@skatcat31
Jul 25 2017 16:35
yes, but that function gets recompiled everytime you get to that line of const hasAorB. A lot of Ramdas ideas is that you use it to build your functions in a library, and then import and use your library. Declaring functions relying on ramda in run space means they get re evaluated, and remade everytime your function is called, much like closures. If these functions are static and can be created at runtime, you can save you lot of time creating them there instead
then your function later reads like a storybook
Bravi
@Bravilogy
Jul 25 2017 16:35
yeah, I can see the benefits of it of course
Robert Mennell
@skatcat31
Jul 25 2017 16:37
router.get('/', function( rq, rs, nx ){
    fetch_data( id ).then( makeReturn ).then( res.end.bind(res) ).then( nx );
}
fetch_data and makeReturn are your library functions. These mean that you maintain them outside your route, and updating your route is as simple as using a different fetch function, updating your library in a single place ot update all routes that use it, or so forth and onward
Denis Stoyanov
@xgrommx
Jul 25 2017 16:39
I use it now
app.route(‘/route’).get(async (req, res) => {…})
Robert Mennell
@skatcat31
Jul 25 2017 16:41
man I wish we were allowed ot use a newer version of node. We use Bluebird.coRoutine(function*(...){...})...
I mean same difference?
Sten-H
@Sten-H
Jul 25 2017 16:44
Is there a function that does this: R.mergeArraysWith(R.subtract, [4, 2], [2, 2]) => [2, 0] Basically mergeWith but for arrays? I feel dumb
Denis Stoyanov
@xgrommx
Jul 25 2017 16:45
@Sten-H zipWith(subtract) :smile:
Sten-H
@Sten-H
Jul 25 2017 16:45
mergeWith returns an indexed objet, i'd like to get an array
Aha! Of course!
Robert Mennell
@skatcat31
Jul 25 2017 16:46
flerp! forget merge is objects
... I always forget that in JS Array instanceof Object
XD was expecting if I was wrong for Ramda to throw and yell at me
Bravi
@Bravilogy
Jul 25 2017 16:56

ok another question :D

let subs = [
  { id: "596621f3fe986c287020a647", subscribed_user_count: 10},
  { id: "3717181e986c287020a647", subscribed_user_count: 10},
];

let groups = [
  { id: "596621f3fe986c287020a647", ss: 11},
  { id: "3717181e986c287020a647", ss: 12},
];

I'd like to merge with two arrays on prop('id')

something like
https://goo.gl/Dhsa4y

Bijoy Thomas
@bijoythomas
Jul 25 2017 17:00
@Sten-H R.zipWith(R.subtract, [4, 2], [2, 2]) ?
Sten-H
@Sten-H
Jul 25 2017 17:00
@bijoythomas yep that was it :)
Denis Stoyanov
@xgrommx
Jul 25 2017 17:02
@Bravilogy what do u want to get? do u have expected result?
Bravi
@Bravilogy
Jul 25 2017 17:04
ok one option:
const fn = useWith(zipWith(merge), [sortBy(prop('id')), sortBy(prop('id'))]);
Sten-H
@Sten-H
Jul 25 2017 19:52
Is it possible to make a pattern like this point free? (x) => R.add(R.prop('wins', x), R.prop('losses', x)
Robert Mennell
@skatcat31
Jul 25 2017 19:54
converge(add, [prop('wins'), prop('losses')])({wins:1, losses:2})
Sten-H
@Sten-H
Jul 25 2017 19:55
@skatcat31 Interesting! Thanks :)
Denis Stoyanov
@xgrommx
Jul 25 2017 19:56
or lift
Robert Mennell
@skatcat31
Jul 25 2017 19:57
@xgrommx why would you use lift over converge in this case?
Denis Stoyanov
@xgrommx
Jul 25 2017 19:58
o(sum)(props([‘wins’, 'losses']))({wins:1, losses:2})
Robert Mennell
@skatcat31
Jul 25 2017 20:03
pipe(props(['wins','losses']), sum)({wins:1, losses:2}) for that matter as well. I find it interesting that o is like a compose for the specific case of one functions output into a next function, and only 1
useful in these exact cases of pipes or composes to a single 1
Denis Stoyanov
@xgrommx
Jul 25 2017 20:05
I dislike this reversed direction for normal understanding pipeline for functions
Robert Mennell
@skatcat31
Jul 25 2017 20:07
pipe is order of steps, compose is order of composition
depends on taste, but both do the same. It depends on if you like reading it as I want to do this, then this or I want to do this of this(pipe(g,f,x) == f(g(x)) , compose(f,g,x) == f(g(x)))
eventually I stopped looking at either, I just grab pipe becuase of underlying code(prevent a reverse) https://github.com/ramda/ramda/blob/v0.24.1/src/compose.js
Denis Stoyanov
@xgrommx
Jul 25 2017 20:13
sorry man))) but I know about all of u talk me
Robert Mennell
@skatcat31
Jul 25 2017 20:14
huh?
Robert Mennell
@skatcat31
Jul 25 2017 20:32
Still kind of confused how lift works... If I'm reading it correctly it's for making a function an apply?
Sten-H
@Sten-H
Jul 25 2017 20:33
I found both lift and "o" a little confusing. Think I understand o now atleast
Robert Mennell
@skatcat31
Jul 25 2017 20:35
If I'm reading this right, lift would be useful in that you can make an apply of a function lift(add)([1,2],[2,4]) == [3,5,4,6]
lift(concat)(['1','2'],['a','b'])
better example
Sten-H
@Sten-H
Jul 25 2017 20:39
aaah, good one I was just sitting trying to figure out how it was adding the number haha
Angel J Piscola
@Redmega
Jul 25 2017 20:41
When I R.map() through an object if I do console.log it is the key;s value but if I try to just use the return from the map its the object itself with keys. I just want the values, how do I do this? R.map(o=>o)(obj) doesn't work, it returns the object instead of an array of the values
Never mind, values exists
Returns a list of all the enumerable own properties of the supplied object. Note that the order of the output array is not guaranteed across different JS platforms.
Let's say I have the keys as col1, col2, etc. Do I have to sort afterwards to ensure order or is there an alternative that will ensure order?
Robert Mennell
@skatcat31
Jul 25 2017 20:46
this one will probably be slowed than values... it takes an object, makes it into an array of [k,v], then sorts that array based on head(key), then takes the second arguments of each, then flattens the array
s oif order doesn't matter, values. If order matter, this
Angel J Piscola
@Redmega
Jul 25 2017 20:47
the value is an array so flatten messes with that. I need the arrays to stay in tact
Hmm
Robert Mennell
@skatcat31
Jul 25 2017 20:47
you need the arrays ot stay in tact?
Angel J Piscola
@Redmega
Jul 25 2017 20:48
Let me build a use case in repl
Will it do the goo.gl on its own?
Got it
Angel J Piscola
@Redmega
Jul 25 2017 20:53
I think I just realized my question was silly
I should be able to just use the map on that for my purposes
Sten-H
@Sten-H
Jul 25 2017 20:59
https://goo.gl/PLiatx I really feel like the winRatio function here should also be able to be pointfree just like we made the total games function but I just can't wrap my head around it. Now we're doing different things with the variable which I think complicates it?
Angel J Piscola
@Redmega
Jul 25 2017 21:03
Is there a way to get the key or index from R.map() on an object?
Never mind, mapObjIndexed exists
Robert Mennell
@skatcat31
Jul 25 2017 21:06
you have two functions you want to converge into a single function
well you have N functinos you want to converge as input for a final function
Sten-H
@Sten-H
Jul 25 2017 21:07
Oh darn I forgot about converge and it was less than an hour since I learned about it haha, thanks so much
Sten-H
@Sten-H
Jul 25 2017 21:14
converge(add, [multiply(2), add(3), add(5)])(1) => 6 it only seems to take the first two evaluated function from the list, I seem to be misunderstanding how it works. Like you said its supposed to take N functions
Ooooh, is it that add only takes two arguments
Robert Mennell
@skatcat31
Jul 25 2017 21:15
converge(pipe(Array, sum), [multiply(2), add(3), add(5)])(1) // 12
sum is like add, but requires an array
Denis Stoyanov
@xgrommx
Jul 25 2017 21:16
compose(sum, sequence(always))([multiply(2), add(3), add(5)]))(1)
Sten-H
@Sten-H
Jul 25 2017 21:16
Yeah I tried with sum, but didn't figure out the cast to Array, I'm starting to understand
Robert Mennell
@skatcat31
Jul 25 2017 21:17
:+1000: for sequence. I keep forgetting that
Denis Stoyanov
@xgrommx
Jul 25 2017 21:17
compose(sum, sequence(always, [multiply(2), add(3), add(5)]))(1)
compose(sum, juxt([multiply(2), add(3), add(5)]))(1)
Bijoy Thomas
@bijoythomas
Jul 25 2017 21:37
how does this work sequence(always, [multiply(2), add(3), add(5)])? Its turning an array of functions into a function of array (treating function as applicative?)
Robert Mennell
@skatcat31
Jul 25 2017 21:38
try supplying ths last arguemnt: sequence(always, [multiply(2), add(3), add(5)])(2) // [4,5,7]
Denis Stoyanov
@xgrommx
Jul 25 2017 21:38
@bijoythomas [a -> a] -> a -> [a] maybe this one
like a m (t a) -> t (m a)
Bijoy Thomas
@bijoythomas
Jul 25 2017 21:40
@skatcat31 thanks .. I get what its doing .. trying to grok how its doing it :-)
Robert Mennell
@skatcat31
Jul 25 2017 21:40
@bijoythomas ah, thoguht you didn't know what it was doing
Bijoy Thomas
@bijoythomas
Jul 25 2017 21:43
thanks @xgrommx , so [a -> a] -> a -> [a] is saying given array of functions from a -> a and then given an a, its returning [a] .. I get that .. but trying to understand your code with the description of sequence: turning a traversable of applicative into an applicative of traversable
Denis Stoyanov
@xgrommx
Jul 25 2017 21:43
@bijoythomas yes =)
Robert Mennell
@skatcat31
Jul 25 2017 21:48
sequence(always, [concat('a')])('b') != sequence(identity, [concat('a')])('b') I'm confused by this case. The one with identitity errors out
Bijoy Thomas
@bijoythomas
Jul 25 2017 21:53
I think its because the first arg to sequence should be like a function that wrap its arg in the context .. that's why in the sequence examples, it uses Maybe.of which when invoked sort of boxes the value in a Just. always boxes the arg in a function.
Denis Stoyanov
@xgrommx
Jul 25 2017 21:54
u can use juxt instead of sequence(always)
Angel J Piscola
@Redmega
Jul 25 2017 22:22
my hasPathsfunction is giving me a headache... Does anyone know of a more legible way to write that? https://goo.gl/gh5SDp I'm trying to match if any values in a nested array match the path of a different object
Angel J Piscola
@Redmega
Jul 25 2017 22:30
any(ignoreKeyValuePair => any(value => pathEq(ignoreKeyValuePair.path,value)(request))(ignoreKeyValuePair.values));
Angel J Piscola
@Redmega
Jul 25 2017 22:39
anyPass accepts an array of functions which are passed a value and must return true, right? In this case I only have one predicate, its just nested a few levels down
must return true/false rather
Robert Mennell
@skatcat31
Jul 25 2017 22:44
you had two valid options, so you could split it into two cases on the same path. There should be a better way to do it, but this is at least a straight foreward way
other option would pipe the path into a predicate
Sten-H
@Sten-H
Jul 25 2017 22:46
If I have two arrays namesArr and valuesArr what would be a nice way to output that as an array of {name: 'name', value: 'value'} objects? My first step was doing map(pair('name'), namesArr) and map(pair('value'), valuesArr) but then I got kind of stuck, was toying a bit with zipObj but doesn't seem right
Robert Mennell
@skatcat31
Jul 25 2017 22:47
Angel J Piscola
@Redmega
Jul 25 2017 22:48
@skatcat31 The thing is the globalOptions is coming from some config. We can't just stick it in the test directly
That path can be configured per server, per instance, etc
And so can the expected values
Robert Mennell
@skatcat31
Jul 25 2017 22:51
if it's a RegExp for testing, those can be stored in strings
if it's a different type of predicate then it may have ot be adjusted
Angel J Piscola
@Redmega
Jul 25 2017 22:52
hmm
Robert Mennell
@skatcat31
Jul 25 2017 22:55
if it's an array of strings to test against, strings to a regex pattern is pretty simple too
Sten-H
@Sten-H
Jul 25 2017 22:59
@skatcat31 Ok zipWith was what I was using originally. Felt a bit imperative or explicit to zipWith something like (n,v) => {name: n, value: v} I guess I'm gettting spoiled by all the fancy functions I keep finding :)
Robert Mennell
@skatcat31
Jul 25 2017 23:00
@Redmega https://goo.gl/nPdG9k this needs soem refactoring to be more general, but it shows an example of constructing a regex from strings
Angel J Piscola
@Redmega
Jul 25 2017 23:00
@skatcat31 Ok I went with what you said, now I have this... Is there any way to get rid of that o => validBody(o)(request)? https://goo.gl/zJGiAL
We can control the global options and their format, just not the fact that it has to be separate
So you went a bit overboard with that
thanks tho :joy: I appreciate the help
I just don't like the o => but if thats the only way I can do it I'm ok with leaving it there.
Robert Mennell
@skatcat31
Jul 25 2017 23:02
http://ramdajs.com/docs/#allPass if all tests need to pass. So you could make a function to make the sets of tests, and then run it against EACH test
Angel J Piscola
@Redmega
Jul 25 2017 23:04
Not all, just any
I changed the regex to use | too just because they'd be entered as separate values.
I think the last link I shared is good enough for our purposes
Robert Mennell
@skatcat31
Jul 25 2017 23:08
@Redmega https://goo.gl/8PLDVJ takes the ignoreKeyValuePairs, and constructs your pipe form the objects
then just shove it through an anyPass should htere be more than one test
line 30 can also be written as const tests = map(toTest)(globalOptions.ignoreKeyValuePairs)
Angel J Piscola
@Redmega
Jul 25 2017 23:10
Oh cool
Robert Mennell
@skatcat31
Jul 25 2017 23:10
oh wait I forget ot make it a predicate
should have fixed it
instead of always returning true
nope... something is broken there
probably the way I'm reducing to a regex
Angel J Piscola
@Redmega
Jul 25 2017 23:13
hmm
Is there a way to see the output of the reduce
Actually a join with | as the separator would be better no?
@skatcat31 I think I did it! https://goo.gl/cvj78B
You had value instead of values
Robert Mennell
@skatcat31
Jul 25 2017 23:18
DERP! also nice on the join('|')
Angel J Piscola
@Redmega
Jul 25 2017 23:19
So pipe passes values from left to right, yeah?
Robert Mennell
@skatcat31
Jul 25 2017 23:19
I'd also suggest extracting validRequest to anyPass(tests) so you can call it other places:
const tests = map(toTest)(globalOptions.ignoreKeyValuePairs)

const validRequest = anyPass(tests)

validRequest(request) // true
Angel J Piscola
@Redmega
Jul 25 2017 23:20
opposite of compose
so you can use either one
just make sure you put them in the right order
Angel J Piscola
@Redmega
Jul 25 2017 23:26
how can I test performance on these different ways of doing this?
Robert Mennell
@skatcat31
Jul 25 2017 23:29
I'm curious what you mean?
Angel J Piscola
@Redmega
Jul 25 2017 23:30
Hold on, setting something up..
Angel J Piscola
@Redmega
Jul 25 2017 23:40
https://goo.gl/qpqowJ Are these accurate?
This will be running once per request so I think any savings is good
Angel J Piscola
@Redmega
Jul 25 2017 23:45
Thoughts @skatcat31 ?
Robert Mennell
@skatcat31
Jul 25 2017 23:52
updated console logs for better comparison https://goo.gl/xe9gTU
constantly running it shows more compariable results
either way it's taking a THOUSAND TIMES for such a small difference, the only one I would say to avoid is hasIgnorePairs?
Sten-H
@Sten-H
Jul 25 2017 23:58
https://goo.gl/VSK9oW there's something about that trailing (arr2) at the end of the compose of this function definition that feels wrong but without it I can't use it both as a partial function and regularly. Is this just how it looks?