These are chat archives for ramda/ramda

7th
Dec 2016
Travis LaDuke
@laduke
Dec 07 2016 02:07
stuck again:
https://goo.gl/mjCyyy
var favorited = {'a1': {done: true}, 'a2': {done:false}}
var ALL = {'a1': {}, 'a2': {}, 'a3': {}} 
//?liftedMerge(favorite, all) -> {'a1': {done: true}, 'a2': {done:false}, 'a3': {}}
Travis LaDuke
@laduke
Dec 07 2016 02:24
don't make me
var favorited = {'a1': {done: true}, 'a2': {done:false}}
var ALL = {'a1': {}, 'a2': {}, 'a3': {}} 
var res = [];
Object.keys(favorited).forEach(x => ALL[x] = (R.merge(favorited[x], ALL[x])))
ALL
I'll do it man
Rob Halff
@rhalff
Dec 07 2016 02:41
@laduke
{
    ...ALL,
   ...favorited
}
Travis LaDuke
@laduke
Dec 07 2016 06:02
no
Travis LaDuke
@laduke
Dec 07 2016 13:44
Sorry.
hkrutzer
@hkrutzer
Dec 07 2016 14:05
how do I concat more than two arrays?
return R.pipe(
      R.map(thing => thing.someArray),
      R.concatAllThoseArrays
)
is what I want basically
Denis Stoyanov
@xgrommx
Dec 07 2016 14:07
@hkrutzer reduce(concat, [], xs)
hkrutzer
@hkrutzer
Dec 07 2016 14:07
cheers
Denis Stoyanov
@xgrommx
Dec 07 2016 14:08
@hkrutzer [].concat(...map()(xs)) :smile:
without pipe
oh
@hkrutzer chain(t => t.someArray)(xs)
this is just a monad =)
hkrutzer
@hkrutzer
Dec 07 2016 14:13
I'm doing a map after so I'll use chain :)
hkrutzer
@hkrutzer
Dec 07 2016 14:29
R.when(
    e => R.isEmpty(R.prop('keyword', e)),
    R.dissoc('keyword')
  )
Can I make the predicate pointfree?
Denis Stoyanov
@xgrommx
Dec 07 2016 14:31
@hkrutzer compose
@hkrutzer compose(isEmpty, prop('keyword'))
Here’s the code in the link:
var pieces = 'wysextplwqpvipxdv[srzvtwbfzqtspxnethm]syqbzgtboxxzpwr[kljvjjkjyojzrstfgrw]obdhcczonzvbfby[svotajtpttohxsh]cooktbyumlpxostt';
pieces = pieces.split(/\[|\]/);
console.log(pieces)
addIndex(partition)((_,i) => i%2 == 0, pieces)
Travis LaDuke
@laduke
Dec 07 2016 16:21
How do you activate rambot?
Jonah
@jonahx
Dec 07 2016 16:21
not sure, but output is (first line is the console.log, 2nd the output):
["wysextplwqpvipxdv","srzvtwbfzqtspxnethm","syqbzgtboxxzpwr","kljvjjkjyojzrstfgrw","obdhcczonzvbfby","svotajtpttohxsh","cooktbyumlpxostt"]

