I have to say your videos are top content. To the point, clear, concise. Usually I run videos 1,5 and skip through them. No need to that with your videos. Keep it up!
I’m convinced this is the best programming channel on UA-cam. Real content, not bs “how I got a job at google” crap. Thanks for the quality content. :)
I always come back to this video, just as you advise, I fell in love with monocle. Also in the newest versions, we must to use andThen instead composeLens and composePrism. Thanks Daniel!
Really nice explanation. At first, I was not sure if lenses are useful, since one can create a similar abstraction relatively easily. But once you combined prisms with lenses, it clicked. I think they are called prisms, since prisms in physics are used to split a bundled light stream apart, to observe its components. In this case it is a parent type which gets split apart and we can see what is beneath.
Thanks for the very clear explanation. I understand how these constructs can be useful when we want to zoom in one specific part of the data structure. Do they also make sense when we want to zoom in to all the parts of such a structure? Say for example I'm writing some kind of transformer from BrandIdentity to something, I need to traverse the whole nested structure and cover all the types of each trait, not just one specific one. Would it be a good idea to code this a lot of lenses and prisms and compose them together or would it become bloated and defeat the point of Lenses zooming on one particular part?
Nice question. It will ultimately depend on how many different things you want to access, and (much more importantly) how often you reuse this access. If you use it once, then lenses aren't that useful for the effort involved.
hm, i wonder if i can use the Prisms together with Chimney library, to make Prisms that help me Transform API-Models to Database-Models and Vice versa, without boilerplate code.
Unless I'm missing something, this seems underwhelming. A prism just replaces a two-branch match expression? And if I want to access a deeply nested field just once, a lens doesn't save me anything? I've been seeing mentions of lenses for a long time, so I was hoping to discover something I could put to good use.
These examples opened my eyes since I had heard the term but never taken time to look into it. To me it is all win-win: composable, enables DRY principle for this task (vs. WET - write everything twice+), and simple to use. Even at two levels it avoids repeating those growing nested accesses. Those examples were intentionally showing each step. But, when you don't need to reuse those intermediate lenses, code simplifies even more. The middle explicit types can be skipped as they are inferred: val brandCircleRadiusOptics = GenLens[BrandIdentity](_.icon).composeLens(GenLens(_.shape)).composePrism(Prism { case Circle(r) => Some(r) case _ => None }{ r => Circle(r) }) val aBrand2 = brandCircleRadiusOptics.modify(_ * 2)(aBrand)
my mistake. I think the explicit types are still needed. E.g. val brandCircleRadiusOptics2 = GenLens[BrandIdentity](_.icon).composeLens(GenLens[Icon](_.shape)).composePrism(Prism[Shape,Double] { case Circle(r) => Some(r) case _ => None }{ r => Circle(r) })
In all cases i do find pattern matching and deconstructing to be nice solutions. def fixSpaces(band:RockBand):RockBand = band match { case RockBand(a, Guitarist(b, Guitar(c, d))) => RockBand(a, Guitarist(b, Guitar(c, d.replace(" ", "-")))) } def modifyCircleIcon(brand: BrandIdentity, mod: Double => Double) : BrandIdentity = brand match{ case BrandIdentity(Logo(c1), Icon(c2, Circle(r))) => BrandIdentity(Logo(c1), Icon(c2, Circle(mod(r)))) case BrandIdentity(Logo(c1), Icon(c2, a)) => BrandIdentity(Logo(c1), Icon(c2, a)) } Maybe it's just that i have not worked that much with heavy nested structures. If you could, i would love if you would elaborate on why or when monocl is worth it.
Pattern magic is awesome! The problem is when you have to repeat the deconstruction over and over again, which is where libraries like Monocle become useful.
I have to say your videos are top content. To the point, clear, concise. Usually I run videos 1,5 and skip through them. No need to that with your videos. Keep it up!
That's the goal! Enjoy!
I’m convinced this is the best programming channel on UA-cam. Real content, not bs “how I got a job at google” crap. Thanks for the quality content. :)
Glad you liked it!
This is so cool.... at first I thought lenses are just too much, but with the prism, nice compositions, thanks for the usually clear explanations.
That's my goal!
I always come back to this video, just as you advise, I fell in love with monocle. Also in the newest versions, we must to use andThen instead composeLens and composePrism. Thanks Daniel!
Great video, as always!
Thanks!!
As usual fantastic and very nicely done
Thanks! More to come!
Nice and simple explanation! THANK YOU!
Very welcome!
Really great video and clear explanations !
Thanks!
Thanks for the video. I'm wondering if there any performance implications when using optics.
The runtime perf degradation should be negligible. The compile time might grow, though, depending on the macro-based optics you use.
Really nice explanation. At first, I was not sure if lenses are useful, since one can create a similar abstraction relatively easily. But once you combined prisms with lenses, it clicked.
I think they are called prisms, since prisms in physics are used to split a bundled light stream apart, to observe its components. In this case it is a parent type which gets split apart and we can see what is beneath.
Glad it was helpful!
Thanks for the very clear explanation. I understand how these constructs can be useful when we want to zoom in one specific part of the data structure. Do they also make sense when we want to zoom in to all the parts of such a structure? Say for example I'm writing some kind of transformer from BrandIdentity to something, I need to traverse the whole nested structure and cover all the types of each trait, not just one specific one. Would it be a good idea to code this a lot of lenses and prisms and compose them together or would it become bloated and defeat the point of Lenses zooming on one particular part?
Nice question. It will ultimately depend on how many different things you want to access, and (much more importantly) how often you reuse this access. If you use it once, then lenses aren't that useful for the effort involved.
Nice tutorial again! worth 30k+ views.
Thank you! Will get to that in time...
hm, i wonder if i can use the Prisms together with Chimney library, to make Prisms that help me Transform API-Models to Database-Models and Vice versa, without boilerplate code.
ah, i mean Iso not Prism.
That's so cool! ✌️😎
Glad you like it!
Unless I'm missing something, this seems underwhelming. A prism just replaces a two-branch match expression? And if I want to access a deeply nested field just once, a lens doesn't save me anything?
I've been seeing mentions of lenses for a long time, so I was hoping to discover something I could put to good use.
The examples are pretty small, but this tool is starting to become the more valuable the more complex your data structures are.
These examples opened my eyes since I had heard the term but never taken time to look into it.
To me it is all win-win: composable, enables DRY principle for this task (vs. WET - write everything twice+), and simple to use. Even at two levels it avoids repeating those growing nested accesses.
Those examples were intentionally showing each step. But, when you don't need to reuse those intermediate lenses, code simplifies even more. The middle explicit types can be skipped as they are inferred:
val brandCircleRadiusOptics = GenLens[BrandIdentity](_.icon).composeLens(GenLens(_.shape)).composePrism(Prism {
case Circle(r) => Some(r)
case _ => None
}{ r => Circle(r) })
val aBrand2 = brandCircleRadiusOptics.modify(_ * 2)(aBrand)
my mistake. I think the explicit types are still needed. E.g.
val brandCircleRadiusOptics2 = GenLens[BrandIdentity](_.icon).composeLens(GenLens[Icon](_.shape)).composePrism(Prism[Shape,Double] {
case Circle(r) => Some(r)
case _ => None
}{ r => Circle(r) })
Wonderful
More incoming!
In all cases i do find pattern matching and deconstructing to be nice solutions.
def fixSpaces(band:RockBand):RockBand = band match {
case RockBand(a, Guitarist(b, Guitar(c, d))) => RockBand(a, Guitarist(b, Guitar(c, d.replace(" ", "-"))))
}
def modifyCircleIcon(brand: BrandIdentity, mod: Double => Double) : BrandIdentity = brand match{
case BrandIdentity(Logo(c1), Icon(c2, Circle(r))) => BrandIdentity(Logo(c1), Icon(c2, Circle(mod(r))))
case BrandIdentity(Logo(c1), Icon(c2, a)) => BrandIdentity(Logo(c1), Icon(c2, a))
}
Maybe it's just that i have not worked that much with heavy nested structures. If you could, i would love if you would elaborate on why or when monocl is worth it.
Pattern magic is awesome! The problem is when you have to repeat the deconstruction over and over again, which is where libraries like Monocle become useful.
i prefer this way -> cuz it's super clear and easy to understend, also don't have any unnesesary dependency
Wooo
Weird guitar. It only has two strings.
LOL
Great video, but Metallica's lead guitarist will always be Dave Mustane.
I heard he started a new band.
@@rockthejvm Megadeath 😃
But yeah, for me Metallica ended with him leaving.
My opinion though.