These are chat archives for ramda/ramda

23rd
Sep 2015
joneshf-work1
@joneshf-work1
Sep 23 2015 00:41
you could chain with append so you don't end up having to flatten at the end.
or just go raw dawg with the reduce
but probably you want a different data structure if you're really concerned about that.
R.pipe(
  R.splitEvery(2),
  R.chain(R.append({locale: 'thinginserted', value: 'thinginserted'}))
);
or something
line up the types if I'm not right.
or maybe apeture?
no, not that.
wonderdogone
@wonderdogone
Sep 23 2015 00:45
im surprised. It should be some kind of insert
joneshf-work1
@joneshf-work1
Sep 23 2015 00:47
what makes you say that?
wonderdogone
@wonderdogone
Sep 23 2015 00:48
append does not work because it needs to be at a specified key throughout
joneshf-work1
@joneshf-work1
Sep 23 2015 00:50
xs = [{foo: 1}, {foo: 2}, {foo: 3}, {foo: 4}, {foo: 5}]
JSON.stringify(R.chain(R.append({bar: 7}), R.splitEvery(2, xs)))
"[{"foo":1},{"foo":2},{"bar":7},{"foo":3},{"foo":4},{"bar":7},{"foo":5},{"bar":7}]"
wonderdogone
@wonderdogone
Sep 23 2015 00:51
ahhs wet
sweet
so its appended at each split
i see
joneshf-work1
@joneshf-work1
Sep 23 2015 00:52
wel lthe last one gets one too
so it's not entirely correct.
wonderdogone
@wonderdogone
Sep 23 2015 00:52
yea but thats alright
yea but thats close
nice
one
cleaner then splitevery, then map.insert
Scott Christopher
@scott-christopher
Sep 23 2015 00:55
If you don't want the extra one on the end, you should alternatively be able to
pipe(splitEvery(n), intersperse([thing]), unnest)
joneshf-work1
@joneshf-work1
Sep 23 2015 00:55
even better
wait, does intersperse exist?
Scott Christopher
@scott-christopher
Sep 23 2015 00:56
Yep
joneshf-work1
@joneshf-work1
Sep 23 2015 00:56
holy smokes
David Chambers
@davidchambers
Sep 23 2015 00:57
Very nice, @scott-christopher!
Scott Christopher
@scott-christopher
Sep 23 2015 01:01
I'm intrigued to know what aperture can be used for.
It seems an oddly specific function to exist in Ramda.
joneshf-work1
@joneshf-work1
Sep 23 2015 01:02
rolling average is what I've used it for in the past.
Scott Christopher
@scott-christopher
Sep 23 2015 01:02
Yeah, I assumed something streamy
Scott Sauyet
@CrossEye
Sep 23 2015 01:03
called chunk elsewhere.
joneshf-work1
@joneshf-work1
Sep 23 2015 01:03
it's a bit comonadic, so there's probably all kinds of stuff you can do with it.
Scott Sauyet
@CrossEye
Sep 23 2015 01:03
Just breaks into equal-sized partitions. A less powerful version of Clojure's partition.
I haven't really used it, but we had three or four separate requests for the functionality.
Scott Christopher
@scott-christopher
Sep 23 2015 01:07
And the penny drops that it's just a sliding window over lists. :|
joneshf-work1
@joneshf-work1
Sep 23 2015 01:07
:)
I ugess not a bit comonadic, but actually comonadic.
aperture = function(n) {
  return R.pipe(
    R.extend(R.identity),
    R.map(R.take(n)),
    R.filter(R.pipe(R.length, R.gt(R.__, n)))
  );
};
or something
well, I guess assuming extend existed in ramda :X
erm, I guess not totally, since tyou have to be able to filter...
infact, just forget it all.
Scott Christopher
@scott-christopher
Sep 23 2015 01:11
I was hoping to finally gain some magical insight and grok comonads for a moment there :D
Scott Sauyet
@CrossEye
Sep 23 2015 01:12
I've given up on that for now!
hemanth.hm
@hemanth
Sep 23 2015 06:31
one more step towards ES6 -> ramda/ramda#1398
Ludwig Magnusson
@TheLudd
Sep 23 2015 11:03
I want to use where but instead of requiering the object to pass all predicates, I only want to require one predicate to pass. Is there a function for this?
Raine Virta
@raine
Sep 23 2015 11:04
propSatisfies?
or do you want to pass same predicate for multiple properties?
Ludwig Magnusson
@TheLudd
Sep 23 2015 11:08

