Hi people! I looking for a way to use merge(), but I need to modify the keys before applying them to the destination. for example, my source is {a: 1, b: 2} and I want to merge it with an empty object, but with the result looking like this {_a: 1, _b:2}

any suggestions?

@ram-bot

```
const data1 = {a: 1, b: 2}
const data2 = {c: 3}
const mergedObj = R.merge(data1, data2)
const updateKeys = obj => R.map(x => '_'+x, R.keys(obj))
R.zipObj(updateKeys(mergedObj), R.values(mergedObj))
```

`{ _a: 1, _b: 2, _c: 3 }`

That is a start, I think I can make it a bit more readable though

@xgrommx That looks useful, but he would still have to get the value for each key. Which I would think where the difficulty is

@ram-bot

```
const updateKeys = o => R.map(x => '_'+x, R.keys(o))
const zipUpdatedKeys = o => R.zipObj(updateKeys(o), R.values(o))
const mergeAndUpdateKeys = R.compose(zipUpdatedKeys, R.merge);
const data1 = {a: 1, b: 2}
const data2 = {c: 3}
mergeAndUpdateKeys(data1, data2)
```

`{ _a: 1, _b: 2, _c: 3 }`

Is that what you were looking for @Emilios1995 ? There might be an even more concise way to do it

@That-David-Guy yes, thanks! I didn't know zipObject. How would you do it more concisely?

Hey folks, I wrote a small function that find the minimum latitude from a list:

```
const findPlacesBoundingBox =
R.pipe(
R.map(
R.pipe(
R.path(['googlePlaceObj', 'geometry', 'location', 'lat']),
),
),
R.reduce(R.min, Infinity),
)
```

I also wants to find the maximum latitude. I can repeat the function for the maximum but it is not DRY and I am sure there should be a better way in Ramda.

Also it is not very efficient. How do you do this in one go?

And do we have a function that do exactly the opposite of

`zipObj`

? `toPairs`

is not exactly the opposite of `zipObj`

Okay I think I found the answer to my second questions. I needed

`R.values`

function to get rid of the keys
@Emilios1995 Not sure. I'm still new to functional programming so there is usually something I'm missing :)

@That-David-Guy nevermind, that was just what I needed! :smile:

@bmamouri It's perhaps not the nicest implementation, but you could do something like the following:

@ram-bot

```
const fn = R.pipe(
R.map(R.path(['googlePlaceObj', 'geometry', 'location', 'lat'])),
R.apply(R.applySpec({ min: Math.min, max: Math.max }))
)
const input = [
{ googlePlaceObj: { geometry: { location: { lat: 0 }}}},
{ googlePlaceObj: { geometry: { location: { lat: 5 }}}},
{ googlePlaceObj: { geometry: { location: { lat: 2 }}}},
{ googlePlaceObj: { geometry: { location: { lat: 3 }}}},
{ googlePlaceObj: { geometry: { location: { lat: 6 }}}}
]
fn(input)
```

`{ min: 0, max: 6 }`

@scott-christopher Thank you.

`apply`

and `applySpec`

was the missing ingredient. That exactly does what I want.
Now if I want to also do this for longtitude I should have two different functions. Something like this:

```
const getMinMax(keyName) => R.pipe(
R.map(R.path(['googlePlaceObj', 'geometry', 'location', keyName])),
R.apply(R.applySpec({ min: Math.min, max: Math.max }))
)
```

Or there is a better alternative?

I actually think what I want to do is a bit different. Here is what I achieved so far:

```
const places = [
{
googlePlaceObj: {
geometry: {
location: {
lat: 1,
lng: 2,
}
}
}
},
{
googlePlaceObj: {
geometry: {
location: {
lat: 11,
lng: 22,
}
}
}
}
]
const getAllLocations =
R.pipe(
R.map(
R.pipe(
R.path(['googlePlaceObj', 'geometry', 'location']),
R.values
),
),
)
```

This will result in a pairs of [lat, lng]s, like so:

`[[1, 2], [11, 22]]`

Now I want to get the minimum lat and lng from the array and maximum lat and lng from the array.

To create a bounding rectangle from all the locations.

