cogitate / guava-libraries

Automatically exported from code.google.com/p/guava-libraries
Apache License 2.0
0 stars 0 forks source link

IfElse and Switch Functions #562

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
They would look something like this:

    Function<Integer, String> ifElseFunction = Functions
        .If(Predicates.equalTo(1), oneFunction)
        .ElseIf(Predicates.equalTo(2), twoFunction)
        .ElseIf(Predicates.equalTo(3), threeFunction)
        .Else(elseFunction);

    Function<Integer, String> switchFunction = Functions
        .Switch()
        .Case(1, oneFunction)
        .Case(2, twoFunction)
        .Case(3, threeFunction)
        .Default(defaultFunction);

In both cases the final Else/Default creates the actual resulting function, 
until then the same instance of a public builder object is returned.

For the Switch there can be a version that takes a Map argument, through this 
the user can specify what kind of Map to use for case-value/case-function pairs.

Original issue reported on code.google.com by attilan3i@gmail.com on 25 Feb 2011 at 2:35

GoogleCodeExporter commented 9 years ago
What about ?

Map<Integer, Function<Integer, String>> conditions = ImmutableMap.of(1, 
oneFunction, 2, twoFunction, 3, threeFunction);
Function<Integer, Function<Integer, String>> strategy = 
Functions.forMap(conditions, elseFunction);
strategy.apply(someIntValue).apply(someIntValue);

OK, the double apply(someIntValue) is not very pretty but it does work.

Original comment by amer...@gmail.com on 25 Feb 2011 at 9:21

GoogleCodeExporter commented 9 years ago
I barely see any point. Can you motivate this?

Original comment by jim.andreou on 25 Feb 2011 at 11:25

GoogleCodeExporter commented 9 years ago
I thought the "If" will motivate itself. I mean if you want to branch the 
transformation of the input based on some conditions (applied on some aspects 
of the input), it seems to me, that the "If" could be generally useful in 
certain situations.

The "Switch" is a bit too much, I agree, it's just there because it is possible 
and if we have the "If", then we could have the Switch as well.

In my work, there was a moment when we needed something, that in the end we 
were able to solve with this "If" pattern. Granted, we don't use it that much. 
Since it is a general pattern, and not too bad I think, I thought I'll share 
here, let's see what the community thinks about it.

@amer...@gmail.com
Interesting alternative, I never used Functions.forMap before, but I think I 
like the "Switch" pattern better.

Original comment by attilan3i@gmail.com on 28 Feb 2011 at 10:52

GoogleCodeExporter commented 9 years ago
I agree that barely useful and has almost no added value. But to play devil's 
advocate... 
Much of what Guava adds in my application is expressiveness. Finally we have 
comparators that anyone can understand at a glance. We can turn a list into a 
map, and it's clear what the key is. This business with the 
maps-as-functions... it's just not clear what it does. Whatever else you might 
argue about them, attilan3i's functions are expressive.

Original comment by raymondofrish on 28 Feb 2011 at 1:11

GoogleCodeExporter commented 9 years ago
IMHO, it is better to use a configuration Map instead of ifElse or switchCase 
DSL builder pattern, because it is Object Oriented and more "guava philosophy" 
for me. If and Switch are procedurals.
If you use ifElse or switchCase builder DSL why not use the one provided with 
the language.

If you want to generalize, you can implements a strategy function which takes a 
Iterable<Map.Entry<Predicate<I>, Function<I, O>>> strategyEntries and iterates 
over until a predicate matches and then apply the function.

Original comment by amer...@gmail.com on 28 Feb 2011 at 1:42

GoogleCodeExporter commented 9 years ago
This stuff seems to cross a certain ill-defined line for me; it trips my "wants 
Java to not be Java" detector, so to speak.  Thanks for the suggestion, but I'm 
going with the other opinions expressed that this is not necessary.

Original comment by kevinb@google.com on 19 Mar 2011 at 3:16

GoogleCodeExporter commented 9 years ago
To me it seems to be a quite reasonable request. I already found such a 
function useful, although I implemented a conditional 'two-way' function, using 
a predicate and two functions. Eg. new ConditionalFunction(pred, trueFunction, 
falseFunction), created with a static likewise named factory method. Else-if 
constructions can then be made by nesting another function in the else part. 
The Builder pattern described above is also quite elegant.

Although it might seem iterative, it does not have side effects, it is an 
expression and can be evaluated at any time. It seems a genuine addition and 
most definitely functional. Haskell has similar expressions.

Original comment by g.e.dej...@gmail.com on 21 Jun 2011 at 9:53

GoogleCodeExporter commented 9 years ago
Your Switch is just a special case of conditional, making the distinction would 
be misleading, because it isn't Java switch with breaks and it isn't functional 
pattern matching.

My implementation of the example would look like this:

new Function<Integer, String>() {
    public String apply(final Integer input) {
        return (input == 1 ? oneFunction : 
                   input == 2 ? twoFunction : 
           input == 3 ? threeFunction : 
           elseFunction;
        ).apply(input);
    }
};

Like the Functions.forMap this has a significant flaw - it does not use 
Predicates. 

Functions.forMap with Predicates and more branches will get pretty ugly to 
write yourself every time.

I don't like that the example applies the resulting Function, it stops 
conditionals from being composable with other Functions. 
The first type parameter of the resulting Function can be different from the 
type parameter of the Predicate (this makes sense of two applies in 
Functions.forMap implementation).

I vote for this issue, we have Functions, Predicates and lazy Iterables, but no 
lazy conditionals?

Original comment by gscerbak@gmail.com on 21 Jun 2011 at 3:13

GoogleCodeExporter commented 9 years ago
This issue has been migrated to GitHub.

It can be found at https://github.com/google/guava/issues/<id>

Original comment by cgdecker@google.com on 1 Nov 2014 at 4:15

GoogleCodeExporter commented 9 years ago

Original comment by cgdecker@google.com on 3 Nov 2014 at 9:09