PHPのタグ付き共用体(Rustと同様)

前の記事私はPHP8.1に列挙型を追加することについて書きました。投票は成功したので、問題は解決したと見なすことができます。







ただし、その列挙型の実装は、グローバルプランの一部にすぎません今日は、次の項目であるタグ付き共用体について検討します。ロシア語では、「type-sum」と解釈されます。







まだ投票されていませんがPHP8.1にも含めること提案されています。







これらすべての用語「代数的データ型」、「合計型」は怖いように聞こえますが、実際にはすべてが非常に単純です。







なぜこれがすべて必要なのですか?







Rustのような結果



Rustで書いた場合は、おそらく組み込みの列挙型結果に出くわしたことでしょう。Rust、Goなどで。これらの言語は明示的なエラー処理の信頼性がはるかに高いと考えているため、例外メカニズムはありません。この言語では、イベントのすべてのバリアントを明示的に処理する必要があり、トップの誰かがそれについて知っていて、正しく処理する方法を知っていることを期待して例外をスローしません。(ここで非難しないでください。例外と戻り値の型のトピックについては、誰もが独自の意見を持っています)。Rustについて具体的に言えば、エラーを生成する可能性のある関数呼び出しの結果は、多くの場合、結果値になります。







結果は、OkとErrの2つのバリアント(PHP列挙型の用語の場合)で構成されます。以前の列挙型機能、または定数を使用してバリエーションを作成することもできますが、値自体を返す必要もあります。さらに、成功した場合、値は文字列にすることができ、エラーの場合、他のタイプにすることができます。たとえば、整数(HTTP応答ステータス)。







投票が成功した場合、PHPでどのように表示されるか:







enum Result {
    case Ok(public string $json);
    case Err(public int $httpStatus);
}

function requestApi($url): Result {
    //
}
      
      





これで、この回答を別の場所に転送でき、エラーとそのタイプに関する知識が失われることはありません。







前回の記事書いように、列挙型は本質的にクラスであり、メソッドなどを持つことができます。タイプサムの場合、メソッドは列挙型全体に対して一般的であるか、特定のケースに対して一般的である可能性があります。







これがMaybeモナドの実装例です(RFCの例):







多分モナド



(Rustでは、このタイプはオプションと呼ばれます)







enum Maybe {
  // This is a Unit Case.
  case None {
    public function bind(callable $f) 
    {
      return $this;
    }
  };

  // This is a Tagged Case.
  case Some(private mixed $value) {
    // Note that the return type can be the Enum itself, thus restricting the return
    // value to one of the enumerated types.
    public function bind(callable $f): Maybe
    {
      // $f is supposed to return a Maybe itself.
      return $f($this->value);
    }
  };

  // This method is available on both None and Some.
  public function value(): mixed {
    if ($this instanceof None) {
      throw new Exception();
    }
    return $this->val;
  }
}
      
      





, : Some None, Some , None — None. bind. value()







RFC ,







$a = Maybe::Some("blabla");
//  $a = Maybe::None
$a->bind();
      
      





, - Result Maybe , - . pattern matching, RFC, . , :







$result = requestApi($url);

if ($result is Result::Some {%$json}) {
    //  $json
}

if ($result is Result::Err {%$httpStatus}) {
    //  $httpStatus
}
      
      





, match.









, tagged unions. , - , , tokenizer (scanner), . : , enum. , , , . . :







enum Token {
   case Comma;
   case LeftBrace;
   case RightBrace;
   case StringLiteral(public string $str);
   case Identifier(public string $identifier);
   //  ..
}
      
      





?



, RFC , , . , "" . tagged unions, , pattern matching.







開発に関する同様の記事、特にマッチングパターンで次に何が起こるかに興味がある場合は、CrossJoinテレグラムチャネルに登録してください。








All Articles