Friday, December 28, 2007

Function Types

Function Types

Function types are used when we want to refer to closures. We can declare a variable of function type and assign to it a reference to a closure. A function type is written as follows: { formal parameters => return type }. Formal parameters are optional. The return type can be any type or void. For example, { int, String => void } means a function with two arguments (int and String) and return type void. Any function with a compatible list of argument types and compatible return type can be assigned to a variable of function type.

  public class DeepThought {
  
    // { => int } means a function with no arguments and return type int
    static { => int } answer = { => 42 };
 
    public static void main(String[] args) {
      int i = answer.invoke();
      System.out.println(i);
    }
 
  }
  

A function with one int argument and return type String:

  { int => String } toBinary = { int x => Integer.toBinaryString(x) };
  String binary11 = toBinary.invoke(11);  // will return 1011
  

A function with no arguments and return type void:

  { => void } sayHello = { => System.out.println("Hello"); };
  sayHello.invoke();  // will print "Hello"
  

Function types can be used as types of arguments:

  static void doTwice({ => void } block) {
    block.invoke();
    block.invoke();
  }
  
  public static void main(String[] args) {
    doTwice({ => System.out.println("deja vu"); });
  }
  

They can also serve as a return type:

  static { => boolean } makeCond() {
    return { => Math.random() < 0.8 };
  }
  
  public static void main(String[] args) {
    { => boolean } cond = makeCond();
    while (cond.invoke()) {
      System.out.println("trying...");
    }
  }
  

Exercises

  1. Write a method that invokes an action on each value of array of ints. The action is passed in a function variable.
  2. Write a method that returns a closure which checks if a value is from a given interval. Bounds of the interval are arguments of the method.
  3. Write a method that selects values from a list in accordance with a predicate passed in a function variable.

Solutions

  static void perform(int[] values, { int => void } action) {
    for (int n: values) {
      action.invoke(n);
    }
  }
  
  public static void main(String[] args) {
    int[] v = { 2, 3, 5, 7, 11 };
    perform(v, { int x => System.out.println(x); });
  }
  
  static { int => boolean } makeInterval(int a, int b) {
    return { int x => a <= x && x <= b };
  }
  
  public static void main(String[] args) {
    { int => boolean } interval = makeInterval(10, 20);
    System.out.println(interval.invoke(15));
  }
  
  static <T> List<T> select(List<T> values, { T => boolean } cond) {
    List<T> selected = new ArrayList<T>();
    for (T t: values) {
      if (cond.invoke(t)) { selected.add(t); }
    }
    return selected;
  }
  
  public static void main(String[] args) {
    List<String> cities =
      Arrays.asList("London", "New York", "Prague", "San Francisco");
    List<String> shortCities = 
      select(cities, { String s => s.length() <= 6 });
    System.out.println(shortCities);
  }
  

11 comments:

Anonymous said...

http://blog.dabarobjects.com/?p=26

Bhargav-------------------------------------------- said...

So essentially with function types you could simulate the behavior of a Function Pointer or Delegates(C#/VB).

/** Java Program to demonstrate delegates using closures! **/
class DelegateDemo
{
/** You must always specify return types! **/
static { => void } method1 = { => System.out.println("This is method 1"); };
static { => void } method2 = { => System.out.println("This is method 2"); };

/** A method which takes a delegate of type void xyz(); **/
static void invoker({=> void} anyMethod)
{
anyMethod.invoke();
}

public static void main(final String[] args) {
invoker(method1);
System.out.println("Now passing method2!!");
invoker(method2);
}
}

Hope I am right!

Bhargav
krishnabhargav.blogspot.com

Zdeněk Troníček said...

I am afraid you are not because there is no way how to assign a method reference to a variable of function type.

Christian Ullenboom said...

Function pointers are valid:

public class FunctionPointerWithClosures
{
static void invoker( { => void } block )
{
block.invoke();
}

public static void main( String[] args )
{
{ => void } method1 = { => System.out.println("Hello tutego"); };
{ => void } method2 = { => System.out.println("Hallo tutego"); };

invoker( Math.random() > 0.5 ? method1 : method2 );
}
}

Christian Ullenboom | http://www.tutego.com/

Konstantin Triger said...

...there is no way how to assign a method reference to a variable of function type.

That's right, but we are close and compiler can greatly help.
Suppose you have:

class Foo {
int test(short){}
}

Foo foo;

Now
{short => int} x = foo.test;

can be converted to:
{short => int} x = {short s => foo.test(s)};

and

{Foo,short => int} x = Foo.test;

can be converted to:
{Foo,short => int} x = {Foo f, short s => f.test(s)};

What do you think?

Zdeněk Troníček said...

There is a new compiler prototype (published today, 2008-03-17). It contains a support for function pointers. For example:

{ int => Integer } box = Integer#valueOf(int);
Integer i = box.invoke(3);

So, you were right. We were not very far :o).

