@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-php source = '< +code-printer?:( CodePrinter.make-config CodeSyntax.php CodeTheme.iceberg-light |> CodePrinter.set-number-fun CodeDesign.number-fun-null )(source); > let fizzbuzz-normal = ` printf( (($i%3?'':'Fizz') . ($i%5?'':'Buzz') ?: $i) . "\n"), ); ` let fizzbuzz-2 = ` $p( (($i%3?'':$f) . ($i%5?'':$b) ?: $i) . " ")); ` let string-xor = ` F]AXQ `# let string-xor-fizz = ` Fizz `# let fizzbuzz-stretched-1 = ` (' x! ~! '^ 'z ` let fizzbuzz-stretched-4 = `Hd G' )( (( $i %3 ? '' :' c! '^ 'L [p ` let fizzbuzz-stretched-5 = `') .( $i %5 ? '' :( 'H '^ (' ') ). (' ` let fizzbuzz-stretched-6 = `b! '^ 'i S' )( 3* 3* 13 ). (' p' ^ 'p ` let fizzbuzz-stretched-7 = `') )? : $i ). " ") ); ` open FigBox in document '< +set-config(| SlydifiThemeAkasaka.default-config with color-emph = Color.black; |); +make-title(| title = { |明日のあなたの役に立たない |PHPコーディング技法 |~細長いFizzBuzzを書く~ |}; author = {|nsfisis (いまむら)|}; date = {|第150回PHP勉強会@東京|}; |); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +frame{自己紹介}< +fig-center(vconcat [ gap 75pt; hconcat [ textbox{nsfisis (いまむら)}; gap 20pt; include-image 50pt `assets/me.jpeg`; ]; gap 20pt; textbox{\@ デジタルサーカス株式会社}; ]); > %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +frame{細長いFizzBuzz?}< +code-block-php(fizzbuzz-normal); > +frame{細長いFizzBuzz?}< +code-block-php(fizzbuzz-normal); +p{ \emph{1行あたりの最大文字数}を最小化しよう } > +frame{1行あたり最大6文字で書いたFizzBuzz}< +code-block-php(fizzbuzz-w5); > +frame{細長いFizzBuzz?}< +fig-center(vconcat [ gap 100pt; textbox{1行何文字あればFizzBuzzが書けるのか?}; ]); > +frame{細長いFizzBuzz?}< +fig-center(vconcat ?:(align-center) [ gap 100pt; textbox{1行何文字あればFizzBuzzが書けるのか?}; gap 20pt; textbox{\emph{2文字}あれば書ける!}; ]); > %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +frame{何が難しいのか?}< +p{ 2文字までのトークンしか使えない } +listing{ * ほとんどのキーワードが書けない ** 書けるのは\inline-code(`as`);、\inline-code(`do`);、\inline-code(`fn`);、\inline-code(`if`);、\inline-code(`or`);のみ * ほとんどの関数が呼べない ** 呼べるのは\inline-code(`_`); (\inline-code(`gettext`);の別名)、\inline-code(`pi`);、\inline-code(`dl`);のみ * 空でない文字列が書けない ** クォート、中身の文字、クォート、で最低3文字必要 } +p{ ではどうするか? } > +frame{FizzBuzzを細長くする}< +code-block-php(fizzbuzz-0); +p{ このFizzBuzzをベースに変形する } > +frame{FizzBuzzを細長くする}< +code-block-php(fizzbuzz-0); +p{ ステップ1: 絶対に短縮できない、\emph{キーワードを排除}する } +p{ \inline-code(`for`);と\inline-code(`echo`);を消す } > +frame{FizzBuzzを細長くする}< +code-block-php(fizzbuzz-1); +listing{ * \inline-code(`for`);は\inline-code(`array_walk`);と\inline-code(`range`);に * \inline-code(`echo`);は\inline-code(`printf`);に * \inline-code(` +frame{FizzBuzzを細長くする}< +code-block-php(fizzbuzz-1); +p{ さっきよりも長くなってない? } > +frame{FizzBuzzを細長くする}< +code-block-php(fizzbuzz-1); +p{ ステップ2: 関数呼び出しをvariable function経由に } > +frame{FizzBuzzを細長くする}< +code-block-php(fizzbuzz-2); +listing{ * 関数名とFizz、Buzzを変数に代入 * \inline-code(`100`);を\inline-code(`10*10`);に * \inline-code(`"\n"`);を使わず、直接改行を挿入 * 上を無視すれば、2文字以下のトークンだけで構成されている } > +frame{FizzBuzzを細長くする}< +code-block-php(fizzbuzz-2); +p{ ステップ3: 文字列を幅2文字以下で生成する } > +frame{文字列リテラルの短縮}< +code-block-php(string-xor); +p{ 文字列の XOR 演算を使う } +p{ 文字列をバイト列と見做し、各要素にXOR演算を適用して結合する } > +frame{文字列リテラルの短縮}< +code-block-php(string-xor-fizz); +p{ ほとんどの文字列を、1行2文字以下で表せる } > +frame{細長いFizzBuzz完成}< +code-block-php(fizzbuzz-stretched-1); > +frame{細長いFizzBuzz完成}< +code-block-php(fizzbuzz-stretched-2); > +frame{細長いFizzBuzz完成}< +code-block-php(fizzbuzz-stretched-3); > +frame{細長いFizzBuzz完成}< +code-block-php(fizzbuzz-stretched-4); > +frame{細長いFizzBuzz完成}< +code-block-php(fizzbuzz-stretched-5); > +frame{細長いFizzBuzz完成}< +code-block-php(fizzbuzz-stretched-6); > +frame{細長いFizzBuzz完成}< +code-block-php(fizzbuzz-stretched-7); +p{ \emph{完成!} } > %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +frame{そしてその先へ......}< +fig-center(vconcat ?:(align-center) [ gap 100pt; textbox{この縛りの下で、どのくらい複雑なプログラムが書けるのか?}; ]); > +frame{そしてその先へ......}< +fig-center(vconcat ?:(align-center) [ gap 100pt; textbox{この縛りの下で、どのくらい複雑なプログラムが書けるのか?}; gap 50pt; textbox{任意のプログラムが書ける!}; ]); > +frame{そしてその先へ......}< +fig-center(vconcat ?:(align-center) [ gap 100pt; textbox{この縛りの下で、どのくらい複雑なプログラムが書けるのか?}; gap 50pt; textbox{任意のプログラムが書ける!}; gap 20pt; textbox{\emph{Laravel}も動かせる}; ]); > +frame{そしてその先へ......}< +fig-center(vconcat ?:(align-center) [ gap 100pt; textbox{任意のプログラムを動かそうとしたときの壁}; gap 20pt; textbox{\inline-code(`eval`);は関数ではないので、variable functionが使えない}; ]); > +frame{そしてその先へ......}< +fig-center(vconcat ?:(align-center) [ gap 100pt; textbox{ではどうやってLaravelを動かすか?}; ]); > +frame{おわりに}< +fig-center(vconcat ?:(align-center) [ gap 100pt; textbox{続きは\emph{PHPerKaigi 2023}で}; ]); > +section{|没スライド|}< +frame{余談: PHP 8 系で動かなくてもいいなら}< +code-block-php(`$f =F .i .z .z ; `); +p{ 未定義の定数が評価されると、その定数の名前の文字列になる (PHP 7.x 以下) } > +frame{余談: PHP 8 系で動かなくてもいいなら}< +code-block-php(`$f =@ F. @i . @z . @z ; `); +p{ 警告を抑制するため、\inline-code(`@`);演算子を使う } > > >