P++: 銀河に平和をもたらすための奇策と決着

> PHP 8から、PHPは「PHP」と「P++」という2つの言語を提供するようになる

というキャッチーな紹介をする[P++: 静的型付けをめざすPHP](https://ezoeryou.github.io/blog/article/2019-08-13-p++.html)という記事がそれなりに話題になり、このニュースは目覚しく革新的な内容で、多くのひとの目を引き付けました。

これは**早まった理解**であり、ほとんど誤報と言ってもいい内容でした。2019年8月15日には提案者本人も、少くとも「P++」の計画を短期的に実現するととは非現実的であり時期尚早であることを認めています。

この記事では、PHP開発の現状、なぜ野心的なP++計画が提案され、事実上撤回されたかの経緯について紹介します。

> **[中立性のための表示]** この記事の著者@tadsanはPHPの静的解析を強く推進する立場です。
>
>  * [PHPゆるふわCI入門](https://www.pixiv.net/fanbox/creator/105589/post/333143)
>  * [PHP型検査･夢と理想と現実](https://www.pixiv.net/fanbox/creator/105589/post/445689))

## 三行で要約

 * PHPはバージョンを経るごとに「歴史的経緯」による負債が削ぎ落されてきた
 * PHPは[RFC](https://wiki.php.net/rfc)と呼ばれる提案とPHP開発者たちによる投票を経て意思決定される
 * いわゆる「P++(**仮称**)」について、2019年8月現在で**決まった事実は何もない**

本題に入る前に本件に関連する重要人物にも軽く触れておきます。

* [Zeev Suraski](https://ja.wikipedia.org/wiki/%E3%82%BC%E3%83%BC%E3%83%96%E3%83%BB%E3%82%B9%E3%83%A9%E3%82%B9%E3%82%AD%E3%83%BC)
    * 1997年にAndi GutmansとともにPHP 3を開発した
    * 2000年にPHP 4で[仮想機械](https://ja.wikipedia.org/wiki/%E4%BB%AE%E6%83%B3%E6%A9%9F%E6%A2%B0)方式のインタプリタ**Zend Engine**を導入する
    * [Zend Technologies](https://ja.wikipedia.org/wiki/%E3%82%BC%E3%83%B3%E3%83%89%E3%83%BB%E3%83%86%E3%82%AF%E3%83%8E%E3%83%AD%E3%82%B8%E3%83%BC%E3%82%BA)の社名や製品名に含まれる**Zend**はZeevとAndiの合成語
    * 今回の**P++**の発案者
* [Nikita Popov](https://nikic.github.io/aboutMe.html)
    * PHP 5.5(2012年)以降、PHPに非常に数多くの提案と実装を行ってきた
    * PHP 7.0では構文解析処理を書き直しASTを導入するなどの立役者
    * PHPの処理系を改善すると同時に、多くのレガシーな仕様の廃止を提案してきた

今回の登場人物を含め、現在のPHP開発においては、**誰もPHPについての意思決定権を持っていない**ことに注意してください。

Ruby作者のまつもとゆきひろ氏などは[優しい終身の独裁者](https://ja.wikipedia.org/wiki/%E5%84%AA%E3%81%97%E3%81%84%E7%B5%82%E8%BA%AB%E3%81%AE%E7%8B%AC%E8%A3%81%E8%80%85)とも呼ばれ、Ruby開発における意思決定役を担っていますが、PHPの意思決定プロセスは多数決による投票制です。それはPHPの最初の開発者である[Rasmus Lerdorf](https://ja.wikipedia.org/wiki/%E3%83%A9%E3%82%B9%E3%83%9E%E3%82%B9%E3%83%BB%E3%83%A9%E3%83%BC%E3%83%89%E3%83%95)も同様で、PHP開発メンバーの一員として1票の投票権しかありません。

## PHP 7から現在までのおさらい

これからの話の前にPHP 5系から現在までのPHPの変遷について復習します。PHP 7.0がリリースされたのは2015年12月であり、今からおよそ3年半前のことです。

はじめにPHP7以降の変更点から、主に文法の改善に着目して抜萃します。

 * [PHP: PHP 7.0 下位互換性のない変更点 - Manual](https://www.php.net/manual/ja/migration70.incompatible.php)
    * エラーや例外の取り扱いの変更
    * 変数やプロパティ、メソッドへの間接的なアクセスの扱い(結合)の変更
    * `list()` の取り扱いの変更
    * 参照による代入で自動的に作成した配列要素の並び順の変更
    * 同じ名前の引数をひとつの関数に複数定義できないようになった
    * 変数参照(`&`)をとる関数の引数を括弧で囲んだときの振る舞いの変更
    * 文字列の取り扱いの変更
        * 16進数値形式の文字列は数値とはみなさない
    * `foreach` の振る舞いの変更
    * 新しいオブジェクトを参照渡しで代入できないようになった
    * ASP タグと script タグの廃止
        * ASPタグ `<% … %>` `<%= … %>`
        * scriptタグ `<script language="php">…</script>`
        * PHP 5では上記形式でも*設定によって* `<?php … ?>` と同様に利用可能
    * `switch` 文に複数の `default` ブロックを書けない
 * [PHP: PHP 7.0.x で推奨されなくなる機能 - Manual](https://www.php.net/manual/ja/migration70.deprecated.php)
    * PHP 4 形式のコンストラクタ
    * 非 static メソッドに対する static 呼び出し
 * [PHP: PHP 7.0 その他の変更 - Manual](https://www.php.net/manual/ja/migration70.other-changes.php)
    * 予約語の制約の緩和 (予約語をメソッド名として利用可能になった)
 * [PHP: PHP 7.1 下位互換性のない変更点 - Manual](https://www.php.net/manual/ja/migration71.incompatible.php)
    * 関数に渡す引数が少ない場合の挙動
    * 変数スコープを調べる関数の動的呼び出しの禁止
    * ASCII 制御文字 delete `0x7F ` は識別子として使えない
 * [PHP: PHP 7.2 下位互換性のない変更点 - Manual](https://www.php.net/manual/ja/migration72.incompatible.php)
    * `countable` ではない型をカウントしたときに警告するように
 * [PHP: PHP 7.2.x で推奨されなくなる機能 - Manual](https://www.php.net/manual/ja/migration72.deprecated.php)
    * クオートしない文字列
    * `(unset)` キャスト
 * [PHP: PHP 7.3.x で推奨されなくなる機能 - Manual](https://www.php.net/manual/ja/migration73.deprecated.php)
    * 大文字と小文字を区別しない定数
 * [PHP: PHP 7.3 下位互換性のない変更点 - Manual](https://www.php.net/manual/ja/migration73.incompatible.php)
    * `switch`内のターゲット指定がない`continue`を警告するように

具体的な説明についてはリンクしたPHPマニュアルの記事を参照してください。

これらの項目のうちには、「複数の記法を一種類に統一した」もののほか、「なぜPHP 5ではこんな不可解な仕様があったのか」と首をかしげるものも含まれます。この要因としてはPHP 7.0で構文解析プロセスの改善(パーサの書き直し、抽象構文木の導入)に伴って、PHP 5時代にあった不合理な文法的制約が大きく取り払われたこと、が大きいです。

次に、PHP 7.0以降で追加された言語機能について主に型・クラス関連に絞って抜萃して紹介します。

 * [PHP: PHP 7.0 新機能 - Manual](https://www.php.net/manual/ja/migration70.new-features.php)
    * `declare(strict_types=1)`で厳格モードの型宣言
        * ファイル単位での設定
    * スカラー型宣言
        * PHP 5では「型ヒント」あるいは「タイプヒンティング」と呼ばれ、`array`, `callable`とクラス名・インターフェイス名など一部キーワードのみ記述可能で、`string`, `int`, `bool`, `float`などの[スカラー型](https://www.php.net/manual/ja/language.types.intro.php)は書くことができなかった
        * `declare(strict_types=1)` に設定していないとき独自のルールでキャスト
    * 戻り値の型宣言
    * 無名クラス `new class {...}` 式
 * [PHP: PHP 7.1新機能 - Manual](https://www.php.net/manual/ja/migration71.new-features.php)
    * nullableな型 `?`
    * 戻り値を返さない関数の特殊な型宣言 `: void`
    * `iterable` 擬似型
    * 複数の例外クラスの `catch`
 * [PHP: PHP 7.2新機能 - Manual](https://www.php.net/manual/ja/migration72.new-features.php)
    * `object` 型宣言
    * パラメータの型の拡大変換
        * インターフェイスの実装やメソッドのオーバーライド時に引数の型指定を省略可能に
 * [PHP: PHP 7.3新機能 - Manual](https://www.php.net/manual/ja/migration73.new-features.php)
    * (型に関連する目立った機能追加はなし)

これらの機能の改廃や追加は[Request for Comments(RFC)](https://wiki.php.net/rfc)という提案と、[php.internalsメーリングリスト](https://news-web.php.net/php.internals)による議論、[PHP開発者らによる投票](https://wiki.php.net/rfc/voting)という手続きを経て導入されています。RFCにはそれぞれの提案の背景や経緯、モチベーション、目的、想定される影響などが明記されています。

まだマニュアルに含まれていませんが、[PHP 7.4ではさらに数多くの提案が実装されて居り](https://wiki.php.net/rfc#php_74)、実装済みのRFCも列挙します。

 * [PHP: rfc:covariant-returns-and-contravariant-parameters](https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters)
    * [共変性と反変性 (計算機科学) - Wikipedia](https://ja.wikipedia.org/wiki/%E5%85%B1%E5%A4%89%E6%80%A7%E3%81%A8%E5%8F%8D%E5%A4%89%E6%80%A7_(%E8%A8%88%E7%AE%97%E6%A9%9F%E7%A7%91%E5%AD%A6))
    * 戻り値の型宣言が共変に、引数の型宣言が反変にできるようになった
 * [PHP: rfc:null_coalesce_equal_operator](https://wiki.php.net/rfc/null_coalesce_equal_operator)
    * `??=` null合体代入演算子が追加された
 * [PHP: rfc:typed_properties_v2](https://wiki.php.net/rfc/typed_properties_v2)
    * プロパティに型宣言が書けるようになった

全体的に見て、PHPは過去の歴史的事情による非合理な仕様が取り除かれ、ほかのプログラミング言語にあるような言語機能が次々と取り入れられつつある過程にあると説明できます。このような機能追加の過程において非常に大きな役割を果たしてきたのがNikitaです。彼は2012年に[ジェネレータ(コルーチン)の導入](https://wiki.php.net/rfc/generators)をはじめ、現在に至るまでPHPに多くの提案をしてきました。

Nikitaは継続して多くの機能追加を提案してきただけでなく、毎年のバージョンアップの度にレガシーな機能の廃止提案も欠かさず行ってきました。今回の件の発端は現在投票期間中の提案[PHP RFC: Deprecate short open tags, again](https://wiki.php.net/rfc/deprecate_php_short_tags_v2)です。

## 銀河に平和をもたらしたい

2019年8月8日にZeevが[Bringing Peace to the Galaxy](https://externals.io/message/106453)という件名のメールをphp.internalsメーリングリストに投稿しました。


> [... and not in the Sith Lord kind of way.] 

件名と繋げると、<q>銀河に平和をもたらす。 ……<a href="https://ja.wikipedia.org/wiki/%E3%82%B7%E3%82%B9_(%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%BB%E3%82%A6%E3%82%A9%E3%83%BC%E3%82%BA)">シス卿</a>のような方法ではなく。</q> から始まる長文のメールです。冒頭部をざっくり訳すと以下のような内容です。

> internals@(メーリングリスト)の最近の(それとあまり最近ではない)議論と最近の提案のいくつか、そして言語の方向性についてのいくつかの声明の見てください。明らかに私たちは両極化が高まっています。
>
> Peterが昨日言ったように、一部のひとたちはいくつかのレガシーなものを取り除きたいのです。私が思うに実際にはその範疇を超えてしまっており、internals@の多くは、PHPの各部はひどく修理が必要で(私も一部同意しますが)、ほかの競合する言語にある機能が「彼らの意見では」非常に欠けているとのことです。
>
> 両極化した一方の端には、私たちが常に抱いていた、後方互換性についての強い偏見を維持すべきであり、PHPは緊急のオーバーホールを要しているわけではなく、機能に関して「少ないことは豊かなこと(less is more)、私たちはほかの言語から競って機能をコピーすることはせず、むしろPHPをシンプルに保つことを選択する」と考える人々が居ます。
>
> これらの視点はほとんど正反対です。そのため、internals@の議論は片方が勝って相手が負ける[ゼロサムゲーム](https://ja.wikipedia.org/wiki/%E3%82%BC%E3%83%AD%E5%92%8C)と化してしまいました。
>
> 私は前者よりも後者の陣営での見方がずっと近いと言ってよいでしょう。それと同時に、前者の視点にも優位性があることも理解しています。私の陣営が「勝った」として、どちらかが勝てばどちらかが負ける議論による否定的な雰囲気や、そのほかのグループの(私がとても尊敬している)人々が感じる失望感は間違いなくプロジェクトにとって悪いことなので、私はしばしば[ピュロスの勝利](https://ja.wikipedia.org/wiki/%E3%83%94%E3%83%A5%E3%83%AD%E3%82%B9%E3%81%AE%E5%8B%9D%E5%88%A9)(犠牲に見合わない勝利)のように感じます。(立場が逆になったときに、同じように感じてくれると願っています)
>
> では、両方の陣営を本当に幸せにする方法があったらどうでしょうか。私はあると思います。

この記事ではこれまで7.0以降のPHPが積極的に後方互換性を切り捨てて新しい機能を取り込んできたことを紹介しました。しかしそれはPHPコミュニティの総意だということはなく、あまり好ましく思わない人々も少なからず居るということです。

話題に挙がった**P++**は、Zeevがそれを解決すべく提案したアイディアです。ここではC言語とC++、(旧来の)JavaScriptとES6のような関係を引き合いに出し、保守的な言語としてのPHPと、革新的な機能を取り込むため言語(**仮称:P++**)を分けよう、PHPの悪評を覆すために言語名は分けようというのです。

このメールの結びでは、このアイディアはコーナーケースについてまだ熟慮していない、生のアイディアであることを認めていますが、Zeevは技術的にも実現可能性は高いと見ており、ブレインストーミングを促したいというのがこのメールの趣旨です。

この議論の直接の契機となったのは、[PHP RFC: Deprecate short open tags, again](https://wiki.php.net/rfc/deprecate_php_short_tags_v2)についての議論でしょう。この提案は`<?php … ?>`の代りに単に `<? … ?>` と書ける機能を廃止しようとする提案です。短いタグ(`<? … ?>`)は`php.ini`で無効化することができるため、すくなくとも現代のPHPのライブラリとして一般公開されるようなコードでは `<?php` または `<?= … ?>` の二種類のタグのどちらかだけを使うことが暗黙の了解となっています。

しかしながら議論は上記で引用したメールで要約されたように、[[RFC] [VOTE] Deprecate PHP's short open tags, again - Externals](https://externals.io/message/106384)のスレッドでは、いささか痛々しい応酬を呈しています。Zeevは廃止提案に対して[Counterargument to Deprecate Short Tags RFC V2](https://wiki.php.net/rfc/counterargument/deprecate_php_short_tags)として反論をまとめています。要は「**壊れてないものを直すな**」「**あってもなくても誰も困らない仕様を消すために時間を浪費するな(させるな)**」という主張です。

## つまりP++はどういう状況なの？

P++は現在、元スレッドの[Bringing Peace to the Galaxy - Externals](https://externals.io/message/106453)と次のスレッド[P++: FAQ - Externals](https://externals.io/message/106503)で議論されています。

今回の渦中にある文章[PHP: P++ idea: FAQ](https://wiki.php.net/pplusplus/faq)は単なるメーリングリストの議論のための「よくある質問」をまとめたメモ書きをwiki.php.netに置いたに過ぎず、**「PHP 8の方針について決定事項の告知」という性格のものではありません。** PHP 8.0で導入される実装済みの機能は https://wiki.php.net/rfc#php_80 を参照してください。

FAQの内容については[型付きPHP、P++のFAQ](https://qiita.com/rana_kualu/items/c1b5397f9232d4c38f91)を参考にしてください。

さて、Nikitaはこのアイディアについて基本的に反対ですが、実現可能性に関しては、これまで数々の機能をPHPに取り入れてきたNikitaでさえ、次のような見解を示しています。

> I think this part is unrealistic from a simple manpower perspective. We have something like ~2 full time developers working on PHP. Even if you can rally some additional interest around this idea, I don't think we have the resources to create a substantially different language in any reasonable amount of time. Doing feature additions and changes to PHP is Hard. Even simple changes require a fair bit of design and engineering effort to integrate with the large complexity of the existing language. This would not change for a hypothetical P++, because we still need to interoperate with PHP.
>
> Even if I agreed with the idea (which I'm pretty skeptical about in this
particular form), I really don't think we have the resources to do
something like this.
>
> https://externals.io/message/106453#106472

要約すると <q>単純に人材が居ないから無理。フルタイム開発者が興味を持って取り組んだとしても妥当な時間で実質的に新しい言語を完成させるのは無茶。PHPとP++を分けたところで相互運用しなきゃいけないんだし設計めっちゃ大変。私がこのアイディアに賛成したとしてもリソースがないから懐疑的</q>と言ってますね。

現状まだRFCとして提案されておらず、「P++」の仕様はおろか実現可能性も含めて具体的な検討前の段階です。

## 「本の虫」の記事について

> P++: 静的型付けをめざすPHP

PHPで静的型付けをしやすくする機能強化を推進する潮流があるのは事実で、そのような仕様強化はPHPではなくP++に行おうという提案である。ただし提案者のZeevはPHPの意思決定の代表者ではない。

> PHP 8から、PHPは「PHP」と「P++」という2つの言語を提供するようになる。

P++はコミュニティの分断と対立を憂慮したZeevが解決のためにしたアイディア*(もはや奇策)*であり、メーリングリスト上でのブレインストーミングの対象とはなっているが、実装方針・実現可能性・リリース時期について何の意思決定がされたわけでもない。

また、FAQにおいては「PHP 8/9?」程度の言及であり、2020年12月にリリース見込みであるPHP 8.0にP++が導入されることをZeevが主張しているという事実もない。

> PHPとP++は同じコードベースであり、ほとんどのコードは共有するので、PHPの開発リソースが2倍必要になることはない。

これは非常に楽観的な見解で、現状P++の仕様、特に型の設計について具体的なものは何も示されていないので、なんとも測りがたい要素です。型についてPHPの標準関数の挙動にまで及ぶ厳密な型システムを導入した場合、PHPとの相互運用のための開発リソースが2倍以上必要になるであろう事態も想像に堅くない。

## ありそうな質問


 * **Q**: なんでこのひと[銀河](https://ja.wikipedia.org/wiki/%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%BB%E3%82%A6%E3%82%A9%E3%83%BC%E3%82%BA%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA)の平和の話をしてるの？
 * **A**: さあ…

-----------

私からは以上です。P++が本当に導入されるかどうかはどうでもいいですが、php.internalsに平和が訪れるといいですね。

## 追記 (8月15日)

日本時間で8月15日になって、[Xdebug](https://xdebug.org/)開発者でPHP 7.4リリースマネージャでもある[Derick Rethans](https://derickrethans.nl/)がRFCで「P++の実現可能性についての世論調査」という名目で投票を開始しました。これはPHPの開発方針として具体的な仕様を取り入れること決めるものではなく、それぞれのZeevが提案するP++プロジェクトに投票者(開発者)個人が時間とエネルギーを費す意向があるかということを調査するものです。

 * [Vote: Straw poll for P++ feasibility - Externals](https://externals.io/message/106605)
 * [PHP: rfc: Poll: Feasibility of P++](https://wiki.php.net/rfc/p-plus-plus)

こうやって陣営を色分けしようとすることが非難されたような気がしないでもないのですが、議論に時間を使う前にそれぞれの開発者の意向を明確にしたいのは理解できます。

日本時間の4時0分現在では**0:22で圧倒的にNo**です。これは世論調査なので通常のRFCとはかなり毛色が異なるのですが、普段のRFCで議決権を行使してないメンバーも積極的に「No」をつきつけている状況です。直近の提案だと投票者が多いもので[PHP: rfc:typed_properties_v2](https://wiki.php.net/rfc/typed_properties_v2)に70人ほどが票を投じてるのですが、今回の意識調査にはTyped Propertyの議決に参加してないひとが投票しているので、あまり参考にならない感じです。

php.netのVCSのアカウント(＝RFCの議決権)を持っているからといってPHPのアクティブな開発者だというわけではないのですが、すくなくとも人数の面では多くの開発関係者が、P++は非現実的なアイディアだと見ている状況です。

## 追記2 (8月15日)

[PHP: rfc: Poll: Feasibility of P++](https://wiki.php.net/rfc/p-plus-plus)にZeev本人も「No」を投じ、短期的に「P++」計画が推進されることはなくなったようです。

<img width="995" alt="スクリーンショット 2019-08-15 6.51.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4121/56eee967-224d-1993-1012-92d967042788.png">
(時刻表示はUTC: 日本時間 2019年8月15日5時59分)

雑な訳ですが、[Vote: Straw poll for P++ feasibilityでのZeevの投稿](https://externals.io/message/106605#106617)を引用します。

> ユーモラスなトーンによって、やっとinternals@がまとまったことを嬉しく思います。
> 私はあなたがたがこのアイディアが好きではなさそうだという感触を得ました。
>
> 大事なこととして、私はこの投票の正当性についての意見(投票の過程、権限などなど…)は自分の中にしまっておき、2点だけコメントします:
>
>  * このP++のアイディアは真空では無意味です。このアイデアに関する歓迎は、「1つの幸せな大家族」と「分裂」の間にある決定を暗示しました。現段階ではそれらが選択肢として理解されているので、私も反対票を投じたいです(いま投票しました、もちろん)。でも、それは間違った選択だと思います。
>  * 「1つの幸せな大家族」だけが選択肢ではないと明らかになったとき、それを議論するのは確実に意味があることです。家族をソフトに分割する方法を選びましょう: 「細分化 (2<sup>n</sup>方言)」「多くのエディション (n方言)」または「明確な権限の別の方言 (2方言)」。それは私たちの多く(私も多分に含まれる)にとっては不可解だと感じ、このアイディアは全員が団結して反対する「邪悪な分断者」だと受け止められたのだと思います。おそらく私は違っていて、PHPに導入しようとしている変更や機能はどのような分割も必要としないのでしょう。それが事実なら、本当におそろしいことです。私たちはこの道を進むと、それを見ることになるでしょう。現段階でそのレベルのエネルギーをつぎこむことは明らかに早いです。
>  * ですが、私たちが直面しようとしている現実が明らかになったとき、それを探求することには間違いなく意味があります。
>
> このスレッドではこれ以上は返信しません。ただし個人的なメッセージには喜んで応えます。

Zeev本人がこう言ってるので、すくなくともPHP 8.0(2020年12月)に向けたP++が導入されることはないでしょう。コミュニティとしては対立構造が浮き彫りになったことを認めながら、言語分割ではないベターな妥協点を見付けていくことになるでしょう。