These are chat archives for ramda/ramda

28th
Mar 2016
Jonah
@jonahx
Mar 28 2016 03:00
@joneshf ty
Raine Revere
@raineorshine
Mar 28 2016 03:38
I’m enjoying using more functional programming, especially the challenge of making things point-free (although I recognize that it isn’t always necessarily better). Here’s one that I’m stuck on. Is there a good way to make this last containsLoose function point-free?
const makeLooselyComparable = (str) => str.trim().replace(/\W/g, '').toLowerCase()
const eqLoose = R.eqBy(makeLooselyComparable)
containsLoose = R.curry((str, array) => R.any(eqLoose(str), array))
Asaf
@asaf-romano
Mar 28 2016 04:34
Raine Revere
@raineorshine
Mar 28 2016 04:36
@asaf-romano Thanks!
James Forbes
@JAForbes
Mar 28 2016 08:09
Is there anything in ramda for traversing large nested structures?
Scott Christopher
@scott-christopher
Mar 28 2016 08:51
@JAForbes Do you have an example of what you're after?
@metaraine For a slightly different approach, uncurryN could also be used.
@ram-bot
const eqLoose = eqBy(pipe(trim,  replace(/\W/g, ''), toLower))
const containsLoose = uncurryN(2, pipe(unary(eqLoose), any))
containsLoose("foo", ["F oO"])
ram-bot
@ram-bot
Mar 28 2016 08:53
true
Scott Christopher
@scott-christopher
Mar 28 2016 08:55
I'd recommend sticking with useWith as @asaf-romano suggested for this particular case though, as it's not particularly clear what's going on here.
James Forbes
@JAForbes
Mar 28 2016 09:04

yeah sure @scott-christopher

Something like: https://www.npmjs.com/package/traverse

But also a transducer, that allows you to stop traversing once a predicate is met (as an example). I'm thinking pretty generally here.

So you need to take(5) where filter(x => x > 5)but x could be any node along the tree. Once you've got your 5, you stop traversing.

Scott Christopher
@scott-christopher
Mar 28 2016 09:22
So you want to collect the nodes until a predicate is satisfied?
James Forbes
@JAForbes
Mar 28 2016 12:33
yep
or map the node values too
im looking for a general tool
Scott Sauyet
@CrossEye
Mar 28 2016 13:08
@JAForbes: have you suggested this as an API extension to substack? Or do you not like that implementation for other reasons?
Hardy Jones
@joneshf
Mar 28 2016 14:17
^
It sounds like that package does what you need sans the transducer part.
Most of the stuff in ramda assumes a structure that is more homogenous. Whereas it looks like the traverse package works with anything you can throw at it.
Hardy Jones
@joneshf
Mar 28 2016 14:24
Do you often have arrays where one element is a number and the next is an object with deep nesting? Or an object where some values are booleans and others are more objects?
Or is it more for the fringe of your program? Like someone gives you some bunk data, and you want to clean it up before operating?
James Forbes
@JAForbes
Mar 28 2016 21:16

@CrossEye substack's API doesn't play very well with other Ramda methods. But it can be made to work for sure. (I go into this further below)

@joneshf I often find myself traversing arbitrary structures in API's for validation/tests. It's not so much that the structure isn't monomorphic, as it is complex.

E.g.

[
   { a: { [  { b: [ { c: [ {} ]}]}]}}
   { a: { [  { b: [ { c: [ {} ]}]}]}}
   { a: { [  { b: [ { c: [ {} ]}]}]}}
]

At each level of depth, each array could have n records. Let's say I want to verify each id is unique for all the c level records across the entire structure.

R.path, won't work because there could be n a, b or c records.
What I really need is something more a kin to R.evolve where I just get notified when a key exists and do a check at that point in time, but then control how the results are accumulated.

It's easy to do it via substacks module, but you need to look at proprietary substack API fields like this.key or this.isLeaf. And anything that relies on this is not very compatible with Ramda, hence the question.

And this really does come up a lot.

Other use cases... taking an API response that is arbitrarily nested (but still homogenous at the record level) and grab only the data necessary for say a GraphQL like implementation (I want these fields in this structure), to reduce payload sizes - or even just rendering the data more easily by pulling the relevant fields into a flat array.

Scott Christopher
@scott-christopher
Mar 28 2016 22:27
@JAForbes You can get a fair way with optics (lenses, traversals, etc).
const data = [{ a: [{ b: [{ c: [{ id: 'foo' }, { id: 'bar' }, { id: 'baz' }]}]}]}];

const idFocus = R.compose(
  Traversal.traversed,
  Traversal.ixObject('a'),
  Traversal.traversed,
  Traversal.ixObject('b'),
  Traversal.traversed,
  Traversal.ixObject('c'),
  Traversal.traversed,
  Traversal.ixObject('id')
);

const allIdsUniq = R.compose(R.allUniq, Fold.toListOf(idFocus));

allIdsUniq(data); // true
Traversal and Fold are from https://github.com/flunc/optics
James Forbes
@JAForbes
Mar 28 2016 23:54

intriguing, but does that require updating the definition of idFocus if the structure of data changes?

I like that you are able to use R.allUniq as if it were a flat list. But I don't like that you need to encode the specific structure of data into the composition of idFocus

I'll definitely explore optics more though, thanks @scott-christopher
Scott Christopher
@scott-christopher
Mar 28 2016 23:55
If you don't have a guaranteed structure, you could use a recursive reduce.
James Forbes
@JAForbes
Mar 28 2016 23:56
ooo intriguing
Scott Christopher
@scott-christopher
Mar 28 2016 23:56
It just means you have to check each node to determine what to do next.
I have to jump into a meeting right now, but I can show you an example a bit later if you'd like.
James Forbes
@JAForbes
Mar 28 2016 23:57
yeah that would be great, thank you
Scott Christopher
@scott-christopher
Mar 28 2016 23:57
:thumbsup: