Let's say that I have function Object f(String a, String b) and I want to call two different functions that return Optional Strings to get the parameters for f Optional<String> getA() and Optional<String> getB(). I can think of two solutions but neither look all that clean, especially when you have even more parameters:
1:
return getA().flatMap(
a -> getB().map(
b -> f(a,b)).get()
2:
Optional<String> a = getA();
Optional<String> b = getB();
if(a.isPresent() && b.isPresent()) {
return f(a.get(), b.get());
}
Is there a cleaner way to do this?
You've just stumbled upon a concept called lifting in functional programming, that enables you to lift regular functions (e.g. A -> B) into new domains (e.g. Optional<A> -> Optional<B>).
There's also a syntactic sugar for flatMapping and mapping more comfortably called the do notation in Haskell and similar languages, and for comprehension in Scala. It gives you a way to keep the flow linear and avoid nesting (that you were forced to go through in your example 1).
Java, unfortunately has nothing of the sort, as its functional programming capabilities are meager, and even Optional isn't really a first-class citizen (no standard API actually uses it).
So you're stuck with the approaches you've already discovered.
In case you're curious about the concepts mentioned above, read on.
Lifting
Assuming you have:
public String f(A a, B b) {
return b + "-" + a;
}
With its Scala equivalent:
def f(a: A, b: B) = b + "-" + a
Lifting f into Option (same as Optional in Java) would look like this (using Scalaz library, see here for Cats)
val lifted = Monad[Option].lift2(f)
lifted is now a function equivalent to:
public Optional<String> f(Optional<A> a, Optional<B> b) {
if(a.isPresent() && b.isPresent()) {
return Optional.of(b + "-" + a);
}
return Optional.empty;
}
Exactly what you're looking for, in 1 line, and works for any context (e.g. List, not just Option) and any function.
For comprehension / Do notation
Using for comprehension, your example would look like this (I think, my Scala is weak):
for {
a <- getA();
b <- getB();
} yield f(a, b)
And again, this is applicable to anything that can be flatMapped over, like List, Future etc.
You could stream the arguments and apply the condition only once, but whether or not this is more elegant than your solutions is in the eye of the beholder:
if (Stream.of(a, b).allMatch(Optional::isPresent)) {
return f(a.get(), b.get());
}
I'm of the opinion that if there is no good way to use Optional, then there is no reason to try to use it anyway.
I find this to be cleaner and simpler than your option 2:
String a = getA().orElse(null);
String b = getB().orElse(null);
if(a != null && b != null) {
return f(a, b);
}
If you are sure that a and b are both present (as your final call to get in solution 1 seems to suggest), I think it is pretty straightforward:
return f(getA().orElseThrow(() -> new NoSuchElementException("a not present")),
getB().orElseThrow(() -> new NoSuchElementException("b not present")));
If you aren’t sure that both are present, I would prefer your solution 1. It exploits Optional the best. Only I would not call get at the end, but rather orElse or what makes sense in your situation, for example:
return getA()
.flatMap(a -> getB().map(b -> f(a,b)))
.orElse("Not both present");
Related
In this question the author uses the following example:
#Override
public final OptionalInt max() {
return reduce(Math::max); //this is the gotcha line
}
So in this case it looks as if max() is a proxy for Math.max on the instance of this class. However there are no arguments passed to max, so does java 8 compile this to something like (Pseudo code):
#Override
public final OptionalInt max(Integer a, Integer b) {
//If neither a or b are null
return new OptionalInt.of(Math.max(a,b));
//Otherwise return empty because we can't compare the numbers
return OptionalInt.empty()
}
Also how would one write the javadoc for something like this?
So in this case it looks as if max() is a proxy for Math.max on the instance of this class. However there are no arguments passed to max, so does java 8 compile this to something like (Pseudo code):
#Override
public final OptionalInt max(Integer a, Integer b) {
//If neither a or b are null
return new OptionalInt.of(Math.max(a,b));
//Otherwise return empty because we can't compare the numbers
return OptionalInt.empty()
}
Not quite :). Let's start by figuring out what the reduce operator actually does. The documentation explains that it performs a reduction on a sequence of numbers by applying an algorithm that is logically equivalent to the following:
public OptionalInt reduce(IntBinaryOperator op) {
boolean foundAny = false;
int result = 0;
for (int element : [this stream]) {
if (!foundAny) {
foundAny = true;
result = element;
}
else {
result = op.applyAsInt(result, element);
}
}
return foundAny ? OptionalInt.of(result)
: OptionalInt.empty();
}
Seems simple enough. If you can tell it how to take two numbers and 'reduce' or 'combine' them into one, then reduce knows how to extend that logic to reduce an entire sequence into a single number. It handles the edge cases and the aggregation for you. All it needs from you is a function that takes in two numbers and gives it one back. That function should conform to the functional interface IntBinaryOperator.
A functional interface is an interface that is meant to describe a single function. Specifically, it describes the argument types and the return type. The rest is largely superfluous. The signature for an IntBinaryOperator looks like this:
int applyAsInt(int left, int right);
You can provide a function that conforms to this specification in several ways. Prior to Java 8, you might have done something like this:
stream.reduce(
new IntBinaryOperator() {
public int applyAsInt(int a, int b) {
return b > a ? b : a;
}
}
);
Java 8 gives us a shorthand form for functional interfaces called lambda expressions. These are a bit more concise, and while they are conceptually similar to anonymous inner classes, they're not quite the same thing.
stream.reduce((a, b) -> b > a ? b : a);
Both functions above are equivalent: they take in two numbers and return the larger of the two. As it turns out, every standard programming library has a function that does exactly the same thing. In Java, that function is Math.max. So rather than writing this logic myself, I can delegate to Math.max:
stream.reduce((a, b) -> Math.max(a, b));
But wait! All reduce wants is a function that takes two numbers and returns one. Math.max does that, so do I even need to wrap it in a lambda? It turns out I don't; I can tell reduce to just call Math.max directly:
stream.reduce(Math::max);
This says "I know you want a function, so I'm show you by name where to find one that's already been written". The compiler knows that Math.max conforms to the (int, int) -> int specification we need, so it emits some bytecode telling the VM how to 'bootstrap' it once it's needed. When the JVM hits your call to reduce, it calls a special method that generates a wrapper class implementing IntBinaryOperator that delegates to Math.max in its implementation of applyAsInt. It only performs this 'bootstrapping' step once. Since calling Math.max doesn't rely on anything other than the two numbers that get passed in, it can cache that implementation and use it the next time you wind up on this code path.
Pre Java 8, this would have been written as:
public MyMathInteface {
OptionalInt max(Integer a, Integer b);
}
public static final MyMathInterface reducing = new MyMathInterface() {
#Override
public OptionalInt max(Integer a, Integer b) {
return OptionalInt.of(Math.max(a, b));
}
};
#Override
public final OptionalInt max() {
return reduce(reducing);
}
Then reduce would be defined as:
public static OptionalInt reduce(MyMathInteface toReduce) {
return toReduce.max(someValueA, someValueB);
}
So to answer your question, no arguments are passed to Math::max, because those values are retrieved by the reduce function. They could be constants or they could be retrieved from some other place.
In any case, the use of the max method in this way is called a method reference, that is where you do SomeObject::method. That :: operator creates a method reference. It returns a function, but does not call the function. The user (reduce) is responsible for calling the function.
I have the following problem. Let's say you have 2 Optional variables
Optional<Contact> c1 = ...
Optional<Contact> c2 = ...
and a method which needs 2 variables of type Contact
void match(Contact c1, Contact c2) {...}
and you need to unwrap both c1 and c2 Optional vars and pass them into the match() method.
My question is "Which is the most elegant way to do that in Java 8?"
So far I've found 2 ways:
by using isPresent
if (c1.isPresent() && c2.isPresent()) {
match(c1.get(), c2.get());
}
by using nested ifPresent
c1.ifPresent((Contact _c1) -> {
c2.ifPresent((Contact _c2) -> {
match(_c1, _c2);
});
});
Both ways are terrible in my opinion. In Scala I can do this:
for {
contact1 <- c1
contact2 <- c2
} yield {
match(contact1, contact2);
}
is there a way in Java 8 to do it neater than I outlined above?
Solution you provided in scala is just syntax sugar for using flatMaps internally. You can use flatmaps in Java 8 too (but there are no syntax sugar for it).
c1.flatMap(contact1 -> c2.flatMap(contact2 -> match(contact1, contact2)));
it is almost the same thing as solution 2 you provided. You also can use applicative functor from https://github.com/aol/cyclops-react (I'm one of contributors) or any other functional java 8 library.
Applicative functor
Optional<String> o3 = Maybe.fromOptional(o1).ap2(String::concat).ap(o2).toOptional();
For-comprehension
Do.add(o1)
.add(o2)
.yield(a->b->a.concat(b));
You could desugar the Scala for-comprehension to map/flatMap in Java 8 with a function like:
public static <T,K,V> Optional<V> map2(Optional<T> opt1, Optional<K> opt2, BiFunction<T, K, V> f) {
Optional<V> result = opt1.flatMap(t1 -> opt2.map(t2 -> f.apply(t1, t2)));
return result;
}
And then pass your function match
If you consider the arguments not having values as an exception then you could handle them like:
try {
match(c1.orElseThrow(NoVal::new), c2.orElseThrow(NoVal::new));
} catch (NoVal ex) {
...
}
If they aren't an exceptional case then I would go with your first option as being more explicit about your intent. In my view it's pretty clear and readable, and easy to change to use orElse if you wish to switch to using defaults if the optionals are empty.
What is a first class citizen function?
Does Java supports first class citizen function?
Edit:
As mention on Wikepedia
First class functions are a necessity
for the functional programming style.
Is there any other use of first class functions?
A language that considers procedures to be "first-class" allows functions to be passed around just like any other value.
Languages like Java 7 (and earlier) and C "kind of" have this capability: C allows function pointers to be passed around, but you can't dynamically define a function in those languages and suddenly pass that somewhere else. Java before version 8 can simulate this to a certain extent with anonymous classes, but it doesn't technically have first-class functions.
On the other hand, C++, D, C#, Visual Basic .NET, Java 8+, and functional languages (like Scheme and Haskell) do allow you to pass around functions like variables. For example, the code below returns a function that adds addend to its input:
Written in D:
int delegate(int) makeAdder(int addend) //Returns a function
{
return delegate int(int x) //Long way
{
return x + addend; //Notice that addend came from _outside_ the function
};
return (int x) { return x + addend; }; //Short way
return x => addend + x; //Super-short way, introduced in D 2.058
}
Written in C#:
Func<int, int> MakeAdder(int addend) //Returns a function
{
return delegate(int x) //The long way. Note: Return type is implicitly 'int'
{
return x + addend;
};
return x => x + addend; //Short way: x "goes to" (x + addend); inferred types
}
Written in C++:
#include <functional>
std::function<int(int)> make_adder(int addend)
{
return [=](int x)
{
return addend + x;
};
}
Written in Scala:
def makeAdder(addend: Int) = (x: Int) => addend + x
Written in Python:
def make_adder(addend):
def f(x):
return addend + x
return f
# or...
return lambda x: addend + x
Written in Erlang:
make_adder(Addend) ->
fun(X) -> Addend + X end.
Written in JavaScript:
function makeAdder(addend) {
return function(x) {
return addend + x;
};
}
Written in JavaScript (ES2015 arrow function syntax):
const makeAdder = addend => x => addend + x;
Written in Scheme:
(define (makeAdder addend)
(lambda (x)
(+ x addend)))
Written in Haskell:
makeAdder :: Int -> (Int -> Int)
makeAdder addend = \x -> addend + x
Written in Visual Basic 2008:
Function MakeAdder(addend As Integer) As Func(Of Integer, Integer)
Return Function(x) (x + addend)
End Function
Written in Swift (both verbose and short-hand implementations):
func makeAdder(append: Int) -> (x: Int) -> Int {
return { (x: Int) -> Int in
return x + append
};
}
func makeAdder(append: Int) -> (Int) -> Int {
return {$0 + append};
}
(By the way, a "lambda" is just a function without a name. Lambdas are only supported in languages that support first-class functions.)
Let us consider the example of functional programming paradigm in which functions are the first class citizens. When we say functions are the first class citizens, we can do the following things with the function...
Function can be assigned to a variable
Function can be stored in a data structure
Function can be passed around as an argument to other functions
Function can be returned from the functions
In functional programming languages, it is possible to do the above mentioned things.
Now, let us try to answer the question, whether java supports first class citizen functions (or) not.
In java, methods are equivalent of functions. It is not possible to do any of the above with methods. But all of the above are possible with java objects. So, objects are the first class citizens in java. Admittedly, java8 supports passing of methods (method behavior, to be precise) to other methods using functional interfaces and lambda expressions. But that does not mean that java has functions as first class citizens.
The ability to do above things such as passing around functions, returning functions from functions is very powerful and useful. This is because, it allows us to pass around the behavior not just the data.
A first class function can be passed around. A typical example is the map function. Here is an example in Scala that squares the elements of a list:
val square = (x:Int) => x*x
val squaredList = List(1,2,3,4).map(square _)
//--> List(1,4,9,16)
The square function is here an argument to the map method, which applies it to every element. If you want to do something like this in Java, you have to use a method wrapped in a class, something like this:
interface F<A,B>{ B apply(A a); }
static <A,B> List<B> map(List<A> list, F<A,B> f) {
List<B> result = new ArrayList<B>();
for(A a:list) result.add(f.apply(a));
return result;
}
//we have to "wrap" the squaring operation in a class in order to make it a function
F<Integer,Integer> square = new F<Integer,Integer>(){
Integer apply(Integer a) { return a*a; }
}
List<Integer> ints = Arrays.<Integer>asList(1,2,3,4);
List<Integer> squares = map(ints, square);
Looking at this you can see that you can get the same task somehow done in Java, but with more overhead, and without "native" support by the language, but by using a workaround (wrapper classes). So Java doesn't support first class functions, but can "simulate" them.
Hopefully Java 8 will support first class functions. If you want to have some support for this now, look at http://functionaljava.org/ or http://functionalj.sourceforge.net/ , or have a look at the Scala language.
The Wikipedia definition is pretty good—it's a function that can be passed around like any other piece of data. Java does not support them. The closest it has is Runnable and Callable objects.
The above answers for #Alpine questions are mostly defining what is First Class Functions along with examples. But still, one question remains why to use?
I'll try to answer the benefits a little differently in Scala where first-class functions are used further as higher-order functions(map, flatMap), Partially Applied Functions and Currying:
As we focus on declarative programming, the how part of processing the data is left as an implementation detail to map, flatMap, and focused more on handling the what actual logic flow.
A caller can specify what should be done and leave the higher-order functions to handle the actual logic flow.
Partially Applied Functions and Currying: What if you wanted to reuse a function invocation and retain some of the parameters to avoid typing them in again?
Partially Applied Function Example:
def factorOf(x: Int, y: Int) = y % x == 0
val multipleOf3 = factorOf(3, _: Int)
val y = multipleOf3(78)
Currying Example:
def factorOf(x: Int)(y: Int) = y % x == 0
val isEven = factorOf(2) _
val z = isEven(32)
The above examples show you how you can reuse the part of first-class functions by not passing all parameters and keep your code DRY principle.
These are few benefits for using first-class functions
Reference for more details: https://www.oreilly.com/library/view/learning-scala
No, you cannot assign a method to a variable or pass it as an argument to another method for example.
Instead you can use interfaces to wrap the intended behaviour, or reflection to reify methods.
Functions are first class citizen means you can pass function anywhere as if it's a variable.
From Scala
def isOdd(in: Int) = in % 2 == 1
val n = (1 to 10).toList
n.filter(isOdd)
see here: isOdd is a function. passed as if it's a variale.
Objects are first class citizen in Java. A first class citizen is the one that can be passed anywhere. The parallel is from a first class citizen of country are allowed almost everywhere.
Read:
When is a feature considered a “First class citizen” in a programming language/platform?
First-class object
First-class function
I'm looking for an elegant way to use values in a Java enum to represent operations or functions. My guess is, since this is Java, there just isn't going to be a nice way to do it, but here goes anyway. My enum looks something like this:
public enum Operator {
LT,
LTEQ,
EQEQ,
GT,
GTEQ,
NEQ;
...
}
where LT means < (less than), LTEQ means <= (less than or equal to), etc - you get the idea. Now I want to actually use these enum values to apply an operator. I know I could do this just using a whole bunch of if-statements, but that's the ugly, OO way, e.g.:
int a = ..., b = ...;
Operator foo = ...; // one of the enum values
if (foo == Operator.LT) {
return a < b;
}
else if (foo == Operator.LTEQ) {
return a <= b;
}
else if ... // etc
What I'd like to be able to do is cut out this structure and use some sort of first-class function or even polymorphism, but I'm not really sure how. Something like:
int a = ..., b = ...;
Operator foo = ...;
return foo.apply(a, b);
or even
int a = ..., b = ...;
Operator foo = ...;
return a foo.convertToOperator() b;
But as far as I've seen, I don't think it's possible to return an operator or function (at least, not without using some 3rd-party library). Any suggestions?
Not only is this possible, it's used as an example in the frequently referenced Effective Java, Second Edition by Josh Bloch. I don't want to step on his copyright, will look for a similar example online...
Okay, the code I remembered is freely available at the website I linked earlier. Click "Download the code samples used in this book", then look at effective2/examples/Chapter6/Item30/Operation.java.
int a = ..., b = ...;
Operator foo = ...;
return foo.apply(a, b);
it is possible to do this if foo is object and Operator is base class and concrete operators are concrete classes that implement apply.
My question is eerily similar to "Writing a generic class to handle built-in types" including being inspired by the fact of working on a class to handle operations on matrices.
Although that question was asked using C# and pointed to an article on Generic Operators.
I don't get it. Java Number does not have an add method so you can have a method like:
public Number myAdd(Number a, Number b){
return a.add(b);
}
So how do you handle a case where you want to be able to handle multiple types of Numbers in Java?
The fundamental problem is with the Java type system which is very primitive.
Since there is no notion of a sealed set of types in Java (nor is it possible for Java to infer the types like Haskell does) there is no way to make make a general Number + Number -> Number without trickery.
For primitives (and those objects like Integer which can be automagically mapped to them) types promotion and the + operation is part of the language. (And this is actual part of the problem: what should Number a + Number b return where a and b are of different types?)
If you really want this behavior you'll have to find (or create) your own custom class that either uses reflection or a series (of checks and) casts and such. Even if you use generics (remember that generics are type-erased) casting will need to be done.
I imagine these problems are part of the reason why Number is as bland as it is.
How good do you want the result to be? If the answer is "good enough, mostly", then this should be sufficent:
public Number myAdd(Number a, Number b){
return a.doubleValue() + b.doubleValue();
}
But if you want something that, say, matches the promotion semantics of Java primitives, you're probably going to have to write it yourself. And then you'll have to figure out what the rules are for all combinations of "non-standard" Number implementations, including BigDecimal, BigInteger, AtomicDouble, AtomicLong, everything in org.apache.commons.lang.mutable, and any random implementation that somebody might decide to write next Tuesday.
It's not clear what the right thing to do is in most of these cases -- converting everything to BigDecimal, for instance, is not an option if one of the arguments is Apache Commons' Fraction.ONE_THIRD; and besides, doing the conversion in a general way presents the same problems as doing the addition in a general way. But having an add() method on Number would require every Number implementation to handle all these cases -- and that's probably why it isn't there.
I don't get it. Java Number does not
have an add method ...
Suppose that java.lang.Number did have an add method or methods, how would you define its signature? How would you define its semantics? How would you deal with "mixed mode" arithmetic?
While it is no doubt possible to answer these questions and design an API, the result is likely to be tricky to use correctly. In addition, it is most unusual for an application to need to perform "representation agnostic" arithmetic. Usually you want / need explicit control over the way that arithmetic is performed and conversions happen. (The Java primitive type promotion rules are already difficult enough for people to get their heads around!!)
All in all, I think that Sun have done us a good service by not trying to support arithmetic in the Number API.
One way of implementing a generic add method is to let the left hand argument infer the return type.
package mixins;
import java.math.BigDecimal;
public class Numbers {
public static boolean isZ(Number n) {
return n instanceof Integer || n instanceof Long || n instanceof Short || n instanceof Byte;
}
public static boolean isR(Number n) {
return n instanceof Double || n instanceof Float;
}
public static BigDecimal add(BigDecimal a, Number b) {
if (b instanceof BigDecimal) {
return a.add((BigDecimal) b);
} else if (isZ(b)) {
return a.add(new BigDecimal(b.longValue()));
} else if (isR(b)) {
return a.add(new BigDecimal(b.doubleValue()));
}
throw new IllegalArgumentException("No valid big decimal translation for " + b.getClass());
}
public static Integer add(Integer a, Number b) {
return a + b.intValue();
}
public static Long add(Long a, Number b) {
return a + b.longValue();
}
public static Float add(Float a, Number b) {
return a + b.floatValue();
}
public static Double add(Double a, Number b) {
return a + b.doubleValue();
}
}
If this is implemented as static methods, you can use static imports.
import static mixins.Numbers.*;
public class Example {
public static void main(String[] args) {
BigDecimal fortytwo = new BigDecimal(42);
BigDecimal fiftyfive = add(fortytwo, 13);
System.out.println(fiftyfive);
}
}
You cannot add any two numbers, for the reasons other pointed out, but you can add numbers of same type, and the result will also be that same type.
You can create generic arithmetics in Java, with something like this:
interface Arithmetics<T> {
T add(T val1, T val2);
}
class IntegerArithmetics implements Arithmetics<Integer> {
Integer add(Integer val1, Integer val2) { return val1 + val2; }
}
//similarly DoubleArithmetics, BigIntegerArithmetics, ...
Generic Java Math library does exactly that for you.
Actually, I've been working on a generic "real" number class (called 'Value') for a while now, but more as a design exercise than anything; and I can see why it hasn't been done sooner.
First off, you have to have to have some basic rules to work by - I chose to use Java FP (IEEE-754) rules - which means you have have to allow for results like 'infinity' and 'NaN', even if the type doesn't actually support them; and things like reciprocals have proved surprisingly tricky. But I'm getting there, and it's been a fun journey.
One thing that helped me was deciding early on that I needed to deal with "identity" values - specifically 0, 1, and -1, along with -0, +/-infinity and NaN as special cases; the reason being that (for example) multiplication by any of them usually doesn't need any calculation at all.
x * 1 = x, x * NaN = NaN, x * 0 = 0 (or NaN), and x * +/-infinity = +/-infinity; and there are similar rules for division, addition and subtraction, which means you can eliminate a lot of dross quickly and consistently.
And that leaves implementers to only have to deal with cases that do need calculation.
Of course, not all types will support all identities, but if you make them methods, you can just throw an exception when either an operand or a result is "unsupported".
Hope it helps anyone else interested in giving it a bash, but it's not as simple it looks. :-)
Personally, I use BigDecimals for almost everything (but that is mainly because I work with currency values). They handle all numeric values of any size. Because of that, in my opinion they are a generic value and could be used as such in your hypothetical example instead of the Number abstract class. Everything can be turned into a BigDecimal, why not use it?
public BigDecimal myAdd(BigDecimal a, BigDecimal b) {
return a.add(b);
}
EDIT: To address BigBrothers comment below, you could always use the doubleValue() method to create your own generic method. The only problem with this is that you may lose precision in some rare cases where someone IS passing in a BigDecimal and it is larger than a Double.maxValue
public Number myAdd(Number a, Number b) {
return new BigDecimal(a.doubleValue() + b.doubleValue());
}
A BigDecimal is a Number, so returning one is of no consequence.