Skip to content

PHPは何を捨て、どんな力を手に入れてきたのか

公開日:

東京都大田区蒲田大田区産業プラザ PiOで開催された『PHPカンファレンス2019』でレギュラーセッション(25分)として発表しました。

Download PDF

スライドテキスト

Page 1

PHPは何を捨て、

どんな力を手に入れてきたのか

What did PHP give up and what power did it get?

PHP Conference Japan

2019-12-01 #phpcon

Page 2

お前誰よ

  • うさみけんた (@tadsan) / Zonu.EXE
  • GitHub/Packagistでは id: zonuexe
  • ピクシブ株式会社 pixiv事業本部
  • Emacs Lisper, PHPer
  • Emacs PHP Modeのメンテナ引き継ぎました
  • 好きなリスプはEmacs Lispです
  • Qiitaに記事を書いたり変なコメントしてるよ

Page 3

Page 4

Page 5

Page 6

これまでのあらすじ

Page 7

昨日

Page 8

Page 9

Page 10

そもそもPHP自体がレガシーと言われがち

Page 11

PHPカンファレンス2016

Page 12

Page 13

本日のお題

Page 14

Page 15

そもそもPHPというプログラミング言語はどんな機能を持っているのか

Page 16

“We have things like protected properties.We have abstract methods. We have all this stuff that your computer science teacher told you you should be using.I don't care about this crap at all.”

–Rasmus Lerdorf https://en.wikiquote.org/wiki/Rasmus_Lerdorf

Page 17

“PHPにはprotectedプロパティも抽象メソッドもありますよ。計算機科学の教授が「使え」と言ってるものは全部。そんなことはクソ興味ないですけど”–Rasmus Lerdorf

Page 18

僕が思いつくPHPの機能をざっと挙げてみると…

Page 19

抽象クラス, トレイト, インターフェイス, ジェネレータ, イテレータ, クロージャ, 函数の動的呼び出し, 無名クラス, eval, 型宣言, 連想配列, リフレクションAPI, 自己文書化, 標準入出力の読み書き,REPL, クラスの遅延ロード

Page 20

改めてPHPの言語仕様が追加された時系列を見てみよう

Page 21

PHP 7.4

Arrow functions 2.0

JavaScriptなど

Typed Property

Javaなどの静的型付き言語

Numeric Literal Separator

Ada, Ruby, JavaScriptなど

Page 22

PHP 7.3

Flexible Heredoc and Nowdoc

Rubyにも似た記法はある

list() Reference Assignment

これはPHP独自に近い

Page 23

PHP 7.2

Trailing Commas In List Syntax

カンマ(,)を並べて書く記法のほぼ全てで余分につけてもよくなった

Parameter Type Widening

継承したクラスで引数の型省略

Page 24

PHP 7.1

Nullable Types

Void Return Type

Multi catch

Allow specifying keys in list()

Page 25

PHP 7.0

Anonymous Class

Generator Delegation(yield from)

Return Type Declaration

Null Coalesce Operator

Scalar type hints

Page 26

PHP 5.6

Exponential Operator(pow**)

Importing named function

Variadic function argument (...)

配列を引数として展開

Argument unpacking(...)

可変長引数を配列として取得

Page 27

PHP 5.5

Generator

finally keyword (try-catch-...)

Const array/string dereference

Allow non-scalar keys in foreach

Page 28

PHP 5.4

Traits

Short array syntax

callable type hint

Page 29

PHP 5.3

Closures (function expression)

関数式、クロージャ、またはラムダ式

JavaScriptのfunctionに似てるが、レキシカルスコープ(変数の捕捉)のためにuseキーワードが必要

Page 30

ひとつひとつの機能の話を語ったら20分では全然足りない

Page 31

なので本日はPHPがどう変わっていったかというエピソードを交えてPHPの言語機能を紹介していきます

Page 32

さて

Page 33

PHP 7.4.0がリリースされましたね

Page 34

12月1日は本日何の日でしょう?

Page 35

Page 36

Page 37

27

この数は何でしょう

Page 38

Page 39

せいかい

PHP7.4に向けて受理されたRFCの数

Page 40

RFC?

Page 41

(Request for Comment)RFC

新バージョンへの変更提案

PHPの機能の改廃の提案はRFCを通じて行われる提案はメーリングリストで議論されPHP.net VCSアカウントの所持者が議決する

Page 42

の歴史PHP RFC

2008年頃から機能提案のために運用されはじめた

2011年(5.4alpha1)から正式なリリースプロセスになった

Page 43

