$30
1. What is the difference between
(a) System.out.println(‘‘CS2030’’), and
(b) ()->System.out.println(‘‘CS2030’’) ?
Explain in terms of the data type and the execution of the printing.
2. Consider the Point class.
(a) Complete the code below to provide the add and scale methods.
public class Point { private final double x; private final double y;
public Point(double x, double y) { this.x = x; this.y = y;
}
@Override public String toString() { return "(" + this.x + ", " + this.y + ")";
}
public Point add(Point q) {
// insert code to return a new point that is the
// sum of this point and point q. Just sum the // corresponding x and y coordinates.
}
public Point scale(double k) {
// insert code to return a new point whose x,y
// coordinates are k times those of this point. }
}
(b) Recall the generic average function:
import java.util.function.BinaryOperator; import java.util.function.BiFunction;
<T> T average(List<T> list, BinaryOperator<T> add, BiFunction<T,Double,T> scale) {
T sum = list.get(0); // assume list is non-empty int size = list.size(); for (T item : list.subList(1, size)) sum = add.apply(sum, item);
return scale.apply(sum, new Double(1.0/size));
}
Provide appropriate lambdas in the code below to compute the average of the three points.
List<Point> list = new ArrayList<>(); list.add(new Point(1.0, 1.0)); list.add(new Point(1.0, 2.0)); list.add(new Point(-1.0, 1.0)); average(list, ??, ??);
(c) Now, in the Circle class, write an add(other) method that returns a new circle whose centre is the sum of the centres of this and other circle, and whose radius is the sum of their corresponding radii.
Likewise, write a scale(k) method that returns a new circle whose radius and centre are scaled by k. Finally, create a list of three circles with different centres and radii, and find the circle whose centre lies at the average of the centres of the three, and whose radius is their average radii. Don’t forget to override the toString method in Circle for displaying it. public class Circle { private final Point centre; private final double radius;
public Circle(Point c, double r) { this.centre = c; this.radius = r;
}
//Don't change the above, but insert code here
//for add(other) and scale(k) methods
}
List<Circle> list = new ArrayList<>(); list.add(new Circle(new Point(1.0, 1.0), 1.0)); list.add(new Circle(new Point(1.0, 2.0), 4.0)); list.add(new Circle(new Point(-1.0, 1.0), 2.0)); average(list, ??, ??);
3. Read the Java documentation of the andThen method in java.util.function.Function.
(a) It is possible to compose functions without using andThen. Complete the code below to do so: import java.util.function.Function;
<T,U,R> Function<T,R> compose(Function<T,U> f, Function<U,R> g) {
// Insert code here to return a function h, such that
// h(x) = g(f(x))
}
(b) Compose the given functions f and g, and apply it to 5 to get 49 as the result. What if you wanted a result of 729?
Function<Integer,Integer> f = x -> x+2;
Function<Integer,Integer> g = x -> x*x; (c) Suppose these two methods are defined in the Point class: public double distanceTo(Point q) { return Math.sqrt(sumOfSquares(this.x - q.x, this.y - q.y));
}
public static double sumOfSquares(double a, double b) { return a*a + b*b;
}
Run the following code in JShell to see what happens. Explain. (Note that the var keyword may be used to denote “some suitable type”. The Java compiler will infer the type of the variable based on the right hand side of the assignment. Also note the use of method references.)
double howFarFromHere(Circle c, Point here) { return compose(Circle::getCentre, here::distanceTo).apply(c);
}
var c = new Circle(new Point(3.0, 4.0), 1.0); var p = new Point(0.0, 0.0); howFarFromHere(c, p);
4. Currying[1] is the conversion a function of two arguments into two functions, each taking one argument, such that their sequencing computes the same result as that of the original function.
For example: suppose f(x,y) = x + y2. Define hx(y) = x + y2, ie. it is a function of one argument y, since the value of x is fixed. Also define g(x) = hx. Then clearly, f(x,y) = hx(y) = g(x)(y). We say that curry(f) = g. This idea is readily expressed as:2
import java.util.function.BiFunction;
<X,Y,Z> Function<Y, Function<X,Z>> curry(BiFunction<X,Y,Z> f) { return y -> (x -> f.apply(x,y));
}
(a) What is the result of executing the following code, and how does this compare withslide 19 of the lecture notes on Functional Interfaces?
Function<Integer, Function<Integer, Integer>> addN = curry( (n,x) -> n+x ); Function<Integer, Integer> add5 = addN.apply(5); add5.apply(7);
(b) What is the result of: addN.apply(10).apply(7) ?
(c) What should ??? be in: ??? mystery = curry(Point::sumOfSquares); That is, what’s the type of mystery? Note that sumOfSquares was defined in Q3(c).
(d) Show how you would use mystery to calculate 32 + 42.
[1] Named after Haskell Curry. See https://en.wikipedia.org/wiki/Currying 2Look up BiFunction in the Java documentation.