Help us understand the problem. What is going on with this article?

セミコロンレス Delphi

More than 3 years have passed since last update.

これは Delphi Advent Calendar 補欠記事です。

セミコロンレスJava

結構前の話題みたいなんですけど、つい先日初めてセミコロンレス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

という型ですが、これは型可変オープン配列パラメータといいます。
簡単に言うとどんな型の引数でも受け付ける代わりに、使う側で型を決定しないといけないよっていうヤツです。

まとめ

ということで、こんな感じで書けますが、他にもっと面白い書き方があったら教えてください!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away