“PHP releases have always been done spontaneously, in a somehow chaotic way. Individual(s) decided when a release will happen and what could or could fit in. Release managers role are unclear and the way to nominate them is not clearly defined either.”‒ Request for Comments: Release Process https://wiki.php.net/rfc/releaseprocess

Page 44

“PHPのリリースは常に無秩序な方法で自発的に行われてきました。個々人がいつリリースされるか、何が起こるか、そして何が収まるかを決定しています。リリースマネージャの役割は不明瞭で、指名の手続きも明確に定義されていません。”‒ Request for Comments: Release Process https://wiki.php.net/rfc/releaseprocess

Page 45

(2008~2010年)この時期のPHPには何があったでしょう

Page 46

この当時のPHP情勢

Page 47

廣川さんの「PHPの今とこれから」が当時の事情の貴重な資料

Page 48

‒ PHPの今とこれから2009 https://www.slideshare.net/hirokawa/php2009

Page 49

‒ PHPの今とこれから2009 https://www.slideshare.net/hirokawa/php2009

Page 50

‒ PHPの今とこれから2009 https://www.slideshare.net/hirokawa/php2009

Page 51

Unicode化とはどういうことか?

Page 52

言語処理系の文字列実装

CSI方式(Code Set Independent)

特定のコードセットに依存しない

UCS正規化方式(Universal Character Set)

内部的に文字コードを統一してから処理する

https://magazine.rubyist.net/articles/0025/0025-Ruby19_m17n.html

Page 53

言語ごとの文字列実装

CSI方式

Ruby, Python 2, PHP

UCS正規化方式

Java, JavaScript, Perl,Python 3, PHP6

Page 54

ざっくりCSI方式

文字列変換をしないので、オーバーヘッドは最小限

サポートする文字コードごとに文字列処理の実装が要る

Page 55

ざっくりUCS正規化方式

文字列を変換するので入出力で変換オーバーヘッドがある

文字列処理は内部文字コード用のものだけ用意すればいい

Page 56

PHP6はUTF-16を目指した

UCS正規化方式への移行

従来のPHP文字列はバイト列

PHP 5.2で(binary)キャストと b"string" が追加された

結局Unicode化しなかったので、ただのエイリアス

Page 57

重要なこと

UCS正規化しないとUnicodeサポートできないわけではない

UTF-16にしても1コードポイント=1文字になるわけではない (サロゲートペア)

Page 58

PHP6.0の顛末

実装は難航し、文字列以外の6.0向け機能は5.3, 5.4系でそれぞれリリースされた

2010年3月にリポジトリのtrunk(master)が5.3にロールバックした

Page 59

Page 60

開発が頓挫したPHP6は欠番としてスキップされPHP5.6の次は7.0になったというのは有名な話

Page 61

Page 62

(私はこの時代にPHPに触れておらず議論を詳しくは追ってないので想像の域は出ないが)

Page 63

この時代にPHPはカウボーイによる開発スタイルを捨て、明文化されたスケジュールとプロセスによる開発体制に移行した

Page 64

PHPのリリース計画やメンテナンス期間が定められたのもこのRFCから

Page 65

PHP5.3ではPHP6を待たず重要な機能がマージされた

Page 66

‒ PHPの今とこれから2009 https://www.slideshare.net/hirokawa/php2009

Page 67

遅延静的束縛

static::method();

親クラスの静的メソッドから継承されたクラスのメソッドを呼び出す

ちなみにforward_static_call()関数のマニュアルには「静的メソッドをコールする」と書いてるが、この説明は間違い (翻訳の問題ではない)

Page 68

Dynamic static call

Hoge::fuga()の代りに

$class="Hoge"; $class::fuga();

で呼べるようになった

静的メソッド版可変関数

Page 69

名前空間

クラスや関数を階層化できる

名前空間違いの同名のクラスが作れるようになった

フルネームをFQSENと呼ぶ

useでファイルローカルな別名を付けることもできる

Page 70

useの誤解されがちなところ

include/requireのようにファイルを読み込む機能ではない

ファイル内で呼べるようローカルな名前を付けるだけ

存在しないクラスをuseしてもエラーにはならない

Page 71

クロージャ (関数式・ラムダ式)

ローカルな関数が作れる

ただの関数を作れるだけではなく、外側の変数を引き込めるのが重要 (関数閉包)

普通の関数やメソッドにその機能はない

Page 72

クロージャ以前の無名関数

create_function()という関数で関数式っぽいことはできた

その実態はevalで lambda_1のような関数を動的に定義する