If I could just convert the array of [[lat, lng], [lat, lng], [lat, lng], …] into [[lat, lat, lat …], [lng, lng, lng, …]] I could easily use

`R.minBy`

and `R.maxBy`

to find the boundary.
`R.transpose`

@bmamouri

`transpose`

can achieve that.
@ram-bot

`R.transpose([[1, 'a'], [2, 'b'], [3, 'c']])`

`[ [ 1, 2, 3 ], [ 'a', 'b', 'c' ] ]`

Thank y ou @scott-christopher for helping me out.

`R.transpose`

was exactly what I was looking for.
You're welcome :)

Last question and thank you in advance.

How can I reuse this code for finding the bootomRight bounds. The only differet is that `R.min`

should be replaced with `R.max`

:

```
const getTopLeft =
R.pipe(
R.map(
R.pipe(
R.path(['googlePlaceObj', 'geometry', 'location']),
R.values,
),
),
R.transpose,
R.map(R.reduce(R.min, Infinity)),
)
getTopLeft(places)
```

I can make the function to get parameter, but I am thinking maybe there is a cleaner way.

It's starting to sound like you might benefit from modeling this using a separate data type.

@bmamouri In your inner pipe up there you might consider using

`props`

instead of `values`

as `values`

doesn't guarantee the order is preserved.
`props`

`R.props`

Good point @Bradcomp. Thank you. I did not notice that the order is not preserved

If you create a monoid instance for a bounding box, you should be able to do something like:

`SyntaxError: Block-scoped declarations (let, const, function, class) not yet supported outside strict mode`

hmm, let me try that again...

@ram-bot

```
class BBox {
constructor(tlLat, tlLng, brLat, brLng) {
this.tlLat = tlLat;
this.tlLng = tlLng;
this.brLat = brLat;
this.brLng = brLng;
}
concat(other) {
var tlLat = max(this.tlLat, other.tlLat),
tlLng = min(this.tlLng, other.tlLng),
brLat = min(this.brLat, other.brLat),
brLng = max(this.brLng, other.brLng);
return new BBox(tlLat, tlLng, brLat, brLng);
}
static fromLatLng({lat, lng}) {
return new BBox(lat, lng, lat, lng)
}
static empty()
{
return new BBox(-Infinity, Infinity, Infinity, -Infinity)
}
}
var objToBBox = pipe(path(['googlePlaceObj', 'geometry', 'location']), BBox.fromLatLng)
var fn = reduce(useWith(concat, [identity, objToBBox]), BBox.empty());
fn([
{ googlePlaceObj: { geometry: { location: { lat: 0, lng: 2 }}}},
{ googlePlaceObj: { geometry: { location: { lat: 5, lng: 5 }}}},
{ googlePlaceObj: { geometry: { location: { lat: 2, lng: 6 }}}},
{ googlePlaceObj: { geometry: { location: { lat: 3, lng: 7 }}}},
{ googlePlaceObj: { geometry: { location: { lat: 6, lng: 3 }}}}
]);
```

`SyntaxError: Block-scoped declarations (let, const, function, class) not yet supported outside strict mode`

hmm, maybe it doesn't like the

`class`

statement
anyway, that evaluates to

`{"brLat": 0, "brLng": 7, "tlLat": 6, "tlLng": 2}`

The

`empty`

instance is a bit of a stretch of the imagination, but it works for this purpose.
This is a beuatiful piece of code @scott-christopher. Being a noob in FP I am not familiar enough with Monoids. But I can see how this works.

A monoid is something with a fancy name that is actually pretty straight forward :)

@scott-christopher TBH, your many code snippets here have helped me be more comfortable with them as well.

@bmamouri I went a lot more literal with it: http://goo.gl/NMjQVD

It basically means you have some function that can take two instances of some type and return an instance of the same type.

Along with a few laws around associativity and identity that need to be adhered to.

e.g.

`concat(a, concat(b, c))`

must be equal to `concat(concat(a, b), c)`

and

`concat(MonoidThing.empty(), monoidThingInstance)`

must be equal to `monoidThingInstance`

and the flipped version of that:

