is there something like

`flattenObj`

in ramda?
Any good, functional patterns for branching based on an argument's type?

```
const f = function(x) {
if (R.is(Object, x)) {
// do Object stuff
} else if (R.is(Number, x) {
// do Number stuff
}
}
```

@kurtmilam

`R.cond`

can be helpful for describing `switch`

/`case`

style functions.
@ram-bot

```
const f = cond([
[is(Object), keys],
[is(Number), add(10)]
])
f(10)
```

`undefined`

hmm... don't know why @ram-bot doesn't like that

but you get the gist

@ram-bot

```
const fn = cond([
[is(Object), keys],
[is(Number), add(10)]
])
fn({a: true})
```

`[ 'a' ]`

`R.cond`

@mrtnbroder Do you have an example of the expected input/output for

`flattenObj`

?
@scott-christopher Thanks - I will mull that over a bit.

Sure.

`R.cond`

basically takes an array of 2-element arrays which contain a predicate function in the first position (the "if" check) and a result function in the second position (the "then" part)
re: flattenObj, this is the input and output of a flattenObj fn I've written:

```
const obj = {a:1, b:{c:3}, d:{e:{f:6}}}
const flatPOJO = flattenPOJO(obj)
/* flatPOJO =
{
a: 1
, ['b.c']: 3
, ['d.e.f']: 6
}
*/
```

This creates a new function that when given some value will try each predicate until one returns

`true`

and then return the result of applying the function in the second position to the same value
but my flattenObj (called flattenPOJO) needs to be refactored, Ramda-style

@scott-christopher That looks much cleaner than what I'm currently doing. Thanks for the example and explanation.

@kurtmilam I'm sure there is a more elegant solution than this brute-force attempt, but it seems to do the trick:

`Unexpected token [`

I don't think @ram-bot likes destructuring arguments

@ram-bot

```
const flattenPOJO = obj => {
const isObj = x =>
typeof x == 'object' && x != null && x.constructor !== Array
const joinPrefix = (prefix, k) =>
prefix.length > 0 ? `${prefix}.${k}` : k
const mapDeep = (prefix, obj) =>
map((pair) => {
const k = pair[0],
v = pair[1]
if (isObj(v)) {
return unnest(mapDeep(joinPrefix(prefix, k), v))
} else {
return [joinPrefix(prefix, k), v]
}
}, toPairs(obj))
return fromPairs(mapDeep('', obj))
}
flattenPOJO({a:1, b:{c:3}, d:{e:{f:6}}})
```

`{ a: 1, 'b.c': 3, 'd.e.f': 6 }`

Managed to get it a bit more succinct:

@ram-bot

```
const isObj = x =>
typeof x == 'object' && x != null && x.constructor !== Array
const flattenObj_ = pipe(toPairs, chain((pair) =>
isObj(pair[1]) ? map((x) => [pair[0]+'.'+x[0], x[1]], flattenObj_(pair[1])) : [[pair[0], pair[1]]]))
const flattenObj = pipe(flattenObj_, fromPairs)
flattenObj({a:1, b:{c:3}, d:{e:{f:6}}})
```

`{ a: 1, 'b.c': 3, 'd.e.f': 6 }`