[["wysextplwqpvipxdv", "syqbzgtboxxzpwr", "obdhcczonzvbfby", "cooktbyumlpxostt"], ["wysextplwqpvipxdv", "syqbzgtboxxzpwr", "obdhcczonzvbfby", "cooktbyumlpxostt”]]
when i create simplified examples, they work
Brad Compton (he/him)
@Bradcomp
Dec 07 2016 16:27
@ram-bot
var pieces = 'wysextplwqpvipxdv[srzvtwbfzqtspxnethm]syqbzgtboxxzpwr[kljvjjkjyojzrstfgrw]obdhcczonzvbfby[svotajtpttohxsh]cooktbyumlpxostt';
pieces = pieces.split(/\[|\]/);
console.log(pieces)
addIndex(partition)((_,i) => i%2 == 0, pieces)
ram-bot
@ram-bot
Dec 07 2016 16:27
console is not defined
Jonah
@jonahx
Dec 07 2016 16:39
after more investigating, i see that it happens whenver the list has an odd number of items:
@ram-bot
addIndex(partition)((_,i) => i%2 == 0, ['a', 'b', 'c', 'd', 'e’])
ram-bot
@ram-bot
Dec 07 2016 16:39
Unexpected token ILLEGAL
Jonah
@jonahx
Dec 07 2016 16:41
@ram-bot
addIndex(partition)((_,i) => i%2 == 0, ['a', 'b', 'c', 'd', 'e'])
ram-bot
@ram-bot
Dec 07 2016 16:41
Unexpected token ILLEGAL
Jonah
@jonahx
Dec 07 2016 16:43
well, that outputs [["a", "c", "e"], ["a", "c", "e”]]. and if you give it an even number of items, it works as expected. is it a bug or my own misunderstanding?
Brad Compton (he/him)
@Bradcomp
Dec 07 2016 16:47
`R.partition
Brad Compton (he/him)
@Bradcomp
Dec 07 2016 16:48
check out the logs
Jonah
@jonahx
Dec 07 2016 16:52
@Bradcomp yeah, i’d noticed that myself too. but i don’t know what to make of it. do you?
Brad Compton (he/him)
@Bradcomp
Dec 07 2016 16:53
R.juxt
Brad Compton (he/him)
@Bradcomp
Dec 07 2016 16:54
I think it has to do with the underlying use of juxt.
Jonah
@jonahx
Dec 07 2016 16:54
so it is a bug?
Brad Compton (he/him)
@Bradcomp
Dec 07 2016 16:54
It iterates over the list twice -> once using filter and then again using reject
So you're index is wrong for the reject partition
Jonah
@jonahx
Dec 07 2016 16:56
but according to the API my usage should be the supported one, no? and the semantics shouldn’t depend on the parity of the list
Brad Compton (he/him)
@Bradcomp
Dec 07 2016 16:57
I would agree with that. Also note that it's wrong in general, not just for odd lists. It's just that it is the parity that matters here
Jonah
@jonahx
Dec 07 2016 16:58
@Bradcomp right
i’ll file an issue
Brad Compton (he/him)
@Bradcomp
Dec 07 2016 16:58
@ram-bot
addIndex(partition)((_,i) => i > 3, 
 ['a', 'b', 'c', 'd', 'e'])
ram-bot
@ram-bot
Dec 07 2016 16:58
[ [ 'e' ], [] ]
Brad Compton (he/him)
@Bradcomp
Dec 07 2016 16:59
:expressionless:
Denis Stoyanov
@xgrommx
Dec 07 2016 17:04
@ram-bot
var r = R.range(1, 11);
R.partition(x=>x%2!==0)(r)
ram-bot
@ram-bot
Dec 07 2016 17:04
[ [ 1, 3, 5, 7, 9 ], [ 2, 4, 6, 8, 10 ] ]
Denis Stoyanov
@xgrommx
Dec 07 2016 17:05
@ram-bot
var r = R.range(1, 11);
R.addIndex(R.partition)((_,x)=>x%3!==0)(r)
ram-bot
@ram-bot
Dec 07 2016 17:05
[ [ 2, 3, 5, 6, 8, 9 ], [ 3, 6, 9 ] ]
Travis LaDuke
@laduke
Dec 07 2016 17:06
@ram-bot
var favorited = {'a1': {done: true}, 'a2': {done:false}}
var ALL = {'a1': {foo: 'z'}, 'a2': {}, 'a3': {bar: 'x'}} 

var mergeKey = (k, l, r) => merge(l,r)
mergeWithKey(mergeKey, ALL,favorited);
ram-bot
@ram-bot
Dec 07 2016 17:06
{ a1: { foo: 'z', done: true },
  a2: { done: false },
  a3: { bar: 'x' } }
Brad Compton (he/him)
@Bradcomp
Dec 07 2016 17:07
@ram-bot
var favorited = {'a1': {done: true}, 'a2': {done:false}}
var ALL = {'a1': {foo: 'z'}, 'a2': {}, 'a3': {bar: 'x'}} 


mergeWith(merge, ALL,favorited);
ram-bot
@ram-bot
Dec 07 2016 17:07
{ a1: { foo: 'z', done: true },
  a2: { done: false },
  a3: { bar: 'x' } }
Travis LaDuke
@laduke
Dec 07 2016 17:07
d'oh. long night
Brad Compton (he/him)
@Bradcomp
Dec 07 2016 17:07
I use mergeWith(merge) fairly often
Travis LaDuke
@laduke
Dec 07 2016 17:08
redux dicts?
Denis Stoyanov
@xgrommx
Dec 07 2016 17:08
@ram-bot
var favorited = {'a1': {done: true}, 'a2': {done:false}}
var ALL = {'a1': {foo: 'z'}, 'a2': {}, 'a3': {bar: 'x'}} 

reduce(merge, {}, [ALL,favorited]);
ram-bot
@ram-bot
Dec 07 2016 17:08
{ a1: { done: true }, a2: { done: false }, a3: { bar: 'x' } }
Brad Compton (he/him)
@Bradcomp
Dec 07 2016 17:08
that and mergeWith(concat) are my two common use cases for mergeWith
Denis Stoyanov
@xgrommx
Dec 07 2016 17:09
@ram-bot
var favorited = {'a1': {done: true}, 'a2': {done:false}}
var ALL = {'a1': {foo: 'z'}, 'a2': {}, 'a3': {bar: 'x'}} 

reduce(mergeWith(merge), {}, [ALL,favorited]);
ram-bot
@ram-bot
Dec 07 2016 17:09
{ a1: { foo: 'z', done: true },
  a2: { done: false },
  a3: { bar: 'x' } }
Brad Compton (he/him)
@Bradcomp
Dec 07 2016 17:09

redux dicts?

Just data processing. Adding new records to a record set while updating the existing ones based on new info, that sort of thing...

Jonah
@jonahx
Dec 07 2016 20:57
Is there a reason ramda doesn’t support empty(Number)? Eg, it seems I should be able to write reduce(add) and it mean the same as reduce(add, 0) just based on the signature of add. Is there a fine point I’m missing that would make this difficult or impossible to do?
LeonineKing1199
@LeonineKing1199
Dec 07 2016 20:59
It doesn't support Boolean either.
Most likely because it doesn't make any philosophical sense for an empty number or boolean.
Jonah
@jonahx
Dec 07 2016 21:01
@LeonineKing1199 yeah I think empty number without context makes no sense (ie, it would be 1 when multiplying, 0 when adding), but it does make sense for the reduce(add) example I gave (I think). Probably should have restricted my question to that.
LeonineKing1199
@LeonineKing1199
Dec 07 2016 21:02
Well, the issue then becomes how do you check if reduce was given the add function?
Brad Compton (he/him)
@Bradcomp
Dec 07 2016 21:03
There are at least two monoid instances for Number: add and multiply.
reduce(add) makes sense as reduce(add, 0), but reduce(multiply) makes more sense as reduce(multiply, 1)
LeonineKing1199
@LeonineKing1199
Dec 07 2016 21:03
You could do a simple reference comparison but that's runtime overhead a library should not enforce on its consumers
Instead, you could create a simple wrapper.
Brad Compton (he/him)
@Bradcomp
Dec 07 2016 21:03
but both add and multiply have the same signature
LeonineKing1199
@LeonineKing1199
Dec 07 2016 21:03
const myReduce = (f) => { if (f === R.add) return R.reduce(R.add, 0); else return R.reduce(f); };
Keep in mind, addition is only monoidal over the set of positive numbers as well.
Or maybe not?
I know subtraction isn't associative
Jonah
@jonahx
Dec 07 2016 21:06
@LeonineKing1199 that makes sense. could you elaborate on your last comment?
*it not being monoidal in some cases
LeonineKing1199
@LeonineKing1199
Dec 07 2016 21:07
Oh, that's irrelevant to the issue at hand.
But monoids are sets closed under an associative binary operation and include an identity element.
You can just google and find all the info you need.
Jonah
@jonahx
Dec 07 2016 21:08
@LeonineKing1199 yeah i know what monoids are, just didn’t understand what you were getting at
LeonineKing1199
@LeonineKing1199
Dec 07 2016 21:08
If you wanted to, you could probably wrap reduce and use something like a switch statement to create the overloads that you desire.
I think switches in JS work with reference comparisons?
Jonah
@jonahx
Dec 07 2016 21:10
@LeonineKing1199 your point about library vs client responsibilities is well taken, though in this case the single check over add and multiply would be extremely light, wouldn’t it? it seems like it would be worth it to me, but i suppose others might disagree
LeonineKing1199
@LeonineKing1199
Dec 07 2016 21:10
Ideally we would implement this branch-free.
Jonah
@jonahx
Dec 07 2016 21:10
how would that be done?
LeonineKing1199
@LeonineKing1199
Dec 07 2016 21:11
I'm not quite sure...
Hmm...
Each function has a toString method so ideally you could use an object with key-value pairs.
Jonah
@jonahx
Dec 07 2016 21:13
isn’t that just branching by another name? (just an implementation detail) without proper types i don’t see how you avoid branching in some way...
LeonineKing1199
@LeonineKing1199
Dec 07 2016 21:13
Maybe?
But this works:
const o = {
  [R.add.toString()]: R.reduce(R.add, 0)
};

const reduceGen = (f) => o[f];

reduceGen(R.add)([0, 1, 2, 3]);
Jonah
@jonahx
Dec 07 2016 21:14
yeah i sort of like it as an implementation, just saying you’re not really avoiding branching.
LeonineKing1199
@LeonineKing1199
Dec 07 2016 21:15
I mean, maybe. Who knows how JS implement objects underneath XD
I'm not reading that much of the V8 API
Jonah
@jonahx
Dec 07 2016 21:15
oh you’re saying it may be faster. yeah it’s possible. i’d guese if and switch would be, but don’t really know either
in any case i don’t think speed matters much here
LeonineKing1199
@LeonineKing1199
Dec 07 2016 21:16
Ah, then it's all good either way. But yeah, I think you can use something like the above to implement reduce with specific default overloads.
Jonah
@jonahx
Dec 07 2016 21:17
yeah, i think i need to start a myRamda module where I put stuff like this, which is personal preference and little tweaks and extra shortcuts
LeonineKing1199
@LeonineKing1199
Dec 07 2016 21:23
But the monoid allusion was to the reduction function, I think. Haskell and JS both have the concept of ordered reductions which is good because at times it's desirable to fold over a range but sometimes order does matter. In the case of monoids, a fold in either direction is equivalent (or so I'm purporting).
Jeff Downie
@JeffDownie
Dec 07 2016 21:27

Is there an issue with R.ap? It seems to be dispatching to the wrong argument - from the description:

Dispatches to the ap method of the second argument, if present.

var o = {
  ap: function(x){
    console.log('CALLED');
    return x;
  }
}
R.ap(o, 1); //CALLED

I searched for an issue but couldn't find it :worried:

LeonineKing1199
@LeonineKing1199
Dec 07 2016 21:30

This is the source:

module.exports = _curry2(function ap(applicative, fn) {
  return (
    typeof applicative.ap === 'function' ?
      applicative.ap(fn) :
    typeof applicative === 'function' ?
      function(x) { return applicative(x)(fn(x)); } :
    // else
      _reduce(function(acc, f) { return _concat(acc, map(f, fn)); }, [], applicative)
  );
});

You can see that it takes the first argument and calls the ap method of that. So you might be right about the docs being out-of-date.

Jeff Downie
@JeffDownie
Dec 07 2016 21:41

So the ap function is/should be called from the Applicative of type f (a -> b)? It's only that it looks like it's the wrong way round compared to the fantasy-land spec, which I thought ramda was using - from their docs: https://github.com/fantasyland/fantasy-land#apply:

a.ap(b)
b must be an Apply of a function

LeonineKing1199
@LeonineKing1199
Dec 07 2016 21:56
You know, I'm not really sure how an applicative interface would work with an OOP flavor.
Haskell seems to emulate C++'s function overloading to meet these kinds of needs.
Denis Stoyanov
@xgrommx
Dec 07 2016 23:00
@JeffDownie f is some container like [], a -> b or Maybe
LeonineKing1199
@LeonineKing1199
Dec 07 2016 23:08
I think he's saying the language is a tad confusing. When I hear "dispatch to the second argument" I kind of assumed what they did which is that the .ap would be called on the second argument, not the first.
LeonineKing1199
@LeonineKing1199
Dec 07 2016 23:18
Isn't the way they do it now, a.ap(b) === b.map(a.value)?
Or is it vice versa?
This is the one time it's nice to have function overloading so you can just do stuff like:
template <typename F, typename T>
auto ap(Maybe<F> f_ab, Maybe<T> f_a) -> Maybe<decltype(F(T))>