`concat(monoidThingInstance, MonoidThing.empty())`

must equal `monoidThingInstance`

Some intuitive ones are numbers with addition.

`add(1, add(2, 3)) == add(add(1, 2), 3)`

`add(0, 5) == 5`

`add(5, 0) == 5`

along with numbers and multiplication, arrays, strings, etc.

I did something like you did as well @Bradcomp.

@Bradcomp you going to the next sacjs?

elm!

@joneshf I know! I'm gonna try to be there!

@Bradcomp With regards to

`values`

not having a guarantee that order is preserved. If it is not, is it consistent with `keys`

. I.e. are they both inconsistent in the same way
As in, would this fail

```
const updateKeys = o => R.map(x => '_'+x, R.keys(o))
const zipUpdatedKeys = o => R.zipObj(updateKeys(o), R.values(o))
const mergeAndUpdateKeys = R.compose(zipUpdatedKeys, R.merge);
const data1 = {a: 1, b: 2}
const data2 = {c: 3}
mergeAndUpdateKeys(data1, data2)
```

`{ _a: 1, _b: 2, _c: 3 }`

Say

`keys`

go a->c->b order, will `values`

also be a->c->b order?
@That-David-Guy It's up to the Javascript implementation I believe, so I wouldn't count on that, though it's *probably* fine.

I would probably go for toPairs and fromPairs

@Bradcomp Thanks! Didn't know about

`toPairs`

@Emilios1995 . There was a bug with the code I gave you since

`values`

and `keys`

don't guarantee order. This should be more safe
@ram-bot

```
const data1 = {a: 1, b: 2}
const data2 = {c: 3}
const updateKey = R.map(x=>['_'+x[0], x[1]] )
const mergeAndUpdateKeys2 =
R.compose(R.fromPairs, updateKey, R.toPairs, R.merge)
mergeAndUpdateKeys2(data1, data2)
```

`{ _a: 1, _b: 2, _c: 3 }`

There is probably still a better way to do the

`updateKey`

part.
@That-David-Guy Thanks! although the former version seemed more intuitive to me. are you sure it's not safe? I did a couple of tests and it worked good

*well

Oh I just read @Bradcomp's messages

:)

Like I said it's probably okay, there's just no guarantee of order

Looking under the hood at R.values, maybe it is safe: https://github.com/ramda/ramda/blob/v0.21.0/src/values.js

as they use

`keys`

to get their key array
I see. But, why would the JS make a difference?

*JS platform

The ECMAScript spec doesn't require an ordering for

`Object.keys`

so it's up to the implementation to decide how to order
@That-David-Guy @Emilios1995 In case you guys were interested, here's a lens based solution: http://goo.gl/hzRJdk

Thanks @Bradcomp ! I haven't really grokked

`lens`

and `over`

yet so I find that one harder to read. I'll have to mull over it tonight
This was mainly an exercise to help me understand them better

:)

@That-David-Guy @Bradcomp Lenses are new to me as well, this is definitely an interesting solution!

@Bradcomp There is a specified order (ES6) for

`Object.keys`

and own property iteration.
Hi, guys. What do you think about using Lenses for converting values between two types? Milliseconds <-> Seconds (just two number types, but semantically different). What is nice about Lenses is that they are composable. So I can compose ms <-> seconds, and seconds <-> minutes. If Lens is not just for focusing on part of bigger thing, but for "looking on thing from different angle", then it seems nice usage for them. So, I have ms, but with Lens, I work with it like I have seconds. What I want is in fact pair of function and inverse function `(a -> b, b -> a)`

, but in composable structure. When I use Lens for that, it works, but I should ignore "previous real thing" in setter, and when use `.set`

, should pass anything (which seems purposelessly).

```
const secondsLens = R.lens(v => v / 1000, v => _ => v * 1000);
const twoMinutes = R.set(secondsLens, 120, null);
```

So is there exist type for such pair `a -> b, b -> a`

. Or should I use Lenses for that?

"A monoid is something with a fancy name that is actually pretty straight forward." Absolutely. I think that one day I'll be smart enough that Monads seem that way too. :smile:

