0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

セミコロンレス Delphi

Posted at

これは 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

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

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

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?