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
1.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
パーサーコンビネーターの実装を通じて学ぶ宣言的プログラミングの魅力 #phpcon_ehime / phpcon-ehime-2026
shogogg
1
53
PHP と TypeScript の型システム比較:AI 時代の「型」は誰のためにあるのか? #frontend_phpcon_do / frontend_phpcon_do_2026
shogogg
1
960
Technical Debt: Understanding it Rightly, Engaging it Rightly #LaravelLiveJP
shogogg
0
330
なぜあなたのコードには「コシ」がないのか?〜AI時代に問う、最後まで美味しい設計と戦略〜 #phpconkagawa / phpconkagawa2026
shogogg
0
410
我々はなぜ「層」を分けるのか〜「関心の分離」と「抽象化」で手に入れる変更に強いシンプルな設計〜 #phperkaigi / PHPerKaigi 2026
shogogg
2
1.5k
AI 時代だからこそ抑えたい「価値のある」PHP ユニットテストを書く技術 #phpconfuk / phpcon-fukuoka-2025
shogogg
1
1.2k
PHPに関数型の魂を宿す〜PHP 8.5 で実現する堅牢なコードとは〜 #phpcon_hiroshima / phpcon-hiroshima-2025
shogogg
1
940
PHP開発者のためのSOLID原則再入門 #phpcon / PHP Conference Japan 2025
shogogg
6
2.5k
PHPer のための プロポーザル駆動アウトプット入門 #phpcon_niigata / PHP Conference Niigata 2025
shogogg
1
940
Other Decks in Programming
See All in Programming
AIが実装を担う時代の「技術設計」と「チームマネジメント」
kamina_zzz
1
130
自作Discord音声botをLambda MicroVMsに移行した話 / Migrating My Discord Voice Bot to Lambda MicroVMs
akihisaikeda
1
270
Herb in Rails 8.2: Your ERB views, now HTML-aware @ Kaigi on Rails 2026, Tokyo, Japan
marcoroth
2
400
SFCで実現する病院・医療システムの動的組み立て式UI
koukimiura
1
170
AI時代のFlutter品質設計 — アプリ品質を守るQuality Layers
omatty198
0
350
AI駆動開発4年目の現在地(『あなたはFDEになるべきか?』イベント資料)
kumaiu
0
130
AI-Powered Domain-Driven Design
ziobrando
0
380
Long Living Tokens, Die, Die, Die! (or: The One Ring is Banned in Modern)
sylph01
0
400
Crash Auto Pipelines
veronikapj
1
350
そのデザイントークン、Flutterでも同じ見た目になりますか?
nakamizu
0
300
[Dev Group Paris Octobre 26] Agentforce, SIforce, Claudeforce, Slackbot… on s'y retrouve ?
nabondance
0
130
高橋メソッドでCVE解説シリーズ 〜CVE-2026-112816〜
hakkadaikon
0
200
Featured
See All Featured
Build your cross-platform service in a week with App Engine
jlugia
234
19k
Exploring anti-patterns in Rails
aemeredith
4
560
Paper Plane (Part 1)
katiecoart
PRO
2
12k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6.2k
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
460
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
70
68k
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.5k
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
540
Building a Scalable Design System with Sketch
lauravandoore
464
34k
Accessibility Awareness
sabderemane
1
290
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.3k
A Soul's Torment
seathinner
8
3.9k
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 が待ち遠しいですね!
\中途採用やってます!!/