<div dir="ltr"><div class="gmail_default" style="font-family:monospace">Hello Kristofer,</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">I am not a part of the Amber Dev Team, but I think I see the reason.</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">Like you said, you can compose various functions (such as Optional::map and Optional::get) to achieve essentially what Optional::transform would give you. However, I think the general idea is that, by the time you have placed your object into a CompletableFuture, CompletionStage, or an Optional, your object is not just a String, but some strongly typed Java object. This aligns with some of the posts about Data-Oriented Programming, where one of the tenants behind it is to leave the untyped objects at the edge and only let the strongly-typed objects in.</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">With that assumption, Optional::transform only serves to be a shortcut for Optional::map -> Optional::get. It's a useful shortcut, but nothing more than a shortcut. As a result, many here might see it as a (comparatively) low value change.<br></div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">However, the default type for untyped objects coming from the outside world is String. As a result, String::transform is accomplishing a very different goal. It's not just a transform, it's also a deserialization method (or at least, a very important component within a deserialization method).</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">Working with strongly typed objects is easy and allows you to add methods wherever you see fit. Therefore, providing a CompletableFuture::transform doesn't hold much value when there's CompletableFuture::apply and CompletableFuture::get.</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">But STRINGLY typed objects (that is not a spelling error) are historically and notoriously difficult to work with and deserialize. And again, the default type of data coming from the outside world is String. Therefore, the need is much higher for a String::transform method, as you cannot extend java.lang.String, and we want to simplify deserialization as much as possible so that we can get away from being Stringly typed as quickly as possible.<br></div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">On top of that, you can extend and implement CompletableFuture and CompletionStage respectively, so you can easily add this transform method yourself, as you mentioned.</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">All that said, I think asking for it for Optional makes enough sense to me. Since that class is final, you can't easily add a method onto it (typeclasses, please come soon!). That reason alone is worth asking for it. But like I said, there's not much value in it when it serves as nothing more than a shortcut for a class that, most would argue, it doesn't need.</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">Let me know your thoughts.</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">Thank you for your time!</div><div class="gmail_default" style="font-family:monospace">David Alayachew<br></div></div>