title: Java: Implement recursive cached from cached Function and cached BiFunction
body: <p>TLDR: How to implement this function?</p>
  <pre><code>public static &lt;T, R&gt; Function&lt;T, R&gt; cachedRecursive(final BiFunction&lt;T, Function&lt;T,R&gt;, R&gt; bifunc) {
          
      }
  </code></pre>
  <p>I need to somehow extract the second argument from the BiFunction so I can return a proper result for the function.</p>
  <p>This project is for learning purposes, although I'm stuck with the last part of my task.</p>
  <p>First part of the task is to create a Cache class extended from the LinkedHashMap, and this is my Implementation:</p>
  <pre><code>public class Cache&lt;K,V&gt; extends LinkedHashMap&lt;K, V&gt; {
  
  
      private static int MaxSize;
      
      public Cache (int maxSize) {
          super(maxSize,1f,false);
          MaxSize = maxSize;
      }
      
      public Cache () {
          super();
      }
      
      public int getMaximalCacheSize () {
          return MaxSize;
      }
  
      @Override
      protected boolean removeEldestEntry(Map.Entry&lt;K, V&gt; eldest) {
          return size() &gt; MaxSize;
      }
  }
  </code></pre>
  <p>As for the second part, it is to create a class for which the function definitions will be added:</p>
  <pre><code>public class FunctionCache {
      
      private static class Pair&lt;T, U&gt; {
          private T stored_t;
          private U stored_u;
          
          public Pair(T t, U u) {
              stored_t = t;
              stored_u = u;
          }
          
          public boolean equals(Object t) {
              
              if (t == this) {
                  return true;
              }
              
              return t == stored_t;
          }
          
          public int hashCode () {
              return stored_t.hashCode();
          }
          
          public T get_first() {
              return stored_t;
          }
          
          public U get_second() {
              return stored_u;
          }
      }
      
      private final static int DEFAULT_CACHE_SIZE = 10000;
      
      public static &lt;T, R&gt; Function&lt;T, R&gt; cached(final Function&lt;T, R&gt; func, int maximalCacheSize) {
          Cache&lt;T, R&gt; cache = new Cache&lt;T,R&gt;(maximalCacheSize);
          return input -&gt; cache.computeIfAbsent(input, func);
      }
  
      public static &lt;T, R&gt; Function&lt;T, R&gt; cached(final Function&lt;T, R&gt; func) {
          Cache&lt;T, R&gt; cache = new Cache&lt;T,R&gt;(DEFAULT_CACHE_SIZE);
          return input -&gt; cache.computeIfAbsent(input, func);
      }
      
      public static &lt;T, U, R&gt; BiFunction&lt;T, U, R&gt; cached(BiFunction&lt;T, U, R&gt; bifunc, int maximalCacheSize) {
          Cache&lt;T, R&gt; cache = new Cache&lt;T, R&gt;(maximalCacheSize);
          
          return (t, u) -&gt; {
              Pair&lt;T,U&gt; pairKey = new Pair&lt;T,U&gt;(t,u);
              
              Function&lt;Pair&lt;T,U&gt;, R&gt; something = input -&gt; {
                  return bifunc.apply(input.get_first(), input.get_second());
              };
              
              if (!cache.containsKey(pairKey.get_first())) {
                  R result = something.apply(pairKey);
                  cache.put(pairKey.get_first(), result);
                  
                  return result;
              } else {
                  return cache.get(pairKey.get_first());
              }
          };
      }
      
      public static &lt;T, U, R&gt; BiFunction&lt;T, U, R&gt; cached(BiFunction&lt;T, U, R&gt; bifunc) {
          Cache&lt;T, R&gt; cache = new Cache&lt;T, R&gt;(DEFAULT_CACHE_SIZE);
          
          return (t, u) -&gt; {
              Pair&lt;T,U&gt; pairKey = new Pair&lt;T,U&gt;(t,u);
              
              Function&lt;Pair&lt;T,U&gt;, R&gt; something = input -&gt; {
                  return bifunc.apply(input.get_first(), input.get_second());
              };
              
              
              if (!cache.containsKey(pairKey.get_first())) {
                  R result = something.apply(pairKey);
                  cache.put(pairKey.get_first(), result);
                  
                  return result;
              } else {
                  return cache.get(pairKey.get_first());
              }
          };
      }
      
      public static &lt;T, R&gt; Function&lt;T, R&gt; cachedRecursive(final BiFunction&lt;T, Function&lt;T,R&gt;, R&gt; bifunc) {
          
      }
  }
  </code></pre>
  <p>This is my problem:</p>
  <pre><code>public static &lt;T, R&gt; Function&lt;T, R&gt; cachedRecursive(final BiFunction&lt;T, Function&lt;T,R&gt;, R&gt; bifunc) {
          
      }
  </code></pre>
  <p>I have absolutely no idea how to implement the cachedRecursive function, the previous functions are working with a simple fibonacci test perfectly, However the goal of this task is to implement the cachedRecursive function that takes a BiFunction with the first argument as the input and the second argument a function. Just to complete the code, this is the main class I used to test:</p>
  <pre><code>public class cachedFunction extends FunctionCache {
  
  
  public static void main(String[] args) {
          
          @SuppressWarnings({ &quot;rawtypes&quot;, &quot;unchecked&quot; })
          BiFunction&lt;BigInteger, BiFunction, BigInteger&gt; fibHelper = cached((n, f) -&gt; {
              if (n.compareTo(BigInteger.TWO) &lt;= 0) return BigInteger.ONE;
              
              return ((BigInteger) (f.apply(n.subtract(BigInteger.ONE), f)))
                      .add((BigInteger)f.apply(n.subtract(BigInteger.TWO), f));
          }, 50000);
          
          Function&lt;BigInteger, BigInteger&gt; fib = cached((n) -&gt; fibHelper.apply(n,fibHelper));
          
          System.out.println(fib.apply(BigInteger.valueOf(1000L)));
      }
  }
  </code></pre>