That is just for one prop right?
What I want is:

var specObj = {
  name: strContains('Alice'),
  email: strContains('gmail')
}

var obj1 = {
  name: 'Alice',
  email: 'alice@hotmail.com'
}

var obj2 = {
  name: 'Bob',
  email: 'bob@gmail.com'
}

Both obj1 and obj2 should pass because they have at least one prop satisfying a part of the spec

Raine Virta
@raine
Sep 23 2015 11:09
okay, now I see
Ludwig Magnusson
@TheLudd
Sep 23 2015 11:16
I think I will map the predicates against the values and then do any on the values
Aldwin Vlasblom
@Avaq
Sep 23 2015 11:21
@TheLudd I liked the challenge - the first thing I came up with, seems pretty long for a simple request but here it is (http://goo.gl/NFDyjo):
//whereAny :: Object -> Object -> Boolean
let whereAny = R.useWith(R.anyPass, R.pipe(R.toPairs, R.map(R.pipe(R.reverse, R.apply(R.propSatisfies)))), R.identity);
Raine Virta
@raine
Sep 23 2015 11:31
const { curry, anyPass, toPairs, map, flip, propSatisfies, apply } = require('ramda');
const strContains = curry((needle, haystack) => haystack.indexOf(needle) >= 0);

const whereAny = curry((spec, obj) =>
  anyPass(map(apply(flip(propSatisfies)),
              toPairs(spec)),
          obj)
);

whereAny({
  name: strContains('Alice'),
  email: strContains('gmail')
}, {
  name: 'Alice',
  email: 'bar'
})
Ludwig Magnusson
@TheLudd
Sep 23 2015 11:33
@Avaq That might work but it seems very unreadable to me. I would unwrap it a bit
Aldwin Vlasblom
@Avaq
Sep 23 2015 11:34
Raine did a very similar thing. He flips argument order, I flip arguments. Same difference. I replaced my lambda with useWith to make it pointfree, but it's probably more readable the way raine did it, with the lambda.
Raine Virta
@raine
Sep 23 2015 11:35
yeah we came up with pretty similar solutions independently
Aldwin Vlasblom
@Avaq
Sep 23 2015 11:36
:)
Ludwig Magnusson
@TheLudd
Sep 23 2015 11:40
I could of course just look at where and write a similair function that only requires one match
That might be the simplest =)
Aldwin Vlasblom
@Avaq
Sep 23 2015 11:41
But then you're treading in imperativeland! Oh no! :o
@raine It would be nicer if we came up with a solution in which anyPass is given its first argument as soon as whereAny is given its first argument, so that when you make a contract like let contract = whereAny({foo: equals("bar")}) the computation from spec -> anyPass(...) doesn't have to be executed every time the contract is called with an object. That doesn't already happen in either of our solutions, right?
Raine Virta
@raine
Sep 23 2015 11:56
@Avaq, for performance reasons?
Aldwin Vlasblom
@Avaq
Sep 23 2015 11:57
Yeah.
I know, i know, root of evil. But for cool reasons as well.
Simply food for thought.
Raine Virta
@raine
Sep 23 2015 11:58
I can only think of using memoize, https://gist.github.com/raine/0bd2ec53e856a1fe1268
Scott Sauyet
@CrossEye
Sep 23 2015 11:59
There is done sordid history behind where. Soon after our first public announcements, someone posted a perf comparison, using our demo code. Our perf was abysmal, for exactly these reasons. We ended up rewriting where to manually curry, and that stayed us down a wild ride where we rewrote everything that way, and then wrote or current versions of curry and rewrote again.
Ahh, the bad old days.
Aldwin Vlasblom
@Avaq
Sep 23 2015 12:00
Using compose kind of solves it, http://goo.gl/nxu5wA, except now you get what DrBoolean calls the ugly butt thing when you want to pass all arguments: whereAny(spec)(object)
@CrossEye Ha, wow. So the performance reasons argument is actually a pretty solid one. :)
Raine Virta
@raine
Sep 23 2015 12:03
I guess there's no way around whereAny(spec)(object)
Aldwin Vlasblom
@Avaq
Sep 23 2015 12:05
I just realized there's uncurry for that!
Right?
Hm. Actually..
Scott Sauyet
@CrossEye
Sep 23 2015 12:06
@raine, manually currying when the first param is available works. I think we lost that sometime for where.
Aldwin Vlasblom
@Avaq
Sep 23 2015 12:06
You'd need a kind of reversed curry, where it returns a curried function that can take multiple arguments per call, from a curried function that only takes one argument per call.
The idea being that the function that only takes one argument per call ensures maximum performance, and if you're going to provide multiple at a time, your performance couldn't have been better anyway.
Aldwin Vlasblom
@Avaq
Sep 23 2015 12:14
Because now the only way we have at our disposal for currying something "locks" the entire computation away until all arguments are present.
Raine Virta
@raine
Sep 23 2015 12:15
yep
Aldwin Vlasblom
@Avaq
Sep 23 2015 12:15
Whereas by using compose, like in my solution, we can make multy-ary functions that compute bits as they're given arguments, but then we end up with the )(<-butt.
Raine Virta
@raine
Sep 23 2015 12:15
but there's no way you could get anything compute beforehand without having a butt
Aldwin Vlasblom
@Avaq
Sep 23 2015 12:16
No, but we don't want people that have all the arguments at the same time to have to type butts to provide them. So maybe we can sugar it using my hypothetical reversed curry.
let whereAny = R.unbutt(R.compose(R.anyPass, specToPredicates))
If you give the resulting function 2 arguments, it just does for arg in arguments do f = f(arg)
Aldwin Vlasblom
@Avaq
Sep 23 2015 12:22
That makes the performance impact pretty explicit as well.
Scott Christopher
@scott-christopher
Sep 23 2015 12:26
It's a bit of a hack, but you can probably also get away with:
var whereAny = curryN(1, (spec, obj) => {
  var fn = anyPass(map(apply(flip(propSatisfies)), toPairs(spec)));
  return typeof obj == 'object' ? fn(obj) : fn;
});
Scott Sauyet
@CrossEye
Sep 23 2015 12:35
That's what we did with where at one point.
Denis Stoyanov
@xgrommx
Sep 23 2015 12:44
Hardy Jones
@joneshf
Sep 23 2015 15:42
consider for a second the types you're working with.
an object is a product type.
that gives the semantics that you want all of the specs to pass
an array (or more accurately a list) encodes non-determinism.
that gives the semantics that you just want to know if any spec passes.
whereAny should take an array of objects as the specs.
Hardy Jones
@joneshf
Sep 23 2015 15:47
That makes your whereAny:
var whereAny = R.pipe(R.where, R.map, R.anyPass);
at least, in theory...
might have to do
var whereAny = R.pipe(R.identity, R.where, R.map, R.anyPass);
oops
var whereAny = R.pipe(R.map(R.where), R.anyPass);
that's right.
Hardy Jones
@joneshf
Sep 23 2015 15:52
whereAny(specs)({name: 'Alice', email: 'wat'}) //=> true
whereAny(specs)({name: 'Alic', email: 'dude'}) //=> false
whereAny(specs)({name: 'Bob', email: 'bob@gmail.com'}) //=> true
An added benefit of changing the type is that you can have more complex specs.
Like specs that depend on more than one key in the object.
Hardy Jones
@joneshf
Sep 23 2015 15:59
If you absolutely must keep the specs as an object, then you can convert it to an array of objects, and go from there.
Ludwig Magnusson
@TheLudd
Sep 23 2015 16:00
@joneshf Interesting angle
Hardy Jones
@joneshf
Sep 23 2015 16:00
var objToObjs = R.pipe(R.toPairs, R.reduce(R.apply(R.createMapEntry), {}))
or something