diff options
Diffstat (limited to 'vhosts/blog/public/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line/index.html')
| -rw-r--r-- | vhosts/blog/public/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line/index.html | 80 |
1 files changed, 40 insertions, 40 deletions
diff --git a/vhosts/blog/public/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line/index.html b/vhosts/blog/public/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line/index.html index 1fe1b48d..ab8e1136 100644 --- a/vhosts/blog/public/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line/index.html +++ b/vhosts/blog/public/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line/index.html @@ -64,14 +64,14 @@ <section id="section--intro"> <h2><a href="#section--intro">記事の構成について</a></h2> <p> - この記事は、普通の fizzbuzz を徐々に変形して最終形にしていく、という構成で書かれている。 最終形を見てどのような仕組みで動いているのか解読してから解説を読みたい、というかたがいれば、 <a href="https://gist.github.com/nsfisis/04c227d5a419867472a0b23a83ad2919#file-fizzbuzz-php-2-letters-per-line-and-supports-php-8-x-without-warnings" rel="noreferrer" target="_blank">このページ</a> にソースコードがあるので、そちらを先に見てほしい。 + この記事は、普通の fizzbuzz を徐々に変形して最終形にしていく、という構成で書かれている。最終形を見てどのような仕組みで動いているのか解読してから解説を読みたい、というかたがいれば、<a href="https://gist.github.com/nsfisis/04c227d5a419867472a0b23a83ad2919#file-fizzbuzz-php-2-letters-per-line-and-supports-php-8-x-without-warnings" rel="noreferrer" target="_blank">このページ</a> にソースコードがあるので、そちらを先に見てほしい。 </p> </section> <section id="section--regulations"> <h2><a href="#section--regulations">レギュレーション</a></h2> <p> - PHP で、次のような制約の下に fizzbuzz を書いた。 + PHP で、次のような制約の下に fizzbuzz を書いた。 </p> <ul> @@ -111,7 +111,7 @@ </ul> <p> - 備考: PHP には <code>short_open_tag</code> というオプションがあり、 これを有効にするとファイル冒頭の <code><?php</code> の代わりに <code><?</code> を使うことができ、文字どおり1行2文字で書ける。 ただ、このオプションはデフォルト off になっている環境が多いようなので、今回は使わないことにした。 + 備考: PHP には <code>short_open_tag</code> というオプションがあり、これを有効にするとファイル冒頭の <code><?php</code> の代わりに <code><?</code> を使うことができ、文字どおり1行2文字で書ける。ただ、このオプションはデフォルト off になっている環境が多いようなので、今回は使わないことにした。 </p> </section> @@ -122,7 +122,7 @@ </p> <p> - 特に、C言語でこのような試みをおこなったことがあるかたならそう思うだろう。事実、Cでのこの制約はほとんど無意味に等しい。 + 特に、C言語でこのような試みをおこなったことがあるかたならそう思うだろう。事実、Cでのこの制約はほとんど無意味に等しい。 </p> <pre class="highlight" language="c"><code class="highlight">#\ @@ -201,11 +201,11 @@ c\ <span class="hljs-comment">/* あとは同じように普通のプログラムを変形するだけなので省略 */</span></code></pre> <p> - バックスラッシュを使った行継続がトークンを区切らない、というのがポイントだ。 + バックスラッシュを使った行継続がトークンを区切らない、というのがポイントだ。 </p> <p> - さて、PHP ではそもそもバックスラッシュを行継続に使うことができない。 これにより、「3文字以上からなるトークンが一切使えない」という制約が課される。 例えば、<code>echo</code> で出力することや、<code>for</code> でループすること、 <code>new</code> でインスタンスを生成することができない。 特に、出力は fizzbuzz をどんなアルゴリズムで実装しようとおこなわなければならないので、できないのは致命的である。 + さて、PHP ではそもそもバックスラッシュを行継続に使うことができない。これにより、「3文字以上からなるトークンが一切使えない」という制約が課される。例えば、<code>echo</code> で出力することや、<code>for</code> でループすること、<code>new</code> でインスタンスを生成することができない。特に、出力は fizzbuzz をどんなアルゴリズムで実装しようとおこなわなければならないので、できないのは致命的である。 </p> <p> @@ -243,11 +243,11 @@ c\ </blockquote> <p> - に反する (というより、「それだとおもしろくもなんともないので、このルールを足した」というのが正しい)。 + に反する (というより、「それだとおもしろくもなんともないので、このルールを足した」というのが正しい)。 </p> <p> - また、2文字だと文字列がまともに書けないのも辛い。<code>''</code> だけで2文字使うので、 「1文字の文字列リテラル」というものを書くことができない。PHP では文字列リテラル中に生の改行が書けるので + また、2文字だと文字列がまともに書けないのも辛い。<code>''</code> だけで2文字使うので、「1文字の文字列リテラル」というものを書くことができない。PHP では文字列リテラル中に生の改行が書けるので </p> <pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$a</span> @@ -256,11 +256,11 @@ a'</span> ;;</code></pre> <p> - とすると <code>$a</code> は <code>"\na"</code> になるのだが、余計な改行が入ってしまう。 + とすると <code>$a</code> は <code>"\na"</code> になるのだが、余計な改行が入ってしまう。 </p> <p> - これらの障害をどのように乗り越えるのか、次節から見ていく。 + これらの障害をどのように乗り越えるのか、次節から見ていく。 </p> </section> @@ -269,7 +269,7 @@ a'</span> <section id="section--commentary--normal-fizzbuzz"> <h3><a href="#section--commentary--normal-fizzbuzz">普通の (?) fizzbuzz</a></h3> <p> - まずは普通に書くとしよう。 + まずは普通に書くとしよう。 </p> <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> @@ -279,14 +279,14 @@ a'</span> }</code></pre> <p> - 素直に書いた fizzbuzz とは言い難いが、このくらいは普通だということにしておかないと、この先がやっていられないので許してほしい。 + 素直に書いた fizzbuzz とは言い難いが、このくらいは普通だということにしておかないと、この先がやっていられないので許してほしい。 </p> </section> <section id="section--commentary--remove-keywords"> <h3><a href="#section--commentary--remove-keywords"><code>for</code> の排除</a></h3> <p> - <code>for</code> は、3文字もある長いキーワードである。 こんなものは使えない。<code>array_</code> 系の関数を使って、適当に置き換えるとしよう。 + <code>for</code> は、3文字もある長いキーワードである。こんなものは使えない。<code>array_</code> 系の関数を使って、適当に置き換えるとしよう。 </p> <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> @@ -299,14 +299,14 @@ fn(<span class="hljs-variable">$i</span>) => );</code></pre> <p> - <code>array_walk</code> や <code>range</code>、<code>printf</code> といった <code>for</code> よりも長いトークンが現れてしまったが、これは次節で直すことにする。 なお、<code>echo</code> は文 (statement) であり式 (expression) ではないので、式である <code>printf</code> に置き換えた。 + <code>array_walk</code> や <code>range</code>、<code>printf</code> といった <code>for</code> よりも長いトークンが現れてしまったが、これは次節で直すことにする。なお、<code>echo</code> は文 (statement) であり式 (expression) ではないので、式である <code>printf</code> に置き換えた。 </p> </section> <section id="section--commentary--shorten-function-invocation"> <h3><a href="#section--commentary--shorten-function-invocation">関数呼び出しの短縮</a></h3> <p> - <code>range</code>、<code>array_walk</code>、<code>printf</code> は長すぎるのでどうにかせねばならない。 ここで、PHP の可変関数を使う。可変関数とは、関数名が文字列として入った変数を経由して、関数を呼び出す機能である。 + <code>range</code>、<code>array_walk</code>、<code>printf</code> は長すぎるのでどうにかせねばならない。ここで、PHP の可変関数を使う。可変関数とは、関数名が文字列として入った変数を経由して、関数を呼び出す機能である。 </p> <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> @@ -323,14 +323,14 @@ fn(<span class="hljs-variable">$i</span>) => );</code></pre> <p> - これで関数を呼び出している所は短くなった。 では、<code>$r</code> や <code>$w</code> や <code>$p</code>、 また <code>'Fizz'</code> や <code>'Buzz'</code> はどうやって 1 行 2 文字に収めるのか。 次のテクニックへ移ろう。 + これで関数を呼び出している所は短くなった。では、<code>$r</code> や <code>$w</code> や <code>$p</code>、また <code>'Fizz'</code> や <code>'Buzz'</code> はどうやって 1 行 2 文字に収めるのか。次のテクニックへ移ろう。 </p> </section> <section id="section--commentary--incompatible-solution"> <h3><a href="#section--commentary--incompatible-solution">余談: PHP 8.x で動作しなくてもいいなら</a></h3> <p> - 今回使ったテクニックを説明する前に、余談として、文字列リテラルの短縮法として今回採用しなかったものを紹介する。 + 今回使ったテクニックを説明する前に、余談として、文字列リテラルの短縮法として今回採用しなかったものを紹介する。 </p> <blockquote> @@ -342,7 +342,7 @@ fn(<span class="hljs-variable">$i</span>) => </blockquote> <p> - というルールがない場合、「未定義の定数が評価された場合、その定数の名前が値になる」という PHP 7.x までの仕様が利用できる。 例えば、 <code>Fizz</code> という文字列が欲しければ、次のようにする。 + というルールがない場合、「未定義の定数が評価された場合、その定数の名前が値になる」という PHP 7.x までの仕様が利用できる。例えば、 <code>Fizz</code> という文字列が欲しければ、次のようにする。 </p> <pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$f</span> @@ -353,7 +353,7 @@ fn(<span class="hljs-variable">$i</span>) => ;;</code></pre> <p> - こうして簡単に文字列を作れる。 なお、この仕様は 7.x 時点でも警告を受けるので、<code>@</code> 演算子を使って抑制してやるとよい。 + こうして簡単に文字列を作れる。なお、この仕様は 7.x 時点でも警告を受けるので、<code>@</code> 演算子を使って抑制してやるとよい。 </p> <pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$f</span> @@ -367,18 +367,18 @@ F. ;;</code></pre> <p> - むしろ、このことがわかっていたからこそ PHP 8.x での動作を要件に課したところがある。 + むしろ、このことがわかっていたからこそ PHP 8.x での動作を要件に課したところがある。 </p> </section> <section id="section--commentary--shorten-string-literals"> <h3><a href="#section--commentary--shorten-string-literals">文字列リテラルの短縮</a></h3> <p> - 実際に使った手法の説明に移る。 + 実際に使った手法の説明に移る。 </p> <p> - ずばり、文字列同士のビット演算を使う。 PHP では、文字列同士でビット演算 (<code>&</code>、<code>|</code>、<code>^</code>) をした場合、 文字列の各バイトごとに指定したビット演算がなされ、それを結合したものが演算結果となる。 + ずばり、文字列同士のビット演算を使う。PHP では、文字列同士でビット演算 (<code>&</code>、<code>|</code>、<code>^</code>) をした場合、文字列の各バイトごとに指定したビット演算がなされ、それを結合したものが演算結果となる。 </p> <pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$a</span> = <span class="hljs-string">"12345"</span>; @@ -394,7 +394,7 @@ F. <span class="hljs-comment">// => F]AXQ</span></code></pre> <p> - これを踏まえ、次のコードを見てみよう。 + これを踏まえ、次のコードを見てみよう。 </p> <pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$x</span> = <span class="hljs-string">"x\nOm\n"</span>; @@ -403,7 +403,7 @@ F. <span class="hljs-keyword">echo</span> <span class="hljs-string">"<span class="hljs-subst">$r</span>\n"</span>;</code></pre> <p> - 実行すると、<code>range</code> が表示される。 さて、PHP では文字列リテラル中に生の改行を直接書いてもよいのだった (「主な障害」の節を参照のこと)。 書きかえてみよう。 + 実行すると、<code>range</code> が表示される。さて、PHP では文字列リテラル中に生の改行を直接書いてもよいのだった (「主な障害」の節を参照のこと)。書きかえてみよう。 </p> <pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$x</span> @@ -420,7 +420,7 @@ o'</span> <span class="hljs-keyword">echo</span> <span class="hljs-string">"<span class="hljs-subst">$r</span>\n"</span>;</code></pre> <p> - さらに <code>#</code> を使って適当に調整すると、次のようになる。 + さらに <code>#</code> を使って適当に調整すると、次のようになる。 </p> <pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$x</span> @@ -443,11 +443,11 @@ o'</span> <span class="hljs-keyword">echo</span> <span class="hljs-string">"<span class="hljs-subst">$r</span>\n"</span>;</code></pre> <p> - 1行あたり2文字で、<code>range</code> という文字列を生成することに成功した。 他の必要な文字列にも、同様の処理をほどこす。 + 1行あたり2文字で、<code>range</code> という文字列を生成することに成功した。他の必要な文字列にも、同様の処理をほどこす。 </p> <p> - 備考: <code>Buzz</code> 中にある小文字の <code>u</code> は、このロジックだと non-printable な文字になってしまう。 ここまでのテクニックを駆使すれば回避するのはそう難しくないので、考えてみてほしい。 + 備考: <code>Buzz</code> 中にある小文字の <code>u</code> は、このロジックだと non-printable な文字になってしまう。ここまでのテクニックを駆使すれば回避するのはそう難しくないので、考えてみてほしい。 </p> </section> </section> @@ -455,7 +455,7 @@ o'</span> <section id="section--stretched-fizzbuzz"> <h2><a href="#section--stretched-fizzbuzz">完成系</a></h2> <p> - 完成したものがこちら。 + 完成したものがこちら。 </p> <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> @@ -612,18 +612,18 @@ _! <section id="section--outro"> <h2><a href="#section--outro">感想など</a></h2> <p> - PHP は、スクリプト言語の中だとシンタックスシュガーが少ない (体感)。 この挑戦は不可能に思われたが、PHP マニュアルとにらめっこしていたらなんとかなった。 + PHP は、スクリプト言語の中だとシンタックスシュガーが少ない (体感)。この挑戦は不可能に思われたが、PHP マニュアルとにらめっこしていたらなんとかなった。 </p> <p> - みんなもプログラムを細長くしよう。 + みんなもプログラムを細長くしよう。 </p> </section> <section id="section--alternative-solution"> <h2><a href="#section--alternative-solution">余談2: 別解</a></h2> <p> - PHP では、バッククォートを使ってシェルを呼び出せる。 これは <code>shell_exec</code> 関数と等価である。 さて、PHP ではバックスラッシュによる行継続が使えないと書いたが、シェルでは使える (当然だが、呼び出されるシェルに依存する。Bash なら大丈夫だろう。知らんけど)。 + PHP では、バッククォートを使ってシェルを呼び出せる。これは <code>shell_exec</code> 関数と等価である。さて、PHP ではバックスラッシュによる行継続が使えないと書いたが、シェルでは使える (当然だが、呼び出されるシェルに依存する。Bash なら大丈夫だろう。知らんけど)。 </p> <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> @@ -640,7 +640,7 @@ o\ `);</code></pre> <p> - なお、ここでは簡単のため出力に <code>printf</code> をそのまま使っているが、 実際には <code>printf</code> という文字列を合成して可変関数で呼び出す。 + なお、ここでは簡単のため出力に <code>printf</code> をそのまま使っているが、実際には <code>printf</code> という文字列を合成して可変関数で呼び出す。 </p> <p> @@ -656,11 +656,11 @@ o\ </blockquote> <p> - に違反してしまう。スペースが使えないと引数とコマンドを区切れない。これは困った。 + に違反してしまう。スペースが使えないと引数とコマンドを区切れない。これは困った。 </p> <p> - もうこれ以上は不可能だと思っていたのだが、この記事の執筆中に解決する方法を思いついたので載せておく。 + もうこれ以上は不可能だと思っていたのだが、この記事の執筆中に解決する方法を思いついたので載せておく。 </p> <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> @@ -694,7 +694,7 @@ ${ `);</code></pre> <p> - 先程と同じく、<code>chr</code> や <code>printf</code> を生成する部分は長くなるので省いた。 + 先程と同じく、<code>chr</code> や <code>printf</code> を生成する部分は長くなるので省いた。 </p> <pre class="highlight"><code>${ @@ -702,7 +702,7 @@ ${ '}</code></pre> <p> - は変数で、中にはスペースとエスケープが入っている (<code>chr(32) . chr(92)</code>)。 シェルに渡されている文字列は次のようになる。 + は変数で、中にはスペースとエスケープが入っている (<code>chr(32) . chr(92)</code>)。シェルに渡されている文字列は次のようになる。 </p> <pre class="highlight"><code>e\ @@ -715,15 +715,15 @@ o\ 3\</code></pre> <p> - これは、前掲したコマンドと同じだ。 かくして、スペースを陽に書かずにシェルをおおよそ自由に扱えるようになった。 Fizzbuzz のワンライナーくらいすぐ書けるだろうから、あとはなんとかなるだろう (試してないけど)。 + これは、前掲したコマンドと同じだ。かくして、スペースを陽に書かずにシェルをおおよそ自由に扱えるようになった。Fizzbuzz のワンライナーくらいすぐ書けるだろうから、あとはなんとかなるだろう (試してないけど)。 </p> <p> - ということでこれは別解ということにしておく。 + ということでこれは別解ということにしておく。 </p> <p> - ちなみに、PHP 8.2 からは、この記法で Warning が出るようになるようだ。 + ちなみに、PHP 8.2 からは、この記法で Warning が出るようになるようだ。 </p> <pre class="highlight"><code>${ @@ -731,7 +731,7 @@ o\ '}</code></pre> <p> - 最新版で警告が出るというのも美しくないので、私としては本編の解法を推す。 + 最新版で警告が出るというのも美しくないので、私としては本編の解法を推す。 </p> </section> </div> |
