New method on java.util.function.Function -- ternary method

David Alayachew davidalayachew at gmail.com
Mon Jan 1 06:36:44 UTC 2024


Here is a direct link to that formatting error. Same link as above.
https://bugs.openjdk.org/browse/JDK-8319802

On Mon, Jan 1, 2024 at 1:29 AM David Alayachew <davidalayachew at gmail.com>
wrote:

> On a side note, I spy a formatting error in the first code block. Looks
> like the backticks shouldn't be there, and I think the phrase following
> them should be outside of the code block.
>
> On Mon, Jan 1, 2024 at 1:26 AM David Alayachew <davidalayachew at gmail.com>
> wrote:
>
>> Hello all,
>>
>> After reading through Brian Goetz's "Effect cases on Switch"
>> (specifically, the "Other switch tricks" section), I have decided to not
>> implement this feature after all. The fact is, switch expressions,
>> especially with "when-clauses", does a better job of clarifying intent than
>> this feature does. Sure, there is slightly more verbosity, but the intent
>> of this feature was never to minimize the character count, it was to
>> increase clarity. And as is, switch expressions with when clauses
>> accomplish that better.
>>
>> Here is a link to the subsection of the abovementioned article --
>> https://inside.java/2023/12/15/switch-case-effect/#other-switch-tricks
>>
>> Could someone help me close this on JBS? Or should it just not be closed
>> at all?
>>
>> Here is a link to the JBS -- https://bugs.openjdk.org/browse/JDK-8319802
>>
>> Thank you for your time and help!
>> David Alayachew
>>
>> On Thu, Nov 9, 2023 at 1:19 AM David Alayachew <davidalayachew at gmail.com>
>> wrote:
>>
>>> Oh, I will also add a specialized version of this method to
>>> java.util.function.UnaryOperator. That is because UnaryOperator is a
>>> subinterface of Function. Function goes T -> R, but UnaryOperator just goes
>>> T -> T. We do not want UnaryOperator to have the T -> R static function
>>> included due to inheritance, so it will get its own version that has the
>>> same method name and parameters, but the type parameters will be different.
>>>
>>> Here is another mockup - this time for UnaryOperator2's version of the
>>> same method.
>>>
>>> > interface UnaryOperator2<T> extends Function2<T,T>, UnaryOperator<T>
>>> > {
>>> >
>>> >     public static <T> UnaryOperator2<T> ternaryApply
>>> >     (
>>> >         Predicate<? super T> test,
>>> >         Function<? super T, ? extends T> trueFunction,
>>> >         Function<? super T, ? extends T> falseFunction
>>> >     )
>>> >     {
>>> >
>>> >         return
>>> >             (T input) ->
>>> >                 test.test(input)
>>> >                     ? trueFunction.apply(input)
>>> >                     : falseFunction.apply(input)
>>> >                     ;
>>> >
>>> >     }
>>> >
>>> > }
>>>
>>> On Thu, Nov 9, 2023 at 12:12 AM David Alayachew <
>>> davidalayachew at gmail.com> wrote:
>>>
>>>> It has been a month since I sent this proposal. Since no one has told
>>>> me that this is a terrible idea, I will submit this as an enhancement to
>>>> JBS, and once the ticket is made, start work on creating a pull request.
>>>>
>>>> On Tue, Oct 3, 2023 at 3:13 AM David Alayachew <
>>>> davidalayachew at gmail.com> wrote:
>>>>
>>>>> Whoops, bad import.
>>>>>
>>>>> Please replace the following line with the one after it.
>>>>>
>>>>> > import java.util.function.Function;
>>>>>
>>>>> > import java.util.function.*;
>>>>>
>>>>> On Tue, Oct 3, 2023 at 3:09 AM David Alayachew <
>>>>> davidalayachew at gmail.com> wrote:
>>>>>
>>>>>> Hello all,
>>>>>>
>>>>>> I have an idea that I want to run by you all -- a new method on
>>>>>> java.util.function.Function to capture ternary operations.
>>>>>>
>>>>>> Here is a mockup of what I wanted to do.
>>>>>>
>>>>>> >
>>>>>> > import java.util.function.Function;
>>>>>> >
>>>>>> > @FunctionalInterface
>>>>>> > public interface Function2<I, O> extends Function<I, O>
>>>>>> > {
>>>>>> >
>>>>>> >    public static <I, O> Function<I, O> ternary
>>>>>> >    (
>>>>>> >        Predicate<I> test,
>>>>>> >        Function<I, O> trueOutput,
>>>>>> >        Function<I, O> falseOutput
>>>>>> >    )
>>>>>> >    {
>>>>>> >
>>>>>> >       return
>>>>>> >           (I input) ->
>>>>>> >               test.test(input)
>>>>>> >               ? trueOutput.apply(input)
>>>>>> >               : falseOutput.apply(input)
>>>>>> >               ;
>>>>>> >
>>>>>> >    }
>>>>>> >
>>>>>> > }
>>>>>> >
>>>>>>
>>>>>> I think this is useful for a few reasons.
>>>>>>
>>>>>>  * This composes, just like the ternary operator itself.
>>>>>>
>>>>>>  * It pairs well with Function.identity() and method references to
>>>>>> clearly (but concisely) communicate intent.
>>>>>>
>>>>>>  * Ternary operations are common, so this will find great use by
>>>>>> developers of all sorts.
>>>>>>
>>>>>> There is at least one part I don't quite like about this design -
>>>>>> what if one (or both!) of your outputs is not a functional transformation
>>>>>> of the input?
>>>>>>
>>>>>> For example, String username = id.isBlank() ? "UNKNOWN" : lookup(id);
>>>>>>
>>>>>> Obviously, this is easy to work around - simply ignore the input of
>>>>>> the function. But you lose clarity and simplicity that way. I would put a
>>>>>> note in the javadoc that says that this method should only be used in
>>>>>> instances where both outputs are a functional transformation of the input.
>>>>>> That way, intent is clarified. But if we go that route, maybe this function
>>>>>> should get a better name to capture that? testThenApply? ternaryTransform?
>>>>>> ternaryApply?
>>>>>>
>>>>>> Thank you for your time and help!
>>>>>> David Alayachew
>>>>>>
>>>>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20240101/7c436a17/attachment.htm>


More information about the amber-dev mailing list