Konstantin Triger said...

Thanks for an update!

Some functionality questions:
1. Does it handle instance methods? (Both cases: instance is specified and instance is not specified).
2. Is there any any restrictions regarding access modifiers? (There should not be, yet is it possible to call a private method?)
3. Suppose you support instance methods, do you correctly distinguish between myVirtualMethod() and super.myVirtualMethod()?

Kosta
Java Query library,
http://jaque.googlecode.com

Zdeněk Troníček said...

Good questions. Yes, there are restrictions caused by access modifiers. So, for example, you cannot call a private method. The next two questions I tried to answer in my new post "Method References".

Anonymous said...

What the interests of that ?
I don't understand.
Except make the code more ugly and obscur.
Why not do play with interface, and class properly ?
Something like :

--- File Invokable.java ---
public interface Invokable
{
public void invoke();
}

---- File Method1.java ----
public class Method1 implements Invokable
{
public void invoke()
{
System.out.println("method1");
}
}

---- File Method2.java ----
public class Method2 implements Invokable
{
public void invoke()
{
System.out.println("method2");
}
}

--- File Invoker.java ---
public class Invoker
{
public static void invoke(Invokable invokable)
{
invokable.invoke();
}
}

--- File Test.java ---
public class Test
{
public static void main(String[] args)
{
Method1 method1 = new Method1();
Method2 method2 = new Method2();

Invoker.invoke( Math.random() > 0.5 ? method1 : method2
}
}

---------------------------------

Like a good Java developer do.

Why build new syntax for a solution that already exists ?

I know my exemple is not the best, but it shows what is behind my head.

Toko Jual Obat Kuat Alat Bantu Sex 087733776655 said...

Klik Aja Di Bawah Ini
Pemesanan: 087733776655
http://obatkuat-57.com/
Jual Obat Pembesar Penis Vigrx Plus
Alat Bantu Sex Pria Dan Wanita
Rajanya Obat Kuat Sex
Obat Perangsang Wanita, Obat Gairah Wanita
Obat Pembesar Payudara Monyok, Payudara Kencang
Alat Pembesar Payudara Montok
Alat Pembesar Penis
Alat Sex Pria Boneka Moderen
Obat Pengental Sperma
Minyak Pembesar Penis, Obat Pemanjang Penis
Obat Hernia Paling Ampuh
Obat Pelangsing Badan, Melangsingkan Tubuh
Obat Perapet Vagina
Obat Peninggi Badan, Meninggikan Bada
Obat Pembesar Pantat, Pembesar Bokong
Obat Pemerah Bibir, Pemerah Puting
Obat Pemutih Wajah Alami Tensung Cream
Obat Penggemuk Badan
Obat Penghilang Tatto Permanen Herbal Alami
Kondom Antik Pria
Rajanya Obat Kuat Pria
Alat Bantu Sex Wanita Antik
Alat Bantu Sex Pria
Obat Kuat Herbal
Vimax Obat Pembesar Alat Vital
Cara Memutihkan Selangkangan dan Ketiak


Obat Pelangsing Badan Fatloss Jimpness Beauty
Selaput Dara Perawan Buatan


Radley Co Tad said...

Very much useful article. Kindly keep blogging

Java Training in Chennai

Java Online Training India