New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IfElse and Switch Functions #562

Closed
gissuebot opened this Issue Oct 31, 2014 · 8 comments

Comments

Projects
None yet
1 participant
@gissuebot

gissuebot commented Oct 31, 2014

Original issue created by attilan3i on 2011-02-25 at 02:35 PM


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.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Oct 31, 2014

Original comment posted by amertum on 2011-02-25 at 09:21 PM


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.

gissuebot commented Oct 31, 2014

Original comment posted by amertum on 2011-02-25 at 09:21 PM


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.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Oct 31, 2014

Original comment posted by jim.andreou on 2011-02-25 at 11:25 PM


I barely see any point. Can you motivate this?

gissuebot commented Oct 31, 2014

Original comment posted by jim.andreou on 2011-02-25 at 11:25 PM


I barely see any point. Can you motivate this?

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Oct 31, 2014

Original comment posted by attilan3i on 2011-02-28 at 10:52 AM


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.

gissuebot commented Oct 31, 2014

Original comment posted by attilan3i on 2011-02-28 at 10:52 AM


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.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Oct 31, 2014

Original comment posted by raymondofrish on 2011-02-28 at 01:11 PM


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.

gissuebot commented Oct 31, 2014

Original comment posted by raymondofrish on 2011-02-28 at 01:11 PM


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.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Oct 31, 2014

Original comment posted by amertum on 2011-02-28 at 01:42 PM


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.

gissuebot commented Oct 31, 2014

Original comment posted by amertum on 2011-02-28 at 01:42 PM


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.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Oct 31, 2014

Original comment posted by kevinb@google.com on 2011-03-19 at 03:16 PM


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.


Status: WontFix

gissuebot commented Oct 31, 2014

Original comment posted by kevinb@google.com on 2011-03-19 at 03:16 PM


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.


Status: WontFix

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Oct 31, 2014

Original comment posted by g.e.dejong on 2011-06-21 at 09:53 AM


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.

gissuebot commented Oct 31, 2014

Original comment posted by g.e.dejong on 2011-06-21 at 09:53 AM


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.

@gissuebot

This comment has been minimized.

Show comment
Hide comment
@gissuebot

gissuebot Oct 31, 2014

Original comment posted by gscerbak on 2011-06-21 at 03:13 PM


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?

gissuebot commented Oct 31, 2014

Original comment posted by gscerbak on 2011-06-21 at 03:13 PM


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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment