Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.

Thursday, January 19, 2012

Fizz 6 - This or That (Ceylon)

Ceylon is a new JVM language being created by Red Hat and Gavin King.  You may recognize that last name. Gavin also created Hibernate, a data library that underlies many e-commerce sites and is integrated (at the default option) into Grails.  Ceylon puts a lot of emphasis into how it handles types, so it seemed like a natural language feature to abuse.

interface Fizz {}
interface Buzz {}

class CFizz() satisfies Fizz {
  shared actual String string = "Fizz";
}

class CBuzz() satisfies Buzz {
  shared actual String string = "Buzz";
}

class CFizzBuzz() satisfies Fizz & Buzz {
  shared actual String string = "FizzBuzz";
}

Fizz|Buzz|Natural fizzIt(Natural i) {
  if ((i % 3 == 0) && (i % 5 == 0)) {
    return CFizzBuzz();
  } else if (i % 5 == 0) {
    return CBuzz();
  } else if (i % 3 == 0) {
    return CFizz();
  } else {
    return i;
  }
}

shared void FizzBuzz06() {
  for (i in 1..100) {
    print(fizzIt(i).string);
  }
}

The particular typing feature I am using is called "Union Types."  When you declare a type as TypeA|TypeB (note the pipe between the two types) you are telling the Ceylon compiler that you will have either TypeA or TypeB, it doesn't matter.  And you won't have TypeC (for this example TypeC is not a TypeA or TypeB).  Without this construct I would be forced to declare the return type of fizzIt to be an Object and hope no stray classes like Klang shows up.

There also exists Intersection Types (TypeA&TypeB) which means that the type is both of TypeA and TypeB without having to create some other interface that joins the two. Instead of createing a new interface RunnableFuture<V> you would just have Runnable&Future<V> without the need for a third class. Throw in stuff like RunnableScheduledFuture<V> which could have been declared as Runnable&Delayed&Future<V> and the code savings start piling up.

No comments:

Post a Comment