@iofjuupasli: I think that converting between related types/units is a great use of lenses. I'm not following the "pre ious real thing" objection.

@iofjuupasli: you could also declare these with an

`iso`

that can compose with other lenses.
@ram-bot

```
const iso = (to, fro) => afb => s => map(fro, afb(to(s)))
const secsToMins = iso(flip(divide)(60), multiply(60))
const milliToSecs = iso(flip(divide)(1000), multiply(1000))
const durationToMins = compose(lensProp('duration'), milliToSecs, secsToMins)
over(durationToMins, add(2), { duration: 0 })
```

`{ duration: 120000 }`

@CrossEye when I "set" new value, it replaces old, and returns it. In example, I've provided, `_`

in `v => _ => v * 1000`

and `null`

in `set`

. I doubt whether it's ok, or am I trying to apply lenses in wrong place. At first glance, it seemed to me, that it would be better to create or find another type for composing function with its inversed version.

@scott-christopher awesome! I don't understand how `iso`

works, just as I don't understand how lenses work in general, so I should learn about it first.

Some type sigs for the various arguments might help.

```
// to :: s -> a
// fro :: a -> s
// afb :: Functor f => a -> f a
iso = (to, fro) => afb => s => map(fro, afb(to(s)))
```

`afb`

is the function given by `over`

/ `view`

that puts the focussed value (the result of `to(s)`

) inside a functor (`Identity`

for `over`

, `Const`

for `view`

)
`to`

and `fro`

are the functions used convert between two types (`s`

and `a`

in the above).
@iofjuupasli Your idea is an excellent use of lenses (or isos as @scott-christopher points out)!

Just found https://github.com/ramda/ramda-lens/blob/master/test%2Ftest.js#L120-L134 and https://github.com/ramda/ramda-lens/blob/master/src%2Fisos.js#L5-L13. With that I can simply switch

`lens a -> b, b -> a -> a`

to `lens b -> a, a -> b -> b`

, and also use only `.view`

method. I found using `.set`

for getting value back from "lensed" value is very confusing. `R.view(from(minsLens))`

is more obvious
Is there something like

`R.splitWhen`

except it will split the string on every matching predicate? I'm looking for something higher level than `reduce`

something like this:

`R.splitWhen(';', ['foo', 'bar', ';', 'baz', ';', 'qux', 'norf', ';']) // [['foo', 'bar'], ['baz'], ['qux', 'norf']]`

I feel like there should be a

`split`

for lists, but there doesn't seem to be one
@ram-bot

`R.splitWhen(R.equals(';'), ['foo', 'bar', ';', 'baz', ';', 'qux', 'norf', ';'])`

`[ [ 'foo', 'bar' ], [ ';', 'baz', ';', 'qux', 'norf', ';' ] ]`

Not quite!

@jdalton So, returning to my issue, does Object.keys guarantee accurate order?

if so, the warning in the docs for https://github.com/ramda/ramda/blob/v0.21.0/src/values.js would need to be removed

does

`R.assoc`

mess with prototype stuff?
i found the

`.constructor`

of the result is `function Object`

instead of the original constructor
```
function Foo(){}
const f = new Foo()
const g = R.assoc('k', 42, f)
g instanceof Foo //false
f instanceof Foo //true
```

hmm,

`R.set`

also messes it up :(
@Emilios1995 For ES6 yes for earlier it's de facto.

Ok, thanks.

One more question, as you may have seen I'm to to all this and I really liked the comments you guys put before every function (Hindley-Milner). Now, I made a function to help with what I was trying to do (update object keys)

```
const headLens = lensIndex(0)
const updateKeys = (f) =>
R.compose(R.fromPairs,
R.map(over(headLens, f)),
R.toPairs)
updateKeys(updateKey)(obj)
```

How would the type annotation comment would look like for updateKeys ?

Something like

`Object -> (String -> String) -> Object`

or

`{ String : * } -> (String -> String) -> { String: * }`

Oh I got it. Thanks!

I had that backwards though

`(String -> String) -> { String : * } -> { String: * }`

oh I see. But I think I would just use

`Object`

, not `{ String : * }`

, because an object key will always be a string.