Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
PHP に部分適用が来るぞ!……ところで何それ?おいしいの? #phpcon / phpcon...
Search
shogogg
July 20, 2026
Programming
1k
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
840
Technical Debt: Understanding it Rightly, Engaging it Rightly #LaravelLiveJP
shogogg
0
310
なぜあなたのコードには「コシ」がないのか?〜AI時代に問う、最後まで美味しい設計と戦略〜 #phpconkagawa / phpconkagawa2026
shogogg
0
390
我々はなぜ「層」を分けるのか〜「関心の分離」と「抽象化」で手に入れる変更に強いシンプルな設計〜 #phperkaigi / PHPerKaigi 2026
shogogg
2
1.4k
AI 時代だからこそ抑えたい「価値のある」PHP ユニットテストを書く技術 #phpconfuk / phpcon-fukuoka-2025
shogogg
1
1.2k
PHPに関数型の魂を宿す〜PHP 8.5 で実現する堅牢なコードとは〜 #phpcon_hiroshima / phpcon-hiroshima-2025
shogogg
1
850
PHP開発者のためのSOLID原則再入門 #phpcon / PHP Conference Japan 2025
shogogg
6
2.4k
PHPer のための プロポーザル駆動アウトプット入門 #phpcon_niigata / PHP Conference Niigata 2025
shogogg
1
840
技術的負債を正しく理解し、正しく付き合う #phperkaigi / PHPerKaigi 2025
shogogg
7
4k
Other Decks in Programming
See All in Programming
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
300
手動確認はもう限界 〜XCUITestでCustom URL Schemeの遷移を起動種別ごとに自動テストする〜 / Testing Custom URL Schemes with XCUITest
otouto
0
340
JRuby: Past, Present, and Future
headius
0
190
The Good Stuff, Not the Slop: Engineering High-Quality Android Apps with Modern AI Tooling
danybony
1
260
AWS Step Functions 大規模並列の壁を越える / jaws-sonic-2026-niigata-step-functions
kasacchiful
PRO
1
530
Apple Intelligence を用いた個人情報誤送信防止、及びユーザーリクエスト体験の改善について
yukiny
0
150
AgentCore CLI で進化した AWS での AI エージェントの作り方 : 必要な機能を必要な時に
icoxfog417
PRO
3
380
App Storeの外へ──日本のiOSサイドローディング入門 for iOSDC Japan 2026
yuukiw00w
0
250
そのリトライ、死んだコネクションを使い回していませんか ── GoのHTTPクライアントとHTTP/2を実プロダクト障害から学び直す
myus4a
0
250
Building an Out-of-Order CPU
latte72
1
800
【高い買い物LT会】初任給で話題の国産フィジカルAIを買った話
akagami
PRO
0
170
Agents on Rails - Rails at Scale 2026
irinanazarova
0
250
Featured
See All Featured
The Limits of Empathy - UXLibs8
cassininazir
1
690
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
3k
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.4k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
4.9k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.6k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
580
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
3k
How Software Deployment tools have changed in the past 20 years
geshan
1
34k
How to Talk to Developers About Accessibility
jct
2
550
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
680
The Curious Case for Waylosing
cassininazir
1
540
Technical Leadership for Architectural Decision Making
baasie
3
580
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 が待ち遠しいですね!
\中途採用やってます!!/