Table of Contents

Introduction to Programming Paradigms

In how many different ways can we reverse a sequence of integers?

We start the lecture by looking at three different Java programs which reverse a sequence of integers.

The Cook-book style:

public class Rev {
	public static void main (String[] args) {
		Integer[] v = new Integer[] {1,2,3,4,5,6,7,8,9};
		int i=0;
		while (i < v.length/2){
			int t = v[i];
			v[i] = v[v.length-1-i];
			v[v.length-1-i] = t;
			i++;
		} 
		show(v);
	}
}

Features:

Possible usages:

The Undergrad-math-teacher-style style (short Undergrad style):

interface List {
	public Integer head ();
	public List tail ();
}
 
class Cons implements List {
	Integer val;
	List next;
	public Cons (Integer val, List next){
		this.val = val;
		this.next = next;
	}
	@Override
	public Integer head() {return val;}
	@Override
	public List tail() {return next;}
}
 
class Empty implements List {
	@Override
	public Integer head() {return -1;}
	@Override
	public List tail() {return null;}
}
 
public class V2 {
 
	private static List rev (List x, List y){
		if (x instanceof Empty)
			return y;
		return rev(x.tail(), new Cons(x.head(),y));
	}
 
	public static List reverse (List l){
		return rev(l,new Empty());
	}
 
	public static void main (String[] args){
		List v = new Cons(1, new Cons(2, new Cons(3, new Empty())));
		List r = reverse(v);
	}
 
}

Features:

Possible usages:

The Industry style:

import java.util.Iterator;
 
class RevView<T> implements Iterable<T> {
	private T[] array;
 
	public RevView(T[] array){
		this.array = array;
	}
 
	@Override
	public Iterator<T> iterator() {
		return new Iterator<T>(){
			private int crtIndex = array.length - 1;
 
			@Override
			public boolean hasNext(){
				return crtIndex >= 0;
			}
 
			@Override
			public T next(){
				return array[crtIndex--];
			} 
 
			@Override
			public void remove () {}
		};
	}
}
 
public class OORev {
 
	public static void main (String[] args) {
		String[] s = new String[]{"1", "2", "3", "4", "5", "6"};
 
		Iterator<String> r = (new RevView<String>(s)).iterator();
		while (r.hasNext()){
			System.out.println(r.next());
		}
	}
}

Features:

Possible usages:

The Uni-math-teacher style (short. Uni style):

interface Op <A,B> {
	public B call (A a, B b);
}
 
interface Foldable <A,B> {
	public B fold (Op<A,B> op, B init);
}
 
class List implements Foldable<Integer,List>{
 
	Integer val;
	List next;
	public List (Integer val, List next){
		this.val = val;
		this.next = next;
	}
 
	public List fold (Op<Integer,List> op, List init){
		if (this.next == null)
			return op.call(this.val,init);
		return this.next.fold(op,op.call(this.val, init));
	}
}
 
public class V4 {
 
	public static void main (String[] args){
 
		List v = new List(1, new List(2, new List(3, null)));
		List r = v.fold(new Op<Integer,List>(){
				@Override
				public List call (Integer i, List l){
					return new List(i,l);
				}
		},null);
	}
}

Features:

fold({1,2,3},+,0) =
 fold({2,3},+,1+0) =
   fold({3},+,2+1+0) =
    fold({},+,3+2+1+0) =
     3+2+1+0

Possible usages:

Why so many reversals?

Note that reversal is an algorithmically trivial task: take the sequence of elements of the collection at hand, be it array of list (or anything else), in their reverse order.

Our point is that, apart from mastering algorithms, a skilled programmer needs solid knowledge on programming concepts and on the way programming languages (and the hardware they employ) are designed. In some cases, these concepts may be subtle (e.g. programming with Monads in Haskell) and may supersede the algorithm at hand in complexity. However, they are crucial in developing a efficient, secure and correct applications.

This lecture will focus on different ways of writing code for specific algorithms, in different programming languages, with an emphasis on Functional Languages (Haskell) and Logic-based Languages (Prolog).

We have clear metrics for choosing algorithms. Do we also have metrics for code writing? For instance:

is a plausible list. While some of these criteria overlap and are difficult to assess objectively, programmers more often than not agree that some programs are well-written while others are poor (w.r.t. some criteria).

How many other ways?

There are many possible variations (and combinations) to our examples, but a few elements do stand out:

Such elements of style are may be called design patterns, i.e. generic ways of writing code, which can be deployed for different implementations.

Some elements of style may have some common ground, or require certain traits from the programming language. These latter are called programming paradigms. For instance, writing programs as recursive functions, using higher-order functions and representing data as ADTs (recall that constructors are functions) are both styles of the functional paradigm.

In this lecture, we shall go over the following paradigms:

Other questions