These are chat archives for ramda/ramda

30th
Dec 2015
Scott Sauyet
@CrossEye
Dec 30 2015 00:04

Although that's always a concern, I actually prefer it. I hate cluttering up my source files with documentation or other extraneous matter.

But even as they are, they are extremely readable, and very useful. (I haven't read them all, yet, but I've been through about half.) Thanks for all your effort.

Hardy Jones
@joneshf
Dec 30 2015 04:05
@niloy one use of lenses that I really liked was something SPJ talked about in his introduction: using lenses as virtual fields.
Hardy Jones
@joneshf
Dec 30 2015 04:23
> const Bob = {name: 'Bob', height: 180, weight: 90};
undefined
> const cmHeight = R.lensProp('height');
undefined
> const inchHeight = R.lens(R.pipe(R.view(cmHeight), R.multiply(0.393701)), (h, b) => R.set(cmHeight, h / 0.393701, b));
undefined
> R.view(cmHeight, Bob);
180
> R.set(cmHeight, 200, Bob);
{ name: 'Bob', height: 200, weight: 90 }
> R.view(inchHeight, Bob);
70.86618
> R.set(inchHeight, 72, Bob);
{ name: 'Bob', height: 182.87990124485333, weight: 90 }
Looks like pipe is still broken.
in any case. The idea is that you can have some canonical representation
here, height is measured in cm.
And you provide lenses for the height in two flavors, one in cm, and the other in inches.
Then you can use those lenses in appropriate ways.
view or set the cm height of bob.
view or set the inch height of bob.
the conversion happens through the lens. So your canonical representation never has to change.
Like in the last example, we set bob's height to 72 inches, that's all well and good for the person that wanted to see it as 72 inches, but we want things in cm, they used the inch lens, but we get cm's stored in the object.
The best part is, the interface is the same between the two, so if you were doing some sort of l10n stuff, you could just pass around different lenses for each location.
Hardy Jones
@joneshf
Dec 30 2015 04:28
and not have to change one bit of your canonical code.
Let's see assoc do that! :D
Niloy Mondal
@niloy
Dec 30 2015 04:31
The code you pasted above, where do you write it?
Hardy Jones
@joneshf
Dec 30 2015 04:32
node
repl
David Chambers
@davidchambers
Dec 30 2015 04:42
That's a great example, @joneshf!
Niloy Mondal
@niloy
Dec 30 2015 04:46
var Bob = {name: 'Bob', height: 180, weight: 90};
var cmHeightGetter = R.prop("height");
var cmHeightSetter = R.assoc("height");
var inchHeightGetter = R.pipe(cmHeightGetter, R.multiply(0.393701));
var inchHeightSetter = (value, obj) => cmHeightSetter(value / 0.393701, obj);
I somewhat get the point of lens though... its a tuple of (getter, setter)
Hardy Jones
@joneshf
Dec 30 2015 16:50
After thinking about it overnight, I think this is a better example.
> const Bob = {height: 180, name: 'Bob', weight: 90};
undefined
> const height = R.lensProp('height');
undefined
> const cmToIn = R.lens(cm => cm * 0.393701, (n, _) => n / 0.393701);
undefined
> const cmHeight = height;
undefined
> const inHeight = R.compose(cmHeight, cmToIn);
undefined
> R.view(cmHeight, Bob)
180
> R.view(inHeight, Bob)
70.86618
> R.set(cmHeight, 190, Bob);
{ height: 190, name: 'Bob', weight: 90 }
> R.set(inHeight, 70, Bob);
{ height: 177.79990398805182, name: 'Bob', weight: 90 }
you can keep height as a private function in side the module.
and expose just cmHeight and inHeight.
inHeight is exactly the composition of lenses.
and cmToIn doesn't even need to live in your module.
Move that to a "units" library or some such.
cmToIn is actually an isomorphism.
It's also quite a bit clearer what's happening there.
Hardy Jones
@joneshf
Dec 30 2015 17:10
Also, remember that view, set, and over are specific implementations, and the lens is the reusable part.

So later down the line, ramda could add something like:

const to = R.curry((lens, f, x) =>
  lens(R.compose(Const, f))(x).value
);

And then you get the following behavior for free:

> to(inHeight, R.add(10), Bob)
80.86618
So we view the focus of the lens, and then modify it as it comes out.
Or any other Functor could be used in the place of Const, and you get some different behavior.
Hardy Jones
@joneshf
Dec 30 2015 17:20
So if you notice you've got a Functor with different behavior, then you probably have some extension to lenses there.
Maybe, Either, Future, etc.
Use those as your Functor and see what happens.
Niloy Mondal
@niloy
Dec 30 2015 19:01
:+1: It will take me some time to grasp all of that, but seems interesting
David Chambers
@davidchambers
Dec 30 2015 23:42
I'm really excited by the possibility of using lenses in this way. Thanks, Hardy!