Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
PHP に部分適用が来るぞ!……ところで何それ?おいしいの? #phpcon / phpcon...
Search
shogogg
July 20, 2026
Programming
180
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
PHP に部分適用が来るぞ!……ところで何それ?おいしいの? #phpcon / phpcon-2026
2026年7月20日に開催された PHP Conference Japan 2026 の LT 登壇資料です
shogogg
July 20, 2026
More Decks by shogogg
See All by shogogg
PHP と TypeScript の型システム比較:AI 時代の「型」は誰のためにあるのか? #frontend_phpcon_do / frontend_phpcon_do_2026
shogogg
1
710
Technical Debt: Understanding it Rightly, Engaging it Rightly #LaravelLiveJP
shogogg
0
270
なぜあなたのコードには「コシ」がないのか?〜AI時代に問う、最後まで美味しい設計と戦略〜 #phpconkagawa / phpconkagawa2026
shogogg
0
330
我々はなぜ「層」を分けるのか〜「関心の分離」と「抽象化」で手に入れる変更に強いシンプルな設計〜 #phperkaigi / PHPerKaigi 2026
shogogg
2
1.3k
AI 時代だからこそ抑えたい「価値のある」PHP ユニットテストを書く技術 #phpconfuk / phpcon-fukuoka-2025
shogogg
1
1k
PHPに関数型の魂を宿す〜PHP 8.5 で実現する堅牢なコードとは〜 #phpcon_hiroshima / phpcon-hiroshima-2025
shogogg
1
760
PHP開発者のためのSOLID原則再入門 #phpcon / PHP Conference Japan 2025
shogogg
6
2.2k
PHPer のための プロポーザル駆動アウトプット入門 #phpcon_niigata / PHP Conference Niigata 2025
shogogg
1
760
技術的負債を正しく理解し、正しく付き合う #phperkaigi / PHPerKaigi 2025
shogogg
7
3.8k
Other Decks in Programming
See All in Programming
SLOをサービス品質の共通言語にするために 取り組んできたこと
wakana0222
0
500
1B+ /day規模のログを管理する技術
broadleaf
0
140
ソフトウェア設計に溶けるインフラ ― AWS CDK のインフラ認識論
konokenj
2
460
Snowflake Summitでの新機能 CoCo / CoWork / snowflake-summit-2026-overall-what-new-coco
tatsuhiro
1
230
なぜ関数型プログラミングで「型」と「証明」が語られるのか #fp_matsuri
kajitack
3
920
初めてのKubernetes 本番運用でハマった話
oku053
0
130
エンジニアにデザインハーネスを 〜デザインプロセスを規定するためのハーネス〜 / Design harness from an engineer's perspective
rkaga
2
1.5k
【やさしく解説 設計編 #1】「ドメイン駆動」と「実装駆動」ってなに? 〜設計の考え方を、たとえ話で学ぼう〜
panda728
PRO
1
120
Laravelで学ぶ Webアプリケーションチューニング入門/web_application_tuning_101
hanhan1978
4
500
型も通る、synthも通る、それでも危ない 〜AIのCDKの権限とコストを機械で検証する〜 / It Passes Type Checks, It Passes Synth Checks, but It’s Still Risky — Automatically Verifying Permissions and Costs in AI’s CDK —
seike460
PRO
1
280
Haskell/Servantを通してWebミドルウェアを捉え直す
pizzacat83
1
580
エンジニア向け会社紹介/Findy Company Profile
findyinc
6
360k
Featured
See All Featured
Google's AI Overviews - The New Search
badams
0
1.1k
Between Models and Reality
mayunak
4
370
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Abbi's Birthday
coloredviolet
3
8.7k
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
2
1.5k
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
1k
Fashionably flexible responsive web design (full day workshop)
malarkey
408
67k
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
0
340
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
2
330
Testing 201, or: Great Expectations
jmmastey
46
8.2k
Stop Working from a Prison Cell
hatefulcrawdad
274
21k
Producing Creativity
orderedlist
PRO
348
40k
Transcript
PHP に部分適用が来るぞ! ……ところで何それ?おいしいの? Shogo Kawase / @shogogg
2026年11月
PHP 8.6 でついに……
PHPに部分適用が実装! 🎉 (見込み)
部分適用?なにそれ?おいしいの?
5分で解説します!
自己紹介 河瀨 翔吾 / Shogo Kawase エンジニアリングマネージャー I LOVE... 妻
/ 型安全 / アジャイル / ももいろクローバーZ 麻雀 / F1 / マリオカート / ACE COMBAT shogogg shogogg
部分適用とは • 部分適用(Partial Application)とは、複数の引数をとる関数や メソッドにおいて、引数の一部をあらかじめ固定(適用)し、 残りの引数だけをとる新しい関数を生成するプログラミングの手法 • 第一級関数や高階関数を多用する関数型プログラミング でよく使われる •
よく似た手法に「カリー化」があるが、厳密には別物(今回は割愛)
具体的なコード例
これが…… $userIds = [1, 24, 105]; $formattedIds = array_map( fn
(int $id): string => sprintf('USER-%05d', $id), $userIds, );
こうなる! $userIds = [1, 24, 105]; $formattedIds = array_map( //
fn (int $id): string => sprintf('USER-%05d', $id), sprintf('USER-%05d', ?), $userIds, );
これが…… $users = [['name' => 'Alice'], ['name' => 'Bob']]; $roles
= [['role' => 'admin'], ['role' => 'member']]; $merged = array_map( fn (array $u, array $r): array => array_merge( $u, $r, ['active' => true], ), $users, $roles, );
こうなる! $users = [['name' => 'Alice'], ['name' => 'Bob']]; $roles
= [['role' => 'admin'], ['role' => 'member']]; $merged = array_map( array_merge(..., ['active' => true]), $users, $roles, ); // [ // ['name' => 'Alice', 'role' => 'admin', 'active' => true], // ['name' => 'Bob', 'role' => 'member', 'active' => true], // ]
これが…… $title = ' My First PHP Blog '; $slug
= $title |> strtolower(...) |> fn (string $v): string => str_replace(' ', '-', $v) |> fn (string $v): string => trim($v, '-');
こうなる! $title = ' My First PHP Blog '; $slug
= $title |> strtolower(...) |> str_replace(' ', '-', ?) |> trim(?, '-'); めっちゃスッキリ!
えっと……スッキリするだけ?
PHPの部分適用のここがすごい!
① プレースホルダー方式
JavaScript の部分適用 const buildApiEndpoint = (baseUrl, version, path) => {
return `${baseUrl}/${version}/${path}`; } // bind による部分適用 // 第1引数(this)に null を指定するお作法がノイズに…… const f = buildApiEndpoint.bind(null, 'https://api.example.com', 'v1'); f('users'); // https://api.example.com/v1/users f('items'); // https://api.example.com/v1/items
Python の部分適用 from functools import partial def buildApiEndpoint(baseUrl, version, path):
return f"{baseUrl}/{version}/{path}" # partial による部分適用 # ノイズは少ないが、直感的とは言い難い f = partial(buildApiEndpoint, 'https://api.example.com', 'v1') f('users') # https://api.example.com/v1/users f('items') # https://api.example.com/v1/items
PHP の部分適用 function buildApiEndpoint(string $baseUrl, string $version, string $path): string
{ return "{$baseUrl}/{$version}/{$path}"; } // ? による部分適用 // ノイズもなく、極めて直感的なシンタックスで部分適用を実現! $f = buildApiEndpoint('https://api.example.com', 'v1', ?); $f('users'); // https://api.example.com/v1/users $f('items'); // https://api.example.com/v1/items
プレースホルダー方式の部分適用 • 関数呼び出しの一部を ? や ... に置き換えるだけでOK! • 圧倒的にシンプルな記述で部分適用を実現! •
先頭から連続する引数だけでなく、任意の位置の引数を指定可能! • ここまでシンプルに部分適用を実現している言語はほとんどない!
Scala の部分適用 def buildApiEndpoint(baseUrl: String, version: String, path: String): String
= { s"$baseUrl/$version/$path" } // _ による部分適用 // PHP と同じくシンプルな記述で自然に部分適用を実現している val f = buildApiEndpoint("https://api.example.com", "v1", _) f("users") // https://api.example.com/v1/users f("items") // https://api.example.com/v1/items
② パフォーマンスの向上
第一級callableと部分適用 • 部分適用は PHP 8.1 で追加された第一級callable の拡張として実装 されている • 第一級callable
は独自の仕組みにより、ユーザー定義 Closure よりも 高い実行効率・パフォーマンスを実現している • 第一級callable 関連の opcode を見ることで、部分適用を使った時の 内部処理を垣間見ることができる
<?php $list = array_map(fn (int $x): int => sqrt($x), [1,
2, 3]); line #* E I O op fetch ext return operands ----------------------------------------------------------------------------------------2 0 E > INIT_FCALL 'array_map' 1 DECLARE_LAMBDA_FUNCTION ~1 [0] 2 SEND_VAL ~1 3 SEND_VAL <array> 4 DO_ICALL $2 5 ASSIGN !0, $2 3 6 > RETURN 1 line #* E I O op fetch ext return operands ----------------------------------------------------------------------------------------2 0 E > RECV !0 1 INIT_FCALL 'sqrt' 2 SEND_VAR !0 3 DO_ICALL $1 4 VERIFY_RETURN_TYPE $1 5 > RETURN $1 6* VERIFY_RETURN_TYPE 7* > RETURN null
<?php $list = array_map(fn (int $x): int => sqrt($x), [1,
2, 3]); line #* E I O op fetch ext return operands ----------------------------------------------------------------------------------------2 0 E > INIT_FCALL 'array_map' 1 DECLARE_LAMBDA_FUNCTION ~1 [0] 2 SEND_VAL ~1 3 SEND_VAL <array> 4 DO_ICALL $2 5 ASSIGN !0, $2 3 6 > RETURN 1 array_map にアロー関数式を渡している line #* E I O op fetch ext return operands ----------------------------------------------------------------------------------------2 0 E > RECV !0 1 INIT_FCALL 'sqrt' 2 SEND_VAR !0 3 DO_ICALL $1 4 VERIFY_RETURN_TYPE $1 5 > RETURN $1 6* VERIFY_RETURN_TYPE 7* > RETURN null
<?php $list = array_map(fn (int $x): int => sqrt($x), [1,
2, 3]); line #* E I O op fetch ext return operands ----------------------------------------------------------------------------------------2 0 E > INIT_FCALL 'array_map' 1 DECLARE_LAMBDA_FUNCTION ~1 [0] . 2 SEND_VAL ~1 3 SEND_VAL <array> 4 DO_ICALL $2 5 ASSIGN !0, $2 3 6 > RETURN 1 line #* E I O op fetch ext return operands ----------------------------------------------------------------------------------------2 0 E > RECV !0 1 INIT_FCALL 'sqrt' 2 SEND_VAR !0 3 DO_ICALL $1 4 VERIFY_RETURN_TYPE $1 5 > RETURN $1 6* VERIFY_RETURN_TYPE 7* > RETURN null DECLARE_LAMBDA_FUNCTION で関数を定義
<?php $list = array_map(fn (int $x): int => sqrt($x), [1,
2, 3]); line #* E I O op fetch ext return operands ----------------------------------------------------------------------------------------2 0 E > INIT_FCALL 'array_map' 1 DECLARE_LAMBDA_FUNCTION ~1 [0] 2 SEND_VAL ~1 3 SEND_VAL <array> 4 DO_ICALL $2 5 ASSIGN !0, $2 3 6 > RETURN 1 定義した関数で sqrt の呼び出しや型チェックが実行される line #* E I O op fetch ext return operands ----------------------------------------------------------------------------------------2 0 E > RECV !0 1 INIT_FCALL 'sqrt' . 2 SEND_VAR !0 3 DO_ICALL $1 4 VERIFY_RETURN_TYPE $1 . 5 > RETURN $1 6* VERIFY_RETURN_TYPE . 7* > RETURN null
<?php $list = array_map(sqrt(...), [1, 2, 3]); line #* E
I O op fetch ext return operands ----------------------------------------------------------------------------------------2 0 E > INIT_FCALL 'array_map' 1 INIT_FCALL 'sqrt' 2 CALLABLE_CONVERT ~1 3 SEND_VAL ~1 4 SEND_VAL <array> 5 DO_ICALL $2 6 ASSIGN !0, $2 3 7 > RETURN 1 第一級callableを使ったコード
<?php $list = array_map(sqrt(...), [1, 2, 3]); line #* E
I O op fetch ext return operands ----------------------------------------------------------------------------------------2 0 E > INIT_FCALL 'array_map' 1 INIT_FCALL 'sqrt' . 2 CALLABLE_CONVERT ~1 . 3 SEND_VAL ~1 4 SEND_VAL <array> 5 DO_ICALL $2 . 6 ASSIGN !0, $2 3 7 > RETURN 1 array_map(C実装)からsqrt(C実装)を直接呼び出している!
<?php echo strtolower('HELLO!!'); line #* E I O op fetch
ext return operands ----------------------------------------------------------------------------------------2 0 E > INIT_FCALL 'strtolower' 1 SEND_VAL 'HELLO%21%21' 2 DO_ICALL $0 3 ECHO $0 3 4 > RETURN 1
<?php echo strtolower('HELLO!!'); line #* E I O op fetch
ext return operands ----------------------------------------------------------------------------------------2 0 E > INIT_FCALL 'strtolower' 1 SEND_VAL 'HELLO%21%21' 2 DO_ICALL $0 3 ECHO $0 3 4 > RETURN 1 単純な関数呼び出し
<?php echo strtolower('HELLO!!'); line #* E I O op fetch
ext return operands ----------------------------------------------------------------------------------------2 0 E > INIT_FCALL 'strtolower'. 1 SEND_VAL 'HELLO%21%21' 2 DO_ICALL $0 3 ECHO $0 . . 3 4 > RETURN 1 関数を呼び出して出力するシンプルな opcode
<?php echo 'HELLO!!' |> (fn (string $x): string => strtolower($x));
line #* E I O op fetch ext return operands ----------------------------------------------------------------------------------------2 0 E > DECLARE_LAMBDA_FUNCTION ~0 [0] 1 INIT_DYNAMIC_CALL ~0 2 SEND_VAL_EX 'HELLO%21%21' 3 DO_FCALL 0 $1 4 ECHO $1 3 5 > RETURN 1 パイプ演算子+アロー関数式 line #* E I O op fetch ext return operands ----------------------------------------------------------------------------------------2 0 E > RECV !0 1 INIT_FCALL 'strtolower' 2 SEND_VAR !0 3 DO_ICALL $1 4 VERIFY_RETURN_TYPE $1 5 > RETURN $1 6* VERIFY_RETURN_TYPE 7* > RETURN null
<?php echo 'HELLO!!' |> (fn (string $x): string => strtolower($x));
line #* E I O op fetch ext return operands ----------------------------------------------------------------------------------------2 0 E > DECLARE_LAMBDA_FUNCTION ~0 [0] . 1 INIT_DYNAMIC_CALL ~0 2 SEND_VAL_EX 'HELLO%21%21' 3 DO_FCALL 0 $1 4 ECHO $1 3 5 > RETURN 1 line #* E I O op fetch ext return operands ----------------------------------------------------------------------------------------2 0 E > RECV !0 1 INIT_FCALL 'strtolower' 2 SEND_VAR !0 3 DO_ICALL $1 4 VERIFY_RETURN_TYPE $1 5 > RETURN $1 6* VERIFY_RETURN_TYPE 7* > RETURN null DECLARE_LAMBDA_FUNCTION で関数を定義
<?php echo 'HELLO!!' |> (fn (string $x): string => strtolower($x));
line #* E I O op fetch ext return operands ----------------------------------------------------------------------------------------2 0 E > DECLARE_LAMBDA_FUNCTION ~0 [0] 1 INIT_DYNAMIC_CALL ~0 2 SEND_VAL_EX 'HELLO%21%21' 3 DO_FCALL 0 $1 4 ECHO $1 3 5 > RETURN 1 定義した関数で strtolowerの呼び出しや型チェックが実行される line #* E I O op fetch ext return operands ----------------------------------------------------------------------------------------2 0 E > RECV !0 1 INIT_FCALL 'strtolower' 2 SEND_VAR !0 3 DO_ICALL $1 4 VERIFY_RETURN_TYPE $1 . 5 > RETURN $1 6* VERIFY_RETURN_TYPE . 7* > RETURN null
<?php echo 'HELLO!!' |> strtolower(...); line #* E I O
op fetch ext return operands ----------------------------------------------------------------------------------------2 0 E > INIT_FCALL 'strtolower' 1 SEND_VAL 'HELLO%21%21' 2 DO_ICALL $0 3 ECHO $0 3 4 > RETURN 1 パイプ演算子+第一級callable
<?php echo 'HELLO!!' |> strtolower(...); line #* E I O
op fetch ext return operands ----------------------------------------------------------------------------------------2 0 E > INIT_FCALL 'strtolower' 1 SEND_VAL 'HELLO%21%21' 2 DO_ICALL $0 3 ECHO $0 3 4 > RETURN 1 DECLARE_LAMBDA_FUNCTION が消えた!しかも……
<?php echo 'HELLO!!' |> strtolower(...); line #* E I O
op fetch ext return operands ----------------------------------------------------------------------------------------2 0 E > INIT_FCALL 'strtolower' 1 SEND_VAL 'HELLO%21%21' 2 DO_ICALL $0 3 ECHO $0 3 4 > RETURN 1 パイプ演算子+第一級callable の opcode と……
<?php echo strtolower('HELLO!!'); line #* E I O op fetch
ext return operands ----------------------------------------------------------------------------------------2 0 E > INIT_FCALL 'strtolower' 1 SEND_VAL 'HELLO%21%21' 2 DO_ICALL $0 3 ECHO $0 3 4 > RETURN 1 通常の関数呼び出しの opcode……
<?php echo 'HELLO!!' |> strtolower(...); line #* E I O
op fetch ext return operands ----------------------------------------------------------------------------------------2 0 E > INIT_FCALL 'strtolower' 1 SEND_VAL 'HELLO%21%21' 2 DO_ICALL $0 3 ECHO $0 3 4 > RETURN 1
<?php echo strtolower('HELLO!!'); line #* E I O op fetch
ext return operands ----------------------------------------------------------------------------------------2 0 E > INIT_FCALL 'strtolower' 1 SEND_VAL 'HELLO%21%21' 2 DO_ICALL $0 3 ECHO $0 3 4 > RETURN 1
<?php echo 'HELLO!!' |> strtolower(...); line #* E I O
op fetch ext return operands ----------------------------------------------------------------------------------------2 0 E > INIT_FCALL 'strtolower' 1 SEND_VAL 'HELLO%21%21' 2 DO_ICALL $0 3 ECHO $0 3 4 > RETURN 1
<?php echo strtolower('HELLO!!'); line #* E I O op fetch
ext return operands ----------------------------------------------------------------------------------------2 0 E > INIT_FCALL 'strtolower' 1 SEND_VAL 'HELLO%21%21' 2 DO_ICALL $0 3 ECHO $0 3 4 > RETURN 1
<?php echo 'HELLO!!' |> strtolower(...); line #* E I O
op fetch ext return operands ----------------------------------------------------------------------------------------2 0 E > INIT_FCALL 'strtolower' 1 SEND_VAL 'HELLO%21%21' 2 DO_ICALL $0 3 ECHO $0 3 4 > RETURN 1 <?php echo strtolower('HELLO!!'); 完全に一致!! line #* E I O op fetch ext return operands ----------------------------------------------------------------------------------------2 0 E > INIT_FCALL 'strtolower' 1 SEND_VAL 'HELLO%21%21' 2 DO_ICALL $0 3 ECHO $0 3 4 > RETURN 1
まとめ • PHP の部分適用は、シンプルな文法と opcode レベルの最適化により 高い可読性とパフォーマンス の両方を実現! • array_map
のような高階関数や、パイプ演算子との相性は抜群! • PHP 8.6 が待ち遠しいですね!
\中途採用やってます!!/