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
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
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
コーディングルールの鮮度を保ちたい for SRE NEXT 2026 / keep-fresh-go-internal-conventions-sre-next-2026
handlename
0
140
吝嗇家のためのAI活用 / AI development for miser - ChatGPT + Issue Driven Development
tooppoo
0
190
Generative UI & AI-Assistants for Your Angular Solutions
manfredsteyer
PRO
0
110
壊れたパーサから始める関数型設計と構成的なパーサ #fp_matsuri
raiga0310
2
220
Hatena Engineer Seminar #37「言語モデルの活用に関する研究」
slashnephy
0
520
AI 輔助遺留系統現代化的經驗分享
jame2408
1
1.2k
SREの積み重ねがAI駆動開発のガードレールになった ― 7つの実践/SRE Guardrails The 7
tomoyakitaura
8
4.3k
Generative UI & AI-Assistants for Your Angular Solutions
manfredsteyer
PRO
1
180
フィードバックで育てるAI開発
kotaminato
1
120
技術記事、 専門家としてのプログラマ、 言語化
mizchi
14
7.5k
AWS CDK を「作」ってみた 〜フルスクラッチで見えた CDK の裏側〜 / aws-cdk-from-scratch
gotok365
3
360
PHP Application における Kubernetes 内 gRPC 通信
ganchiku
0
420
Featured
See All Featured
Utilizing Notion as your number one productivity tool
mfonobong
4
420
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
62
45k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
880
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
The browser strikes back
jonoalderson
0
1.4k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.6k
Exploring anti-patterns in Rails
aemeredith
3
440
ラッコキーワード サービス紹介資料
rakko
1
3.9M
Designing Powerful Visuals for Engaging Learning
tmiket
1
450
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
220
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
260
Crafting Experiences
bethany
1
220
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 が待ち遠しいですね!
\中途採用やってます!!/