Sunday, January 22, 2012

Functional Java?

Привет всем.

Писал раньше, по моему, но тут начал учить Scala. Все понравилось, супер, но для Android я проигрываю в скорости сборки проекта, это очень важно когда тестируешь UI. Как то не склеилось у меня со Scala под Android, может в будущем. Но после возвращения в Java, как то захотелось функциональной состовляющей, поэтому набросал парочку классов для помощи с этим делом. Примеры:
package com.fjava;

public interface F {

 A invoke();
}
package com.fjava;

public interface F1 {

 A invoke(B b);
}
package com.fjava;

public class Lazy {

 private T value;
 private F f;

 public Lazy(F f) {
  this.f = f;
 }

 public T invoke() {
  if (value == null) {
   value = f.invoke();
   f = null;
  }
  return value;
 }
}
При использовании этих классов можно выполнять действия как в чисто функциональном языке, т.е. 2 типа closures и один lazy инициализация. Код будет выглядить как то так:
package com.fjava.test;

import com.fjava.*;

public class Test {
 static class A {
  public final String value;

  public A(F1 f) {
   value = f.invoke(4);
  }

  public A(F f) {
   value = f.invoke();
  }
 }

 public static void main(String[] args) {
  Lazy s = new Lazy(new F() {
   @Override
   public String invoke() {
    return "Lazy String value.";
   }
  });
  System.out.println(s.invoke());
  F f = new F() {
   @Override
   public Void invoke() {
    System.out.println("Closure without arguments.");
    return null;
   }
  };
  f.invoke();
  F1 fi2 = new F1() {
   @Override
   public Integer invoke(final Integer i) {
    return i * 2;
   }
  };
  System.out.println("Closure with Integer: 3 * 2 = " + fi2.invoke(3));
  System.out.println("Apply closure: " + new A(new F1() {
   @Override
   public String invoke(final Integer value) {
    return String.valueOf(value + 6);
   }
  }).value);
  System.out.println("Apply closure 2: " + new A(new F() {
   @Override
   public String invoke() {
    return "2";
   }
  }).value);
 }
}
Как то не круто смотриться, не так ли? И тут пришла ко мне идея, в идеале, сделать плагин для Eclipse с подстветкой синтаксиса и встроить транслятор в очередь сборки перед Java компилятором. Теперь как это (уже работает) и смотрится, обозвал просто FJava (functional java), файлы с расширением .fjava. И теперь, как выше программу можно "сжать":
package com.fjava.test;

public class Test {

 static class A {
  
  public final String value;

  public A((String, Integer) => f) {
   value = f.invoke(4);
  }

  public A((String) => f) {
   value = f.invoke();
  }
 }

 public static void main(String[] args) {
  lazy String s = "Lazy String value.";
  System.out.println(s.invoke());

  f = (Void) => {
   System.out.println("Closure without arguments.");
  };
  f.invoke();

  fi2 = (Integer, Integer i) => {
   return i * 2;
  };
  System.out.println("Closure with Integer: 3 * 2 = " + fi2.invoke(3));
 
  System.out.println("Apply closure: " + new A((String, Integer value) => {
   return String.valueOf(value + 6);
  }).value);

  System.out.println("Apply closure 2: " + new A((String) => {
   return "2";
  }).value);
 }
}
По моему крутатенюшка выходит то! Буду стараться, а главное всен нативно будет, не нужно никаких библиотек, в принципе. Хотя если расширяться и добавлять foreach/fold/reduce/map и другие фичи для List/Array, то ну будет + 2 класса еще к проекту.

1 comment:

  1. Жаль, не хотит парсер нормально показывать код :) ну так думаю догадаетесь что и куда. Потом сделаю нормально.

    ReplyDelete