Using Paja

This manual describes how to get the most from Paja programming in a minimum amount of time.

Writing a parametric class

In Paja, genericity is provided through parametric classes.

Suppose you have to write a parameterized (generic) version of a Stack class. Below lies the Paja code of a straightforward implementation of such a class. The type of contained objects, Elem, is found right after the class name, enclosed in =< >= 'braces'. 

public class Stack=<Elem>= {
    private Elem[] v = new Elem[100]; // static vector containing the elements
    private int top=0; // top of stack

    public void push(Elem e) {
        v[top++] = e;
    }

    Elem pop() {
        return v[--top];
    }
}

Using a parametric class

In order to use specific instances of the parametric stack we have created, one has just to give the effectives parameters of the class (types!). Here is an example of such a use:

...

Stack=<String>= s;
s = new Stack=<String>=();

s.push("one");
s.push("two");

System.out.println(s.pop()); // prints two 
System.out.println(s.pop()); // prints one 

...

Bounded parameters

Often, one wants to establish a 'contract' between the author and the users of a parametric class, about its parameters.

This can be done by specifying a bound to those parameters. In the piece of code below, the elements of HashingSet are required to implement Hashable.

interface Hashable {
  long getHashValue();
}

class HashingSet=<Elem extends Hashable>= {
   ...

   put(Elem e) {

      long key=e.getHashValue();

       ...
   }

   ...
}
Knowing that Elem implements Hashable somehow, the compiler is able to valid the
call to getHashValue. It will also ensure that all parameters to HashingSet will
meet the Hashable requirement.

Please note that, as a bound, any class or interface can be used.
Also, even if Hashable is an interface, the keyword used to denote
the bound remains "extends". 

Advanced

The features introduced above should suffice for daily use of genericity.
However, Paja has a few neat features giving the full power of genericty 
to java users.

"incomplete" parametric types

Coming directly from the YAFL world, this feature allow to write most of the methods
working on a range of parametric type without parameterizing themselves.

As an example, imagine that you need a method that swaps the two elements on top of a stack.
You'll notice that there is absolutely no need to know their exact type to do that.

The clean way would be to include the method in the generic stack class. However, this might not
always be possible, so Paja proposes to "omit" the parameter, as shows the following example.

class Main {
  ... 

  void swap(Stack s) {
    s.Elem e1, e2;

    e1 = s.pop();
    e2 = s.pop();

    s.push(e1);
    s.push(e2);
  }
}
Please note the way we can reference the type of the elements of the stack s.

Another possible use of incomplete types is when you simply do not care about
parameters.

static methods of parameterized classes

When the above mechanism is not sufficient, something more pedantic is needed.

Imagine we need to swap the top elements of two stacks. Of course, it is 
required that the two stacks have the same element type.

This is written as such:

class Main {

  class Stacks=<Elem>= {
     static void swapTops(Stack=<Elem>= s1, Stack=<Elem>= s2) { 
        Elem e1, e2;

        e1 = s1.pop();
        e2 = s2.pop();

        s1.push(e1);
	s2.push(e2);
     }
  }

  ...

  void f() { 
    Stack=<String>= s1, s2; 
    Stacks=<String>=.swapTops(s1, s2);

    ...
  }
}

Note that, even if use of type parameters is allowed in static methods, it is NOT allowed
it static fields!

F-Bounded polymorphism

This is the natural extension of bounded parameters, where bounds can be functions of the
parameters.

A useful example follows.

interface Comparable=<T>= {
  bool isGreaterThan(T t);
}

class Vector=<T>= {
  ...
}

MyString implements Comparable=<MyString>= {
  ...
}

class OrderedVector=<T extends Comparable =<T>=>= // F-bound!
{

  void sort() {
     T t1,t2;

     ... 
       bool b = t1.isGreaterThan(t2); // ok, because T extends Comparable=<T>=
     ...
  }

}

class Main {
...

  OrderedVector=<MyString>= v; // ok, because MyString implements Comparable=<MyString>=

  ...
  v.sort();
  
...
}

Paja: Natural extensions to Java

Also this is conceptually not related to genericity, it is important to note that Paja does not impose any counter-intuitive restriciton. New types introduced in Paja can be used exactly as any other type. It's worth noticing the following three cases where we don't artifcially impose a restriction.
  1. multi-level parametric types. A parametric type can be used as an effective parameter type. For example, the type Stack=<Stack=<String>=>= is a valid type.
  2. "instanceof" operator. You can test an object to have any parameter or parametric type, and any combination of them.
  3. arrays. Array can be combined with parametric types as will.

Package paja.util

The distribution constains a paja.util package, which implements a parametric Collection library. That collection library is closely designed after java.util collections suite, so you should have no problem with it once you are familiar with the non-parametric library.

The thing you want to know is that the actual implemented classes and interfaces are

Please note that those classes are not serializable (yet).