Task: First-class functions





Java: import java.util.ArrayList;

public class FirstClass{
	
	public interface Function<A,B>{
		B apply(A x);
	}
	
	public static <A,B,C> Function<A, C> compose(
			final Function<B, C> f, final Function<A, B> g) {
		return new Function<A, C>() {
			@Override public C apply(A x) {
				return f.apply(g.apply(x));
			}
		};
	}
	 
	public static void main(String[] args){
		ArrayList<Function<Double, Double>> functions =
			new ArrayList<Function<Double,Double>>();
		
		functions.add(
				new Function<Double, Double>(){
					@Override public Double apply(Double x){
						return Math.cos(x);
					}
				});
		functions.add(
				new Function<Double, Double>(){
					@Override public Double apply(Double x){
						return Math.tan(x);
					}
				});
		functions.add(
				new Function<Double, Double>(){
					@Override public Double apply(Double x){
						return x * x;
					}
				});
		
		ArrayList<Function<Double, Double>> inverse = new ArrayList<Function<Double,Double>>();
		
		inverse.add(
				new Function<Double, Double>(){
					@Override public Double apply(Double x){
						return Math.acos(x);
					}
				});
		inverse.add(
				new Function<Double, Double>(){
					@Override public Double apply(Double x){
						return Math.atan(x);
					}
				});
		inverse.add(
				new Function<Double, Double>(){
					@Override public Double apply(Double x){
						return Math.sqrt(x);
					}
				});
		System.out.println("Compositions:");
		for(int i = 0; i < functions.size(); i++){
			System.out.println(compose(functions.get(i), inverse.get(i)).apply(0.5));
		}
		System.out.println("Hard-coded compositions:");
		System.out.println(Math.cos(Math.acos(0.5)));
		System.out.println(Math.tan(Math.atan(0.5)));
		System.out.println(Math.pow(Math.sqrt(0.5), 2));
	}
}







Ada: with Ada.Float_Text_IO,
     Ada.Integer_Text_IO,
     Ada.Text_IO,
     Ada.Numerics.Elementary_Functions;

procedure First_Class_Functions is
   use Ada.Float_Text_IO,
       Ada.Integer_Text_IO,
       Ada.Text_IO,
       Ada.Numerics.Elementary_Functions;

   function Sqr (X : Float) return Float is
   begin
      return X ** 2;
   end Sqr;

   type A_Function is access function (X : Float) return Float;

   generic
      F, G : A_Function;
   function Compose (X : Float) return Float;

   function Compose (X : Float) return Float is
   begin
      return F (G (X));
   end Compose;

   Functions : array (Positive range <>) of A_Function := (Sin'Access,
                                                           Cos'Access,
                                                           Sqr'Access);
   Inverses  : array (Positive range <>) of A_Function := (Arcsin'Access,
                                                           Arccos'Access,
                                                           Sqrt'Access);
begin
   for I in Functions'Range loop
      declare
         function Identity is new Compose (Functions (I), Inverses (I));
         Test_Value : Float := 0.5;
         Result     : Float;
      begin
         Result := Identity (Test_Value);

         if Result = Test_Value then
            Put      ("Example ");
            Put      (I, Width => 0);
            Put_Line (" is perfect for the given test value.");
         else
            Put      ("Example ");
            Put      (I, Width => 0);
            Put      (" is off by");
            Put      (abs (Result - Test_Value));
            Put_Line (" for the given test value.");
         end if;
      end;
   end loop;
end First_Class_Functions;