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
580
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
750
Technical Debt: Understanding it Rightly, Engaging it Rightly #LaravelLiveJP
shogogg
0
280
なぜあなたのコードには「コシ」がないのか?〜AI時代に問う、最後まで美味しい設計と戦略〜 #phpconkagawa / phpconkagawa2026
shogogg
0
340
我々はなぜ「層」を分けるのか〜「関心の分離」と「抽象化」で手に入れる変更に強いシンプルな設計〜 #phperkaigi / PHPerKaigi 2026
shogogg
2
1.3k
AI 時代だからこそ抑えたい「価値のある」PHP ユニットテストを書く技術 #phpconfuk / phpcon-fukuoka-2025
shogogg
1
1.1k
PHPに関数型の魂を宿す〜PHP 8.5 で実現する堅牢なコードとは〜 #phpcon_hiroshima / phpcon-hiroshima-2025
shogogg
1
790
PHP開発者のためのSOLID原則再入門 #phpcon / PHP Conference Japan 2025
shogogg
6
2.3k
PHPer のための プロポーザル駆動アウトプット入門 #phpcon_niigata / PHP Conference Niigata 2025
shogogg
1
780
技術的負債を正しく理解し、正しく付き合う #phperkaigi / PHPerKaigi 2025
shogogg
7
3.9k
Other Decks in Programming
See All in Programming
霧の中の代数的エフェクト
funnyycat
1
480
「寝てても仕事が進む」Claude Codeで組む第二の脳
tomoyafujita2016
0
310
今さら聞けない .NET CLI
htkym
0
180
自動化したのに回らないテスト運用の壁ーAI時代の品質責任と生産性
mfunaki
0
130
『コードを書く以外の』エンジニアリング〜課金基盤移行プロジェクト推進のためのTips4選
yuriko1211
0
580
Laravel Boostに学ぶ、AIにPHPを書かせる技術 〜OSSの実装から蒸留するエージェント制御の王道〜
kentaroutakeda
3
670
Built Our Own Background Agent at LayerX
layerx
PRO
9
5k
源内ハンズオン概要編
hideg
0
120
S3 を使うアプリケーションをローカル完結で動かすことに全力を注いでみた / Running S3 Apps Offline
contour_gara
0
370
Japan Community Day at Kubecon + CloudNativeCon Japan 2026: Learning Container Privilege Control by Building My Own Low-Level Container Runtime
ternbusty
1
140
Apache Hive: Toward a Cloud Native Lakehouse
okumin
0
180
型も通る、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
540
Featured
See All Featured
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
170
Bash Introduction
62gerente
615
220k
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
680
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
400
Six Lessons from altMBA
skipperchong
29
4.4k
YesSQL, Process and Tooling at Scale
rocio
174
15k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.8k
AI: The stuff that nobody shows you
jnunemaker
PRO
9
890
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
460
The Cost Of JavaScript in 2023
addyosmani
55
10k
GitHub's CSS Performance
jonrohan
1033
470k
Art, The Web, and Tiny UX
lynnandtonic
304
22k
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 が待ち遠しいですね!
\中途採用やってます!!/