1
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?

Markdownライクな構文のスクリプト言語「Turbine」のoutパラメータ

Posted at

Turbineのoutパラメータ

これまでの記事では、Turbineの基本的な文法や特徴的なEnumの仕組みについて紹介してきました。
今回は、CやC++のように複数の値を返したいときに使える、出力パラメータの仕組みについて紹介します。

なぜoutパラメータが必要なのか?

Turbineでは、関数の戻り値は1つだけです。
では、「結果」と「成功フラグ」を同時に返したいときはどうすればいいでしょうか?

たとえば、ゼロ除算を検知できるdivide()関数では、成功・失敗のフラグも返したくなります。そんなときに使えるのが outパラメータ です。

Pythonなどの多くのスクリプト言語では、関数が複数の値を返すことが容易です。

def divide(a, b):
    if b == 0:
        return 0, False
    return a / b, True

result, ok = divide(10, 2)

このように、複数の値をタプルで返すのは自然で便利です。
一方で、CやC++では戻り値がひとつしかないため、参照渡しやポインタを使って追加の結果を返すのが一般的です。

int divide(int a, int b, bool &ok)
{
    if (b == 0) {
        ok = false;
        return 0;
    }
    ok = true;
    return a / b;
}

TurbineはこのC/C++スタイルを継承しつつ、マークダウンライクな簡潔な文法で表現できるようにしています。

Turbineのoutパラメータの書き方

outパラメータは、引数名の前に &を付けて宣言します。

# divide(a int, b int, &ok bool) int
  if b == 0
    ok = false
    return 0
  ok = true
  return a / b

上の関数は、整数の割り算を行い、割り切れるかどうかをokで返します。
Turbineでは、関数の戻り値とoutパラメータを明確に区別しています。
呼び出し側は次のように書けます。

# main(args vec{string}) int
  - ok bool
  - res = divide(10, 2, &ok)
  if ok
    print("result =", res)
  else
    print("divide by zero")
  return 0

&ok によって、関数の中でokとして参照される変数が渡され、結果が書き戻されます。

outパラメータの設計方針

Turbineでoutパラメータを採用した理由は、単なるC言語的懐古ではなく、戻り値の意味を明確に分けるためです。
たとえば次のようなケースでは、戻り値そのものが主要な結果であり、エラー状態は「補助的な情報」として扱いたくなります。

// 数値でなければok = falseを返す
# parse_int(s string, &ok bool) int

もし戻り値を (int, bool)のような多値にしてしまうと、常にそれらを分解しなければならず、「主な結果」と「付随情報」の区別があいまいになります。Turbineでは、

  • 戻り値 → 関数の主目的となる値
  • outパラメータ → 状態・フラグ・追加結果

という明確な棲み分けを設計思想としています。

discardキーワードで出力を明示的に無視する

outパラメータを使いたくない場合、単に省略することはできません。
なぜなら、Turbineでは「outパラメータを指定しておきながら、呼び出し後に結果を使わない」ことをエラーとして検出するからです。

その代わりに、意図的に無視することを示す特別なキーワード discardが用意されています。

# main(args vec{string}) int
  - result int = parse_int("123", &discard)
  print(result)
  return 0

このように書くと、

  • 出力パラメータ用の変数宣言を省略できる
  • 呼び出し後の未使用エラーを回避できる
  • 「この出力は意図的に無視している」という意図がコード上で明示できる

という利点があります。discardは、関数の副結果を扱わない軽量スクリプトでは特に便利です。

outパラメータの制約

outパラメータにはいくつかのルールがあります。

  • &を付けられるのはプリミティブ型のみ (bool, int, float)
  • 参照型である文字列やコンテナ(vec, mapなど)、構造体をOutパラメータにすることはできません

関数呼び出し時は、必ず既存の変数、または &discardを指定する必要があります。参照型の変数はもともと参照渡しされるため、関数内で直接変更できます。

まとめ

Turbineのoutパラメータは、「主結果を戻り値で返し、副結果を参照で返す」 という明確な設計思想のもとにあります。

  • &を付けるだけで、関数から追加の結果を返せる
  • 呼び出し側も常に&を実引数につけて区別する
  • 戻り値との意味分離でコードが読みやすくなる
  • 未使用の出力実引数はエラーで教えてくれる
  • discardで意図的な無視を明示できる
  • プリミティブ型のみ対応でシンプルなメモリモデル

小さなスクリプトや補助的な関数で、戻り値以外にもう一つ情報を伝えたいとき、Turbineのoutパラメータはとても実用的な手段になるはずです。

リンク

現在は開発中で、仕様や文法を少しずつ固めています。
詳細や開発ログは以下で公開しています:

👉 GitHub
👉 ドキュメント(英語)

興味のある方へ

  • 新しい言語の設計に興味がある方
  • C/C++と相性の良い小さなスクリプト言語を探している方
  • Markdown風の軽量な構文に興味がある方

ぜひコメントやフィードバックをいただけると嬉しいです!
今後も開発進捗や実装例などを投稿していく予定です。

1
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
1
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?