なんとなく、ちょっと前に書いたHaxeのFizzBuzzコードを解説してみる。
「Haxeの機能を無駄に使いまくったFizzBuzz」を解説してみた。
まずはイテレータ
HaxeにはIteratorという型があります。
typedef Iterator<T> = {
function hasNext() : Bool;
function next() : T;
}
この型であればfor構文を使うことができます。
FizzBuzzでは、実装したFizzBuzzのイテレータ型を作ってfor構文を使っています。
for( fizzbuzz in new FizzBuzzIter(100) ){
fizzbuzzes.push( fizzbuzz.toString() );
}
Iteratorの実装
Iteratorを実装するには、単純に、 hasNext()メソッドとnext()メソッドを実装すれば良いだけ です。どっかの言語ではIteratorインターフェースを実装しないとイケナイですがその必要がないのです。
class FizzBuzzIter{
public function hasNext(){
...
}
public function next(){
...
}
}
enum
さて、FizzBuzzを実装するにあたって、FizzBuzzのenum型を実装しました。なぜなら、数値をFizzとBuzzを扱うので、それをまとめるためにenumを作りました。 enumがパラメータを持つことができる のはみなさんご存知でしょうからあえて説明する必要もないでしょう。
enum FizzBuzz{
Fizz;
Buzz;
FizzBuzz;
Number(i : Int);
}
if式
Haxeの ifは式 なので、 値を返します。なのでこのように書くことができます。
class FizzBuzzIter{
//....
public function next(){
var result = if( this.i % 15 == 0 ){
FizzBuzz;
}else if( this.i % 3 == 0 ){
Fizz;
}else if( this.i % 5 == 0 ){
Buzz;
}else{
Number(this.i);
}
// .....
}
}
using
さて、さっきつくったFizzBuzz型のインスタンスにtoStringメソッドをつくりましょう。どうするかって? usingに決ってるじゃないですかー!!!
class FizzBuzzUtil{
public static function toString(fizzbuzz : FizzBuzz){
return switch (fizzbuzz) {
case Fizz: "fizz";
case Buzz: "Buzz";
case FizzBuzz: "FizzBuzz";
case Number(i): Std.string(i);
}
}
}
するとusing FizzBuzzUtilすると....
using FizzBuzzUtil; // using!!
class Main{
public static function main(){
var fizzbuzzes = new Array<String>();
for( fizzbuzz in new FizzBuzzIter(100) ){
fizzbuzzes.push(
fizzbuzz.toString()
// ここでenum型のインスタンスにメソッドが付いている!!!
);
}
}
}
テンプレートシステム
Haxeには 標準でテンプレートシステム 標準で備わっています!!!
class Main{
public static function main(){
// ....
var templateText = "::foreach fizzbuzzes:: ::__current__:: ::end::";
var template = new haxe.Template(templateText);
var output = template.execute({ fizzbuzzes : fizzbuzzes });
trace(output);
}
}
型推論とか構造的部分型とか!!!
じつは既につかっている!!! みんなわかっているよね???
まとめ
Haxe素晴らしい!!!