これは Delphi Advent Calendar 補欠記事です。
#セミコロンレスJava
結構前の話題みたいなんですけど、つい先日初めてセミコロンレスJavaというのを拝見しました。
2015年にはセミコロンレスJavaのアドベントカレンダーなんてものもあったみたいです。
セミコロンレスJava Advent Calendar 2015
これに感化されて ObjectPascal でもセミコロンレスを試してみました。
#セミコロンレスObjectPascal
{$WARNINGS OFF}
begin
(procedure(F: array of const)begin end)([
// 定番のやつ
(function(const Count: Integer): Integer
begin
for Result := 0 to Count - 1 do
Writeln('Good-bye, semicolon world !')
end
)(3),
// FizzBuzz
(function: Byte
begin
for Result := 1 to 100 do
(procedure(S: array of Variant)
begin
Writeln(S[Ord(S[0] mod 3 = 0) or (Ord(S[0] mod 5 = 0) shl 1)])
end)
([Result, 'Fizz', 'Buzz', 'FizzBuzz'])
end
)(),
// Enter 押されるまで待つ
(function: Byte
begin
Readln
end
)()
])
end.
#解説
##必要の無いセミコロン
そもそも Pascal は end の前には ; は要りません。
なのでコレを書かないことにします。
##セミコロンの要らない関数・手続きの宣言
一部で話題の
(procedure begin end)()
(function: RETURN_TYPE begin end)()
を使います。
この書き方は 文中にいきなり無名関数を定義して呼び出す構文(?)です。
##セミコロンの要らない連続した呼び出し
上記で宣言した関数・手続きを呼び出す方法ですが、普通に書くと
(procedure begin Writeln('Foo') end)();
(procedure begin Writeln('Bar') end)()
となってしまい、セミコロンが付いてしまいます。
そこで、コレを全部 function にして、この戻り値を受け取る手続きの引数にしてやります。
例えば
(procedure(F: array of const) begin end)([Func1, Func2, Func3...]);
と書くと Func1 が実行されたあと、Func2 が実行され、さらに後続の関数が呼ばれるという仕組みです。
より具体的には
(procedure(F: array of const) begin end)([
(function: Integer
begin
// 何か処理
end)(),
(function: String
begin
// 何か処理
end)(),
(function: Integer
begin
// 何か処理
end)()
]);
と、無名関数を連続で書くことで、順序通りの処理を実現しています。
これを使えば全ての処理は一行ごとに無名関数化すれば良いので大体どんな処理も書けると思います。
for 文なんかも↓こんな感じで書けます。
※for 文のループ変数はローカル変数でなければならないので変数定義をしたいところですが変数定義をしてしまうとセミコロンがついてしまうので、戻り値 Result をループ変数にしています。
// FizzBuzz
(function(const Count: Integer): Integer
begin
for Result := 0 to Count - 1 do
Writeln('Good-bye, semicolon world !')
end
)(3), // 3回ループ
また、ここで使われている
F: array of const
という型ですが、これは型可変オープン配列パラメータといいます。
簡単に言うとどんな型の引数でも受け付ける代わりに、使う側で型を決定しないといけないよっていうヤツです。
#まとめ
ということで、こんな感じで書けますが、他にもっと面白い書き方があったら教えてください!