@scott-christopher Looks good! My function also works on arrays (which I didn't mention previously):

```
const input = {a:1, b:{c:3}, d:{e:{f:6}, g:[{h:8, i:9}, 0]}}
//output:
{ a: 1, 'b.c': 3, 'd.e.f': 6 , 'g.0.h': 8, 'g.0.i': 9, 'g.1': 0}
```

I think you could get away with removing the check in

`isObj`

to avoid Arrays.
@ram-bot

```
const flattenObj_ = pipe(toPairs, chain((pair) =>
typeof pair[1] == 'object' ? map((x) => [pair[0]+'.'+x[0], x[1]], flattenObj_(pair[1])) : [pair]))
const flattenObj = pipe(flattenObj_, fromPairs)
flattenObj({a:1, b:{c:3}, d:{e:{f:6}, g:[{h:8, i:9}, 0]}})
```

```
{ a: 1,
'b.c': 3,
'd.e.f': 6,
'd.g.0.h': 8,
'd.g.0.i': 9,
'd.g.1': 0 }
```

Nice! More concise + additional functionality.

although it seems to be confused, having prefixed 'g' with 'd'.

`g`

is a member of `d`

in `{a:1, b:{c:3}, d:{e:{f:6}, g:[{h:8, i:9}, 0]}}`

You're right - I had meant to put 'g' outside of 'd', thus the confusion.

that's way more concise than my non-ramda function.

I might throw it in the cookbook because I recall a couple of others asking for something similar recently.

Good idea. Here's my current, non-ramda function in action. It does a couple of additional things I'd forgotten to mention.

@scott-christopher I was one of them :d

I'm going to take the time to refactor mine from scratch into Ramda-style to get the exact functionality I need as well as the valuable practice it'll provide.

but I'll probably cheat a little and use yours as a guide when I'm feeling stumped.

:D

I'm guessing this has something to do with Mongo, or some kind of document store db?

@scott-christopher something like that. CouchDB is the actual target, and I'm working with JSON config documents.

Right. I'd be interested to hear how it works out for you.

Hi guys, I keep running into this pattern:

```
let data = { a : 1, b : 2 };
const bar = x => 5 * x.a;
const foo = x => R.set(R.lensProp('c'), bar(x), x);
foo(data);
```

Is there a way to refactor out the x from function foo?

@mspoulsen You can use

`converge`

for this, but it doesn't really help the readability of the code. You can also use `assoc`

instead of the lens to avoid the need to wrap your call in `R.set`

.
@ram-bot

```
var data = { a : 1, b : 2 };
var bar = x => 5 * x.a;
var foo = R.converge(R.assoc('c'), [bar, R.identity])
foo(data);
```

`{ a: 1, b: 2, c: 5 }`

@Bradcomp thanks! :thumbsup:

hello!

how can I implement this using compose/pipe?

```
Monad().chain(function(var1) {
return Monad().chain(function(var2) {
return var1 + var2
});
});
```

@rickmed Is your goal to apply a binary function to two values in containers?

mmm not sure what you mean (just learning fp sorry :) )

are you talking about something like ap or liftN?

Yeah, I was going to suggest

`lift`

so lift would apply them in parallel, right? what if I wanted to do it in sequence like with chain above?

So when you say

`Monad()`

up above, are you instantiating an empty Monad, or just using it as a placeholder for a Monad that you've already created?
the second i guess, meaning, an instantiated monad, something like monad.of(something)

sorry let me edit the code

```
Monad.of(a).chain(function(var1) {
return functor.of(a).map(function(var2) {
return var1 + var2
});
});
```

Sorry, I am messing with a few things here...

http://goo.gl/rzmYOq

http://goo.gl/rzmYOq

does that makes more sense?

It does.

btw, what maybe library is that?

I think you will need to use

`lift`

or `ap`

in order to work with multiple wrapped values.
Ramda-fantasy

That, and Sanctuary (under namespace S) are included in the repl

got it, thanks!

cool

I'm trying to get something working with this function:

`const safeDiv = curry((a, b) => b === 0 ? Maybe.Nothing() : Maybe.of(a / b))`

So we can get

`chain`

involved
my use case is something like: compose(fn1, fn2, fn3)

Do they all operate on the same monad?

The problem with

`compose`

and `pipe`

is that, after the innermost function, they expect a single parameter
I say problem, but really I just mean that's how they work

I need fn1 to have access to a variable in fn3

like if fn2 were a function between the monad and the functor in the example above

So you need to have access to the scope of fn1 in fn3?

the other way around (compose runs from right to left, no?)

Sorry, you're right

`compose`

won't get you there without other helper functions. You'll need to pass both values you need to fn1 from fn3. So you'll probably want to pass a pair out of fn3, then apply fn2 to one of the items in the pair, passing the other one through unchanged. `converge`

might help.
let me check converse out

similar to lift, right?

got it, thank you! @Bradcomp

Cool!

Sorry if I made things more confusing than needed

no! it was helpful!