この関数はリスキーなのでPHP7.2からdeprecated

Page 73

PHPのクロージャ

構文上はJavaScriptのものに似ているが、useで列挙しないと外側の変数を捕捉できない

この仕様にはPHPの変数の説明しにくい挙動が関わっている…

Page 74

PHPの変数

PHPで変数の値を再代入したり引数に渡したりすると、(意味論として)値がコピーされる

クロージャでuseしたときもPHPでは引数と同じ動きになる

&を付けると変数の参照をとる

Page 75

JavaScriptのクロージャ

make_counter = function() {i = 0;return function () {return i++;};};

c1 = make_counter();

console.log(c1());console.log(c1());console.log(c1());

Page 76

PHPのクロージャ

この記述だと$i=0のコピーされるだけ。 &を付けると変数リファレンスで値を更新できる

<?php$make_counter = function() {$i = 0;return function () use ($i) {return $i++;};};

$c1 = $make_counter();

var_dump($c1()); //=> 0 var_dump($c1()); //=> 0 var_dump($c1()); //=> 0

Page 77

最初のRFCクロージャ

実はJavaScript風クロージャよりも前に短いクロージャが提案されてた (2008年3月)

RFC: Short syntax for anonymous functions

ただしDraft止まり

Page 78

‒ PHP: rfc:short-syntax-for-anonymous-functions https://wiki.php.net/rfc/short-syntax-for-anonymous-functions

Page 79

‒ PHP: rfc:short-syntax-for-anonymous-functions https://wiki.php.net/rfc/short-syntax-for-anonymous-functions

Page 80

時は流れて2019年

Page 81

PHP: rfc:arrow_functions_v2 https://wiki.php.net/rfc/arrow_functions_v2

Page 82

PHP: rfc:arrow_functions_v2 https://wiki.php.net/rfc/arrow_functions_v2

Page 83

姿形は違うが幾度もの議論の末に短い記法の関数式が導入された

Page 84

ところで

Page 85

PHP: rfc:arrow_functions_v2 https://wiki.php.net/rfc/arrow_functions_v2

Page 86

私たちはこの提案者の名前を見たことがある!

Page 87

‒ PHPの今とこれから2012 https://www.slideshare.net/hirokawa/php-now-and-then-2012-at-php-conference-2012-tokyo-japan

Page 88

ジェネレータ

(古典的な)コルーチン

「何度も繰り返す」構造を関数(メソッド)を使って簡単に作れる

Page 89

Nikita Popov

近年のPHPの中核的な開発者

PHP5.5以降、非常に多数の言語機能を実装してPHPに取り入れてきた

PHP-Parserなどの作者

去年の大学院を卒業し今年JetBrainsに入社してPhpStormチームに参加

Page 90

とてもざっくり言うとレガシー仕様を消し、不条理な挙動は是正し、他言語にあるようなカッコイイ機能を追加提案してきた

Page 91

不条理な挙動って?

Page 92

例: 未定義定数はその文字列になる

echo PHP;

=> 文字列 "PHP" が出力

E_NOTICE/E_WARNING

error_reportingが低い環境でさりげなく生き残ってた可能性が高い

Page 93

歴史的経緯で残ったレガシー仕様はさくっと消しまくっていこうぜ

Page 94

いいじゃん

いいじゃん

Page 95

📛

Page 96

🔥

Page 97

🔥

🔥

🔥

Page 98

燃えた

Page 99

Page 100

Deprecate PHP's short open tags, again

一般的なPHPタグは<?php ... ?>または<?= ... ?> だが、<? ... ?>という形式もある

php.iniで有効無効を切替られる環境によってOnだったりOffだったり

Page 101

Deprecate PHP's short open tags, again

XML宣言との相性がとても悪い

そんな半端モンは引導を渡してやろうぜ! ということで提案された

構文がシンプルになるし、機械的に変換もできるから良いだろ、という主旨

Page 102

Zeevによる反論

Page 103

Page 104

Zeev Suraski

PHP3・4の開発者

相方のAndi GutmansとともにVM型処理系のZend Engine開発

PHPでよくあるZend…はZeevとAndiに由来

PHPコードに未だに影響を残す

Page 105

さらなる提案

Page 106

Page 107

続きはWebで

Page 108

Page 109

まとめ

Page 110

PHPは力を手に入れようとして失敗してきた経験が結構ある

Page 111

現在のPHPは静的解析できる環境が年々強まって往年のざっくりさは息をひそめつつある

Page 112

銀河の平和はどっちだ