@require: class-slydifi/theme/akasaka @require: code-printer/code-design @require: code-printer/code-printer @require: code-printer/code-syntax @require: code-printer/code-theme @require: figbox/figbox let-block +code-block source keywords = let syntax = let void-syntax-rule = CodePrinter.syntax-rule-fun (fun _ -> None) in CodePrinter.make-syntax (| line-comment = void-syntax-rule; block-comment = void-syntax-rule; string = void-syntax-rule; keywords = keywords; identifier = void-syntax-rule; others = []; |) in '< +code-printer?:( CodePrinter.make-config syntax CodeTheme.iceberg-light |> CodePrinter.set-number-fun CodeDesign.number-fun-null )(source); > let-block +code-block-php source = '< +code-printer?:( CodePrinter.make-config CodeSyntax.php CodeTheme.iceberg-light |> CodePrinter.set-number-fun CodeDesign.number-fun-null )(source); > let catchline-try = `getPrevious()) { printf('%c', $e->getLine() + 23); } echo "\n"; }` let catchline-fn-f = `function f(int $i) { if ($i < 0) f(); try { match ($i) { 0 => X, // 12行目 // (間の空行は省略) 2 => X, // 49行目 // (間の空行は省略) 1, 3 => X, // 57行目 }; } finally { f($i - 1); } }` let catchline-fn-f-with-comments = `function f(int $i) { if ($i < 0) f(); // エラー!引数が足りない! try { match ($i) { 0 => X, // 12行目: エラー!未定義の定数! // (間の空行は省略) 2 => X, // 49行目: エラー!未定義の定数! // (間の空行は省略) 1, 3 => X, // 57行目: エラー!未定義の定数! }; } finally { f($i - 1); } }` let catchline-fn-f-snip = `function f(int $i) { if ($i < 0) f(); try { // ... } finally { f($i - 1); } }` let error-chain = `getMessage(), PHP_EOL; // => b echo $e->getPrevious()->getMessage(), PHP_EOL; // => a }` open FigBox in document '< +make-title(| title = { |PHPerKaigi 2023 のトークン問題で |ボツにした問題を供養する |}; author = {|nsfisis (いまむら)|}; date = {|第149回PHP勉強会@東京|}; |); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +frame{自己紹介}< +fig-center(vconcat [ hconcat [ gap 20pt; textbox{nsfisis (いまむら)}; gap 20pt; include-image 50pt `assets/me.jpeg`; ]; gap 20pt; textbox{\@ デジタルサーカス株式会社}; ]); > %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +frame{PHPerKaigiとは}< +fig-center(vconcat [ gap 20pt; textbox{2018年から開催されているPHPのカンファレンス}; gap 20pt; textbox{今年2023年も、3月23日から25日に開催}; ]); > +frame{PHPerチャレンジとは}< +fig-center(vconcat [ gap 20pt; textbox{PHPerKaigiの企画の1つ}; gap 20pt; textbox{\inline-code(`#`);から始まる文字列(トークン)を、}; textbox{公式サイトやスポンサーブログから探す}; gap 10pt; textbox{例: \inline-code(`#PHP`);}; ]); > +frame{トークン問題とは}< +fig-center(vconcat [ gap 20pt; textbox{PHPerチャレンジのトークンを、PHPのソースコードに隠す}; gap 20pt; textbox{実行したり解読したりするとトークンが入手できる}; ]); > +frame{デジタルサーカスのトークン問題}< +fig-center(vconcat [ gap 20pt; textbox{今年も問題を作成しました(全5問)}; gap 20pt; textbox{ボツ問になった問題のうちの1問を供養}; ]); > %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +frame{Catchline}< +code-block-php(catchline-try); > +frame{Catchline}< +code-block-php(catchline-fn-f); > +frame{Catchline}< +code-block-php(catchline-try); +p{ \inline-code(`f()`);を呼び出して\inline-code(`Throwable`);を捕まえ、何かする } > +frame{Catchline}< +code-block-php(catchline-fn-f-with-comments); > +frame{Catchline}< +code-block-php(catchline-try); +p{ \inline-code(`f(3)`);からスタート } > +frame{Catchline}< +code-block-php(catchline-fn-f-snip); +p{ 1ずつ減らして、\inline-code(`$i`);が負なら引数なしで呼ぶ } > +frame{Catchline}< +p{ \listing{ * \inline-code(`f(3)`); * \inline-code(`f(2)`); * \inline-code(`f(1)`); * \inline-code(`f(0)`); * \inline-code(`f(-1)`); * \inline-code(`f()`); ここで終わり } } > +frame{Catchline}< +code-block-php(catchline-try); +p{ \inline-code(`\Throwable::getPrevious()`);を順に辿り、(エラーの発生した行数+23)を } +p{ ASCIIコード\text-color(Color.gray(0.75)){[1]}と見做して出力 } +p{ \text-color(Color.gray(0.75)){[1]: VAS Syndrome} } > +frame{Catchline}< +p{ \inline-code(`\Throwable::getPrevious()`); } +p{ このエラーの1つ前のエラー(=大本の原因) } +p{ \listing{ * エラー処理中に別のエラーが起きたとき、元々のエラーを保存する * 内部利用しているライブラリが投げた例外クラスを、自分で定義した例外クラスでラップする } } > +frame{Catchline}< +code-block-php(error-chain); +p{ \inline-code(`finally`);節の中で例外を発生させると、PHPの処理系が勝手に`$previous`を設定する } > +frame{Catchline}< +code-block-php(catchline-fn-f-with-comments); > +frame{Catchline}< +code-block-php(catchline-try); +p{ (エラーの発生した行数+23)をASCIIコードと見做して出力 } > +frame{Catchline}< +code-block-php(catchline-fn-f-with-comments); > +frame{Catchline}< +p{ \listing{ * 12 + 23 = 35 (\inline-code(`#`);) * 49 + 23 = 72 (\inline-code(`H`);) * 57 + 23 = 80 (\inline-code(`P`);) } } +p{ 組み合わせて\inline-code(`#PHP`);に } > %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +frame{おわりに}< +fig-center(vconcat ?:(align-center) [ gap 20pt; textbox{来たる3月のPHPerKaigi 2023で}; gap 20pt; textbox{これより数段凝った問題を5つ出題します!}; gap 20pt; textbox{みなさまの挑戦をお待ちしております!}; ]); > >