aboutsummaryrefslogtreecommitdiffhomepage
path: root/content/posts
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2023-03-19 03:24:43 +0900
committernsfisis <nsfisis@gmail.com>2023-03-19 03:24:43 +0900
commitdb3d51ddc421dad68abddb95d01ffdab440197d6 (patch)
tree35a6b45bb964b22fa74486596f4e640db82fb0ac /content/posts
parentcb5a2a0afdf822651db035904cd8c1307a7b7743 (diff)
downloadblog.nsfisis.dev-db3d51ddc421dad68abddb95d01ffdab440197d6.tar.gz
blog.nsfisis.dev-db3d51ddc421dad68abddb95d01ffdab440197d6.tar.zst
blog.nsfisis.dev-db3d51ddc421dad68abddb95d01ffdab440197d6.zip
feat(content): specify heading id
Diffstat (limited to 'content/posts')
-rw-r--r--content/posts/2021-03-30/phperkaigi-2021.xml38
-rw-r--r--content/posts/2021-10-02/ruby-then-keyword-and-case-in.xml12
-rw-r--r--content/posts/2021-10-02/rust-where-are-primitive-types-from.xml6
-rw-r--r--content/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre.xml223
-rw-r--r--content/posts/2021-10-02/vim-swap-order-of-selected-lines.xml38
-rw-r--r--content/posts/2022-04-09/phperkaigi-2022-tokens.xml40
-rw-r--r--content/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal.xml6
-rw-r--r--content/posts/2022-05-01/phperkaigi-2022.xml12
-rw-r--r--content/posts/2022-08-27/php-conference-okinawa-code-golf.xml12
-rw-r--r--content/posts/2022-08-31/support-for-communty-is-employee-benefits.xml2
-rw-r--r--content/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line.xml955
11 files changed, 671 insertions, 673 deletions
diff --git a/content/posts/2021-03-30/phperkaigi-2021.xml b/content/posts/2021-03-30/phperkaigi-2021.xml
index 745db4b..ab682b9 100644
--- a/content/posts/2021-03-30/phperkaigi-2021.xml
+++ b/content/posts/2021-03-30/phperkaigi-2021.xml
@@ -17,7 +17,7 @@
</revision>
</revhistory>
</info>
- <section xml:id="_phperkaigi_2021_参加レポ">
+ <section xml:id="report">
<title>PHPerKaigi 2021 参加レポ</title>
<simpara>
2021-03-26 から 2021-03-28
@@ -34,7 +34,7 @@
発表はトラック A、B に分かれていたのだが、今回はすべて A
トラックを視聴している (切り替えるのが面倒だっただけ)。
</simpara>
- <section xml:id="_凡例">
+ <section xml:id="report-legend">
<title>凡例</title>
<blockquote>
<simpara>
@@ -45,9 +45,9 @@
感想など
</simpara>
</section>
- <section xml:id="_day_0_前夜祭_20210327">
+ <section xml:id="report--day-0">
<title>Day 0 前夜祭 (2021/03/27)</title>
- <section xml:id="_1730_a">
+ <section xml:id="report--day-0--1730-a">
<title>17:30 [A]</title>
<simpara>
PHP で AWS Lambda
@@ -103,7 +103,7 @@
だという先入観を持っていたのだが、この発表のデモによればそうでもないらしい。
</simpara>
</section>
- <section xml:id="_1810_a">
+ <section xml:id="report--day-0--1810-a">
<title>18:10 [A]</title>
<simpara>
大規模サイトの SEO
@@ -155,7 +155,7 @@
は大して知らないので新鮮な話が多かった。その分語れることも少ない……。
</simpara>
</section>
- <section xml:id="_1850_a">
+ <section xml:id="report--day-0--1850-a">
<title>18:50 [A]</title>
<blockquote>
<simpara>
@@ -217,7 +217,7 @@
いわゆる「健常者」にとって、こうした問題を普段の生活の中で意識するのは難しい。だからこそ情報へのアンテナは張っておくようにしたい。
</simpara>
</section>
- <section xml:id="_1930_a">
+ <section xml:id="report--day-0--1930-a">
<title>19:30 [A]</title>
<simpara>
PHP で FUSE
@@ -284,9 +284,9 @@
</simpara>
</section>
</section>
- <section xml:id="_day_1_20210327">
+ <section xml:id="report--day-1">
<title>Day 1 (2021/03/27)</title>
- <section xml:id="_1050_a">
+ <section xml:id="report--day-1--1050-a">
<title>10:50 [A]</title>
<simpara>
ATDD
@@ -380,7 +380,7 @@
高レベルテストの自動化は現在のプロジェクトでも感じており、自動化のチャンスは伺っている。とはいえセッションでも指摘されているように自動化することにコストがかかりすぎる領域があるのも事実で、そのバランスが難しい。
</simpara>
</section>
- <section xml:id="_1150_a">
+ <section xml:id="report--day-1--1150-a">
<title>11:50 [A]</title>
<simpara>
型解析を用いたリファクタリング
@@ -421,13 +421,13 @@
Ruby の typeprof には注目している。
</simpara>
</section>
- <section xml:id="_1230_a">
+ <section xml:id="report--day-1--1230-a">
<title>12:30 [A]</title>
<simpara>
昼食をとっていた。事前に何か食料を買っておくべきだった。
</simpara>
</section>
- <section xml:id="_1310_a">
+ <section xml:id="report--day-1--1310-a">
<title>13:10 [A]</title>
<simpara>
Documentation as Code
@@ -490,7 +490,7 @@
情報を起点にするのは理にかなっている。問題はトレースをいつ、どう取るかだろうか。それを自動化しなければ、実態との乖離が避けられないだろう。
</simpara>
</section>
- <section xml:id="_1410_a">
+ <section xml:id="report--day-1--1410-a">
<title>14:10 [A]</title>
<simpara>
cookie による session 管理
@@ -500,7 +500,7 @@
やセッションの話としては非常に分かりやすくまとめられていたので、知らない人が学ぶにはいい教材だろう。
</simpara>
</section>
- <section xml:id="_1450_a">
+ <section xml:id="report--day-1--1450-a">
<title>14:50 [A]</title>
<simpara>
PHP のエラーと例外
@@ -613,7 +613,7 @@
のように、すでに例外が言語システムに根ざしている言語ではどうすればよいか。この場合も同じく静的検証の力を借りることになるだろう。
</simpara>
</section>
- <section xml:id="_1530_a">
+ <section xml:id="report--day-1--1530-a">
<title>15:30 [A]</title>
<simpara>
Laravel のメール認証
@@ -623,7 +623,7 @@
の知識がない私にはまったくついていけなかった。また、個人的にタイトルがややミスリーディングに感じた。
</simpara>
</section>
- <section xml:id="_1610_a">
+ <section xml:id="report--day-1--1610-a">
<title>16:10 [A]</title>
<simpara>
gRPC
@@ -677,7 +677,7 @@
というエコシステムに乗れることのメリットが大きいと感じる。そのエコシステムにうまく乗れない時点で、うーんという感じ。
</simpara>
</section>
- <section xml:id="_1650_a">
+ <section xml:id="report--day-1--1650-a">
<title>16:50 [A]</title>
<simpara>
アーキテクチャテスト
@@ -726,7 +726,7 @@
</blockquote>
</section>
</section>
- <section xml:id="_day_2_20210328">
+ <section xml:id="report--day-2">
<title>Day 2 (2021/03/28)</title>
<simpara>
冒頭に書いた通り、2日目から体調が悪くまともに聴けていない。途中までは頭痛を我慢しつつ見ていたのだが、まともに入ってこなかった。
@@ -735,7 +735,7 @@
残念ではあるが、いずれにせよ見られていない発表は他にもあるので、今週末にでもまとめて見ようと思う。
</simpara>
</section>
- <section xml:id="_全体の感想">
+ <section xml:id="report--comments">
<title>全体の感想</title>
<simpara>
Day 2
diff --git a/content/posts/2021-10-02/ruby-then-keyword-and-case-in.xml b/content/posts/2021-10-02/ruby-then-keyword-and-case-in.xml
index 40ac316..00afc01 100644
--- a/content/posts/2021-10-02/ruby-then-keyword-and-case-in.xml
+++ b/content/posts/2021-10-02/ruby-then-keyword-and-case-in.xml
@@ -23,14 +23,14 @@
<simpara>
<hr/>
</simpara>
- <section xml:id="_tl_dr">
+ <section xml:id="tl-dr">
<title>TL; DR</title>
<simpara>
<literal>case</literal> - <literal>in</literal> によるパターンマッチング構文でも、<literal>case</literal> - <literal>when</literal>
と同じように <literal>then</literal> が使える (場合によっては使う必要がある)。
</simpara>
</section>
- <section xml:id="_then_とは">
+ <section xml:id="what-is-then-keyword">
<title><literal>then</literal> とは</title>
<simpara>
使われることは稀だが、Ruby では <literal>then</literal>
@@ -75,7 +75,7 @@
]]>
</programlisting>
</section>
- <section xml:id="_なぜ普段は書かなくてもよいのか">
+ <section xml:id="why-then-is-usually-unnecessary">
<title>なぜ普段は書かなくてもよいのか</title>
<simpara>
普通 Ruby のコードで <literal>then</literal>
@@ -116,7 +116,7 @@
無事 Hello, World! と出力されるようになった。
</simpara>
</section>
- <section xml:id="_なぜ_then_や_や改行が必要か">
+ <section xml:id="why-then-or-linebreak-is-needed">
<title>なぜ <literal>then</literal> や <literal>;</literal> や改行が必要か</title>
<simpara>
なぜ <literal>then</literal> や <literal>;</literal> や改行 (以下 「<literal>then</literal> 等」)
@@ -158,7 +158,7 @@
が代用できるので、ほとんどの場合 <literal>then</literal> は必要ない。
</simpara>
</section>
- <section xml:id="_case_in_における_then">
+ <section xml:id="then-in-case-in">
<title><literal>case</literal> - <literal>in</literal> における <literal>then</literal></title>
<simpara>
ようやく本題にたどり着いた。来る Ruby 3.0 では <literal>case</literal> と <literal>in</literal>
@@ -257,7 +257,7 @@
]]>
</programlisting>
</section>
- <section xml:id="_まとめ">
+ <section xml:id="outro">
<title>まとめ</title>
<itemizedlist>
<listitem>
diff --git a/content/posts/2021-10-02/rust-where-are-primitive-types-from.xml b/content/posts/2021-10-02/rust-where-are-primitive-types-from.xml
index f395f4f..7c19fc5 100644
--- a/content/posts/2021-10-02/rust-where-are-primitive-types-from.xml
+++ b/content/posts/2021-10-02/rust-where-are-primitive-types-from.xml
@@ -22,7 +22,7 @@
<simpara>
<hr/>
</simpara>
- <section xml:id="_前置き">
+ <section xml:id="intro">
<title>前置き</title>
<simpara>
Rust
@@ -63,7 +63,7 @@
</simpara>
</blockquote>
</section>
- <section xml:id="_調査">
+ <section xml:id="code-reading">
<title>調査</title>
<simpara>
調査に使用したソース (調査時点での最新 master)
@@ -230,7 +230,7 @@
という名前の別の型が見つかるからだ。
</simpara>
</section>
- <section xml:id="_まとめ">
+ <section xml:id="outro">
<title>まとめ</title>
<simpara>
Rust
diff --git a/content/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre.xml b/content/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre.xml
index 2a61fb4..4e3f187 100644
--- a/content/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre.xml
+++ b/content/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre.xml
@@ -22,13 +22,13 @@
<simpara>
<hr/>
</simpara>
- <section xml:id="_tl_dr">
+ <section xml:id="tl-dr">
<title>TL; DR</title>
<simpara>
違いはない。ただのエイリアス。
</simpara>
</section>
- <section xml:id="_調査記録">
+ <section xml:id="code-reading">
<title>調査記録</title>
<simpara>
Vim の autocmd events には似通った名前のものがいくつかある。大抵は
@@ -56,114 +56,113 @@
<blockquote>
<simpara>
ソースコードへのリンク
- <link xl:href="https://github.com/vim/vim/tree/8e6be34338f13a6a625f19bcef82019c9adc65f2">vim
- (調査時点での master branch)</link>
- <link xl:href="https://github.com/neovim/neovim/tree/71d4f5851f068eeb432af34850dddda8cc1c71e3">neovim
- (上に同じ)</link>
- </simpara>
-</blockquote>
-<section xml:id="_vim_のソースコード">
- <title>vim のソースコード</title>
- <simpara>
- 以下は、autocmd events
- の名前と内部で使われている整数値とのマッピングを定義している箇所である。見ての通り、上でエイリアスではないかと述べた3組には、それぞれ同じ内部値が使われている。
- </simpara>
- <simpara>
- <link xl:href="https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L85-L86">https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L85-L86</link>
- </simpara>
- <programlisting language="c" linenumbering="unnumbered">
- <![CDATA[
- {"BufAdd", EVENT_BUFADD},
- {"BufCreate", EVENT_BUFADD},
- ]]>
- </programlisting>
- <simpara>
- <link xl:href="https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L95-L97">https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L95-L97</link>
- </simpara>
- <programlisting language="c" linenumbering="unnumbered">
- <![CDATA[
- {"BufRead", EVENT_BUFREADPOST},
- {"BufReadCmd", EVENT_BUFREADCMD},
- {"BufReadPost", EVENT_BUFREADPOST},
- ]]>
- </programlisting>
- <simpara>
- <link xl:href="https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L103-L105">https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L103-L105</link>
- </simpara>
- <programlisting language="c" linenumbering="unnumbered">
- <![CDATA[
- {"BufWrite", EVENT_BUFWRITEPRE},
- {"BufWritePost", EVENT_BUFWRITEPOST},
- {"BufWritePre", EVENT_BUFWRITEPRE},
- ]]>
- </programlisting>
-</section>
-<section xml:id="_neovim_のソースコード">
- <title>neovim のソースコード</title>
- <simpara>
- neovim の場合でも同様のマッピングが定義されているが、こちらの場合は Lua
- で書かれている。以下にある通り、はっきり <literal>aliases</literal> と書かれている。
- </simpara>
- <simpara>
- <link xl:href="https://github.com/neovim/neovim/blob/71d4f5851f068eeb432af34850dddda8cc1c71e3/src/nvim/auevents.lua#L119-L124">https://github.com/neovim/neovim/blob/71d4f5851f068eeb432af34850dddda8cc1c71e3/src/nvim/auevents.lua#L119-L124</link>
- </simpara>
- <programlisting language="lua" linenumbering="unnumbered">
- <![CDATA[
- aliases = {
- BufCreate = 'BufAdd',
- BufRead = 'BufReadPost',
- BufWrite = 'BufWritePre',
- FileEncoding = 'EncodingChanged',
- },
- ]]>
- </programlisting>
- <simpara>
- ところで、上では取り上げなかった <literal>FileEncoding</literal> だが、これは
- <literal>:help FileEncoding</literal> にしっかりと書いてある。
- </simpara>
- <literallayout class="monospaced"> *FileEncoding*
- <![CDATA[
- FileEncoding Obsolete. It still works and is equivalent
- to |EncodingChanged|.
- ]]>
-</literallayout>
-</section>
-<section xml:id="_まとめ">
- <title>まとめ</title>
- <simpara>
- 記事タイトルについて言えば、どちらも変わらないので好きな方を使えばよい。あえて言えば、次のようになるだろう。
- </simpara>
- <itemizedlist>
- <listitem>
- <literal>BufAdd</literal>/<literal>BufCreate</literal>
- <itemizedlist>
- <listitem>→ <literal>BufCreate</literal> は歴史的な理由により ("for historic reasons") 存在しているため、新しい方 (<literal>BufAdd</literal>) を使う</listitem>
- </itemizedlist>
- </listitem>
- <listitem>
- <literal>BufRead</literal>/<literal>BufReadPost</literal>
- <itemizedlist>
- <listitem>→ <literal>BufReadPre</literal> との対称性のため、あるいは <literal>BufWritePost</literal> との対称性のため <literal>BufReadPost</literal> を使う</listitem>
- </itemizedlist>
- </listitem>
- <listitem>
- <literal>BufWrite</literal>/<literal>BufWritePre</literal>
- <itemizedlist>
- <listitem>→ <literal>BufWritePost</literal> との対称性のため、あるいは <literal>BufReadPre</literal> との対称性のため <literal>BufWritePre</literal> を使う</listitem>
- </itemizedlist>
- </listitem>
- <listitem>
- <literal>FileEncoding</literal>/<literal>EncodingChanged</literal>
- <itemizedlist>
- <listitem>→ <literal>FileEncoding</literal> は <literal>`Obsolete'' と明言されているので、`EncodingChanged</literal> を使う</listitem>
- </itemizedlist>
- </listitem>
- </itemizedlist>
- <simpara>
- ところでこの調査で知ったのだが、<literal>BufRead</literal> と <literal>BufWrite</literal>
- は上にある通り発火するタイミングが「後」と「前」で対称性がない。可能なら
- <literal>Pre</literal>/<literal>Post</literal> 付きのものを使った方が分かりやすいだろう。
- </simpara>
-</section>
-</section>
+ <link xl:href="https://github.com/vim/vim/tree/8e6be34338f13a6a625f19bcef82019c9adc65f2">vim (調査時点での master branch)</link>
+ <link xl:href="https://github.com/neovim/neovim/tree/71d4f5851f068eeb432af34850dddda8cc1c71e3">neovim (上に同じ)</link>
+ </simpara>
+ </blockquote>
+ <section xml:id="code-reading--vim">
+ <title>vim のソースコード</title>
+ <simpara>
+ 以下は、autocmd events
+ の名前と内部で使われている整数値とのマッピングを定義している箇所である。見ての通り、上でエイリアスではないかと述べた3組には、それぞれ同じ内部値が使われている。
+ </simpara>
+ <simpara>
+ <link xl:href="https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L85-L86">https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L85-L86</link>
+ </simpara>
+ <programlisting language="c" linenumbering="unnumbered">
+ <![CDATA[
+ {"BufAdd", EVENT_BUFADD},
+ {"BufCreate", EVENT_BUFADD},
+ ]]>
+ </programlisting>
+ <simpara>
+ <link xl:href="https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L95-L97">https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L95-L97</link>
+ </simpara>
+ <programlisting language="c" linenumbering="unnumbered">
+ <![CDATA[
+ {"BufRead", EVENT_BUFREADPOST},
+ {"BufReadCmd", EVENT_BUFREADCMD},
+ {"BufReadPost", EVENT_BUFREADPOST},
+ ]]>
+ </programlisting>
+ <simpara>
+ <link xl:href="https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L103-L105">https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L103-L105</link>
+ </simpara>
+ <programlisting language="c" linenumbering="unnumbered">
+ <![CDATA[
+ {"BufWrite", EVENT_BUFWRITEPRE},
+ {"BufWritePost", EVENT_BUFWRITEPOST},
+ {"BufWritePre", EVENT_BUFWRITEPRE},
+ ]]>
+ </programlisting>
+ </section>
+ <section xml:id="code-reading--neovim">
+ <title>neovim のソースコード</title>
+ <simpara>
+ neovim の場合でも同様のマッピングが定義されているが、こちらの場合は Lua
+ で書かれている。以下にある通り、はっきり <literal>aliases</literal> と書かれている。
+ </simpara>
+ <simpara>
+ <link xl:href="https://github.com/neovim/neovim/blob/71d4f5851f068eeb432af34850dddda8cc1c71e3/src/nvim/auevents.lua#L119-L124">https://github.com/neovim/neovim/blob/71d4f5851f068eeb432af34850dddda8cc1c71e3/src/nvim/auevents.lua#L119-L124</link>
+ </simpara>
+ <programlisting language="lua" linenumbering="unnumbered">
+ <![CDATA[
+ aliases = {
+ BufCreate = 'BufAdd',
+ BufRead = 'BufReadPost',
+ BufWrite = 'BufWritePre',
+ FileEncoding = 'EncodingChanged',
+ },
+ ]]>
+ </programlisting>
+ <simpara>
+ ところで、上では取り上げなかった <literal>FileEncoding</literal> だが、これは
+ <literal>:help FileEncoding</literal> にしっかりと書いてある。
+ </simpara>
+ <literallayout class="monospaced">
+ <![CDATA[
+ *FileEncoding*
+ FileEncoding Obsolete. It still works and is equivalent
+ to |EncodingChanged|.
+ ]]>
+ </literallayout>
+ </section>
+ </section>
+ <section xml:id="outro">
+ <title>まとめ</title>
+ <simpara>
+ 記事タイトルについて言えば、どちらも変わらないので好きな方を使えばよい。あえて言えば、次のようになるだろう。
+ </simpara>
+ <itemizedlist>
+ <listitem>
+ <literal>BufAdd</literal>/<literal>BufCreate</literal>
+ <itemizedlist>
+ <listitem>→ <literal>BufCreate</literal> は歴史的な理由により ("for historic reasons") 存在しているため、新しい方 (<literal>BufAdd</literal>) を使う</listitem>
+ </itemizedlist>
+ </listitem>
+ <listitem>
+ <literal>BufRead</literal>/<literal>BufReadPost</literal>
+ <itemizedlist>
+ <listitem>→ <literal>BufReadPre</literal> との対称性のため、あるいは <literal>BufWritePost</literal> との対称性のため <literal>BufReadPost</literal> を使う</listitem>
+ </itemizedlist>
+ </listitem>
+ <listitem>
+ <literal>BufWrite</literal>/<literal>BufWritePre</literal>
+ <itemizedlist>
+ <listitem>→ <literal>BufWritePost</literal> との対称性のため、あるいは <literal>BufReadPre</literal> との対称性のため <literal>BufWritePre</literal> を使う</listitem>
+ </itemizedlist>
+ </listitem>
+ <listitem>
+ <literal>FileEncoding</literal>/<literal>EncodingChanged</literal>
+ <itemizedlist>
+ <listitem>→ <literal>FileEncoding</literal> は <literal>`Obsolete'' と明言されているので、`EncodingChanged</literal> を使う</listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ <simpara>
+ ところでこの調査で知ったのだが、<literal>BufRead</literal> と <literal>BufWrite</literal>
+ は上にある通り発火するタイミングが「後」と「前」で対称性がない。可能なら
+ <literal>Pre</literal>/<literal>Post</literal> 付きのものを使った方が分かりやすいだろう。
+ </simpara>
+ </section>
</article>
diff --git a/content/posts/2021-10-02/vim-swap-order-of-selected-lines.xml b/content/posts/2021-10-02/vim-swap-order-of-selected-lines.xml
index f50a8a0..f919301 100644
--- a/content/posts/2021-10-02/vim-swap-order-of-selected-lines.xml
+++ b/content/posts/2021-10-02/vim-swap-order-of-selected-lines.xml
@@ -22,7 +22,19 @@
<simpara>
<hr/>
</simpara>
- <section xml:id="_バージョン情報">
+ <section xml:id="tl-dr">
+ <title>TL; DR</title>
+ <programlisting language="vim" linenumbering="unnumbered">
+ <![CDATA[
+ " License: Public Domain
+
+ command! -bar -range=%
+ \ Reverse
+ \ keeppatterns <line1>,<line2>g/^/m<line1>-1
+ ]]>
+ </programlisting>
+ </section>
+ <section xml:id="version">
<title>バージョン情報</title>
<simpara>
<literal>:version</literal> の一部
@@ -34,9 +46,9 @@
</simpara>
</blockquote>
</section>
- <section xml:id="_よく紹介されている手法">
+ <section xml:id="existing-solution">
<title>よく紹介されている手法</title>
- <section xml:id="_tac_tail">
+ <section xml:id="existing-solution--external-commands">
<title><literal>tac</literal> / <literal>tail</literal></title>
<simpara>
<literal>tac</literal> や <literal>tail -r</literal> などの外部コマンドを <literal>!</literal>
@@ -52,7 +64,7 @@
オプションは環境によって利用できないことがあり、複数の環境を行き来する場合に採用しづらい
</simpara>
</section>
- <section xml:id="_gm0">
+ <section xml:id="existing-solution--global-command">
<title><literal>:g/^/m0</literal></title>
<simpara>
こちらは外部コマンドに頼らず、Vim の機能のみを使う。<literal>g</literal> は <literal>:global</literal>
@@ -99,7 +111,7 @@
</simpara>
</section>
</section>
- <section xml:id="_gm0_の問題点">
+ <section xml:id="problem-of-global-command">
<title><literal>:g/^/m0</literal> の問題点</title>
<simpara>
<literal>:global</literal>
@@ -114,7 +126,7 @@
</simpara>
</blockquote>
</section>
- <section xml:id="_解決策">
+ <section xml:id="solution">
<title>解決策</title>
<blockquote>
<simpara>
@@ -177,7 +189,7 @@
の呼び出しをユーザー定義関数に切り出すことで上述の問題を解決できる。
</simpara>
</section>
- <section xml:id="_解決策_改訂版">
+ <section xml:id="solution-revised">
<title>解決策 (改訂版)</title>
<blockquote>
<simpara>
@@ -203,16 +215,4 @@
</simpara>
</blockquote>
</section>
- <section xml:id="_コピペ用再掲">
- <title>コピペ用再掲</title>
- <programlisting language="vim" linenumbering="unnumbered">
- <![CDATA[
- " License: Public Domain
-
- command! -bar -range=%
- \ Reverse
- \ keeppatterns <line1>,<line2>g/^/m<line1>-1
- ]]>
- </programlisting>
- </section>
</article>
diff --git a/content/posts/2022-04-09/phperkaigi-2022-tokens.xml b/content/posts/2022-04-09/phperkaigi-2022-tokens.xml
index e3d9c45..352eba0 100644
--- a/content/posts/2022-04-09/phperkaigi-2022-tokens.xml
+++ b/content/posts/2022-04-09/phperkaigi-2022-tokens.xml
@@ -33,7 +33,7 @@
リポジトリはこちら: <link xl:href="https://github.com/nsfisis/PHPerKaigi2022-tokens">https://github.com/nsfisis/PHPerKaigi2022-tokens</link>
</simpara>
</section>
- <section xml:id="_第1問_brainf_ck_php">
+ <section xml:id="q1-brainfuck">
<title>第1問 brainf_ck.php</title>
<simpara>
ソースコードはこちら。実行には PHP 8.1 以上が必要なので注意。
@@ -114,16 +114,16 @@
<simpara>
この問題は、単に適切なバージョンの PHP で動かせばトークンが得られる。
</simpara>
- <section xml:id="_解説">
+ <section xml:id="q1-brainfuck--commentary">
<title>解説</title>
- <section xml:id="_絵文字">
+ <section xml:id="q1-brainfuck--commentary--emoji">
<title>絵文字</title>
<simpara>
まず目につくのは大量の絵文字だろう。 PHP
は識別子に使用できる文字の範囲が広く、絵文字も使うことができる。
</simpara>
</section>
- <section xml:id="_プログラム全体">
+ <section xml:id="q1-brainfuck--commentary--brainfuck">
<title>プログラム全体</title>
<simpara>
Brainf*ck のインタプリタとプログラムになっている。 Brainf*ck
@@ -185,7 +185,7 @@
なお、<literal>$🐘</literal> はいわゆる main 関数であり、プログラムの実行部分である。
</simpara>
</section>
- <section xml:id="_絵文字の選択">
+ <section xml:id="q1-brainfuck--commentary--emoji-selection">
<title>絵文字の選択</title>
<simpara>
おおよそ意味に合致するよう選んでいるが、<literal>$🤡</literal> と <literal>$🎪</literal>
@@ -193,7 +193,7 @@
のマスコットの象に由来する。
</simpara>
</section>
- <section xml:id="_strict_types">
+ <section xml:id="q1-brainfuck--commentary--strict-types">
<title>strict_types</title>
<simpara>
<literal>declare</literal> 文の <literal>strict_types</literal> に指定できるのは、<literal>0</literal> か <literal>1</literal>
@@ -201,7 +201,7 @@
8.1 から追加された、<literal>0O</literal> または <literal>0o</literal> から始まる八進数リテラルを使った。
</simpara>
</section>
- <section xml:id="_url">
+ <section xml:id="q1-brainfuck--commentary--url">
<title>URL</title>
<simpara>
ソースコードのライセンスを示したこの部分だが、
@@ -216,7 +216,7 @@
以降は行コメントになっている。
</simpara>
</section>
- <section xml:id="_リテラルなしで数値を生成する">
+ <section xml:id="q1-brainfuck--commentary--numbers">
<title>リテラルなしで数値を生成する</title>
<simpara>
ソースコード中に、ほとんど数値リテラルが書かれていないことにお気づきだろうか。
@@ -245,7 +245,7 @@
にし、さらにビット反転して <literal>-1</literal> にしている。
</simpara>
</section>
- <section xml:id="_if_文なしで条件分岐">
+ <section xml:id="q1-brainfuck--commentary--conditionals">
<title><literal>if</literal> 文なしで条件分岐</title>
<simpara>
三項演算子ないし <literal>match</literal> 式を使うことで、<literal>if</literal>
@@ -254,7 +254,7 @@
のような形で分岐することもできる。
</simpara>
</section>
- <section xml:id="_whilefor_文なしでループ">
+ <section xml:id="q1-brainfuck--commentary--loops">
<title><literal>while</literal>、<literal>for</literal> 文なしでループ</title>
<simpara>
不動点コンビネータを使って無名再帰する
@@ -273,7 +273,7 @@
</section>
</section>
</section>
- <section xml:id="_第2問_riddle_php">
+ <section xml:id="q2-riddle">
<title>第2問 riddle.php</title>
<simpara>
ソースコードはこちら。実行には PHP 8.0 以上が必要なので注意。
@@ -324,7 +324,7 @@
<simpara>
ここでは、私の想定解を解説する。
</simpara>
- <section xml:id="_読解">
+ <section xml:id="q2-riddle--code-reading">
<title>読解</title>
<simpara>
まずはソースコードを読んでいく。
@@ -372,7 +372,7 @@
5文字ごとに区切ったあと、改行で結合している。
</simpara>
</section>
- <section xml:id="_ヒント">
+ <section xml:id="q2-riddle--hint">
<title>ヒント</title>
<simpara>
次に、ソースコードに書いてあるヒントを読んでいく。
@@ -390,7 +390,7 @@
ファイルに追加ヒントとして書かれている)。
</simpara>
</section>
- <section xml:id="_解く">
+ <section xml:id="q2-riddle--solve">
<title>解く</title>
<simpara>
ここまでわかれば、あと一歩で解ける。すなわち、<literal>0x14B499C</literal> が <literal>#</literal>
@@ -455,7 +455,7 @@
</simpara>
</section>
</section>
- <section xml:id="_第3問_toquine_php">
+ <section xml:id="q3-toquine">
<title>第3問 toquine.php</title>
<simpara>
ソースコードはこちら。
@@ -504,9 +504,9 @@
<simpara>
実際にはもう少しパイプで繋げなければならない。
</simpara>
- <section xml:id="_解説_2">
+ <section xml:id="q3-toquine--commentary">
<title>解説</title>
- <section xml:id="_プログラム全体_2">
+ <section xml:id="q3-toquine--commentary--quine">
<title>プログラム全体</title>
<simpara>
コメントにもあるとおり、これは quine (風) のプログラムになっている。
@@ -518,14 +518,14 @@
異なるのはトークンになっている部分のみである。
</simpara>
</section>
- <section xml:id="_トークン">
+ <section xml:id="q3-toquine--commentary--tokens">
<title>トークン</title>
<simpara>
<literal>$xs</literal> がトークンに対応している。変換のロジックは <literal>riddle.php</literal>
とほぼ同じなので省略する。
</simpara>
</section>
- <section xml:id="_状態保持">
+ <section xml:id="q3-toquine--commentary--states">
<title>状態保持</title>
<simpara>
トークンの何文字目まで出力したかを、ソースコードを変えずに (quine
@@ -534,7 +534,7 @@
から情報を取得している。
</simpara>
</section>
- <section xml:id="_rot_13">
+ <section xml:id="q3-toquine--commentary--rot-13">
<title>ROT 13</title>
<simpara>
Quine は、素朴に書くとプログラムの一部が 2回記述されてしまう。
diff --git a/content/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal.xml b/content/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal.xml
index f80a730..a98f94e 100644
--- a/content/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal.xml
+++ b/content/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal.xml
@@ -37,7 +37,7 @@
リポジトリはこちら: <link xl:href="https://github.com/nsfisis/term-banner">https://github.com/nsfisis/term-banner</link>
</simpara>
</section>
- <section xml:id="_motivation">
+ <section xml:id="motivation">
<title>Motivation</title>
<simpara>
以前、https://github.com/nsfisis/big-clock-mode[big-clock-mode]
@@ -64,7 +64,7 @@
まあ、作らなくても探せばあると思うが、作りたいものは作りたいので知ったことではない。
</simpara>
</section>
- <section xml:id="_プログラム">
+ <section xml:id="program">
<title>プログラム</title>
<simpara>
全体の流れは次のようになっている。
@@ -85,7 +85,7 @@
仕事ではスクリプト言語ばかり書いているが、やはりコンパイル言語はいい。
</simpara>
</section>
- <section xml:id="_フォント">
+ <section xml:id="font">
<title>フォント</title>
<simpara>
フリーの 8x8
diff --git a/content/posts/2022-05-01/phperkaigi-2022.xml b/content/posts/2022-05-01/phperkaigi-2022.xml
index 1290abd..621fcde 100644
--- a/content/posts/2022-05-01/phperkaigi-2022.xml
+++ b/content/posts/2022-05-01/phperkaigi-2022.xml
@@ -30,9 +30,9 @@
昨年のレポートは<link xl:href="/posts/2021-03-30/phperkaigi-2021">こちら</link>。
</simpara>
</section>
- <section xml:id="_感想">
+ <section xml:id="comments">
<title>感想</title>
- <section xml:id="_厳選おすすめトーク">
+ <section xml:id="comments--great-sessions">
<title>厳選おすすめトーク</title>
<simpara>
多くの素晴らしいトークの中から、特におすすめのものを
@@ -111,14 +111,14 @@
</simpara>
</blockquote>
</section>
- <section xml:id="_トークン問題の作成">
+ <section xml:id="comments--token-quizzes">
<title>トークン問題の作成</title>
<simpara>
今回は、PHPer チャレンジ用に弊社のトークン問題を
3題作成した。こちらについては<link xl:href="/posts/2022-04-09/phperkaigi-2022-tokens">別途記事にしている</link>ので、そちらを参照されたい。
</simpara>
</section>
- <section xml:id="_phper_チャレンジ">
+ <section xml:id="comments--phper-challenge">
<title>PHPer チャレンジ</title>
<simpara>
<link xl:href="https://fortee.jp/phperkaigi-2022/challenge">1位</link>になった。<br/>
@@ -126,7 +126,7 @@
をいただいた。
</simpara>
</section>
- <section xml:id="_カンファレンス全体への感想">
+ <section xml:id="comments--conference">
<title>カンファレンス全体への感想</title>
<simpara>
<link xl:href="/posts/2021-03-30/phperkaigi-2021">去年の参加レポ</link>
@@ -157,7 +157,7 @@
</simpara>
</section>
</section>
-<section xml:id="_そして来年へ">
+<section xml:id="next-year">
<title>そして来年へ……?</title>
<simpara>
PHPerKaigi 2023 があるかどうか存じ上げないが、あるとすれば、次の
diff --git a/content/posts/2022-08-27/php-conference-okinawa-code-golf.xml b/content/posts/2022-08-27/php-conference-okinawa-code-golf.xml
index 76fc041..581dcb4 100644
--- a/content/posts/2022-08-27/php-conference-okinawa-code-golf.xml
+++ b/content/posts/2022-08-27/php-conference-okinawa-code-golf.xml
@@ -33,7 +33,7 @@
<link xl:href="https://speakerdeck.com/memory1994/php-conference-okinawa-2022-extra?slide=3">https://speakerdeck.com/memory1994/php-conference-okinawa-2022-extra?slide=3</link>
</simpara>
</section>
- <section xml:id="_解">
+ <section xml:id="solution">
<title>解</title>
<simpara>
細かいレギュレーションは不明だったので、勝手に定めた。
@@ -74,9 +74,9 @@
]]>
</programlisting>
</section>
- <section xml:id="_使用したテクニック">
+ <section xml:id="techniques">
<title>使用したテクニック</title>
- <section xml:id="_指数表記">
+ <section xml:id="techniques--exponential-notation">
<title>指数表記</title>
<simpara>
割と多くの言語のゴルフで使えるテクニック。<literal>e</literal>
@@ -84,7 +84,7 @@
<literal>10000</literal>、<literal>5000</literal>、<literal>2000</literal>、<literal>1000</literal> を指数表記している。
</simpara>
</section>
- <section xml:id="_foreach_や_for_の中身を1つの文に">
+ <section xml:id="techniques--shorten-loop">
<title>foreach や for の中身を1つの文に</title>
<simpara>
<literal>foreach</literal>、<literal>for</literal>、<literal>if</literal> などの後ろには、通常 <literal>{</literal>
@@ -92,7 +92,7 @@
を省略できる。C言語などでも使える。
</simpara>
</section>
- <section xml:id="_r_に初期値を入れない">
+ <section xml:id="techniques--omit-initialization">
<title>$r に初期値を入れない</title>
<simpara>
PHP では、<literal>$r[] = &#8230;&#8203;</literal>
@@ -111,7 +111,7 @@
バイト縮む。
</simpara>
</section>
- <section xml:id="_php_タグの外に文字列を置く">
+ <section xml:id="techniques--put-text-outside-php-tag">
<title>PHP タグの外に文字列を置く</title>
<simpara>
PHP では、<literal>&lt;?php</literal> <literal>?&gt;</literal>
diff --git a/content/posts/2022-08-31/support-for-communty-is-employee-benefits.xml b/content/posts/2022-08-31/support-for-communty-is-employee-benefits.xml
index a28b96d..02fbe93 100644
--- a/content/posts/2022-08-31/support-for-communty-is-employee-benefits.xml
+++ b/content/posts/2022-08-31/support-for-communty-is-employee-benefits.xml
@@ -30,7 +30,7 @@
本件を社内でしつこく推進した1人として、推進の理由等を書き残しておきます。
</simpara>
</section>
-<section xml:id="_なぜ">
+<section xml:id="why">
<title>なぜ?</title>
<simpara>
組織としての寄付理由は前掲した記事に譲るとして、ここでは、私が社内でこの件を推進した理由について書くことにします。
diff --git a/content/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line.xml b/content/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line.xml
index d39526a..d828554 100644
--- a/content/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line.xml
+++ b/content/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line.xml
@@ -19,7 +19,7 @@
</revision>
</revhistory>
</info>
- <section xml:id="_記事の構成について">
+ <section xml:id="intro">
<title>記事の構成について</title>
<simpara>
この記事は、普通の fizzbuzz
@@ -28,7 +28,7 @@
にソースコードがあるので、そちらを先に見てほしい。
</simpara>
</section>
- <section xml:id="_レギュレーション">
+ <section xml:id="regulations">
<title>レギュレーション</title>
<simpara>
PHP で、次のような制約の下に fizzbuzz を書いた。
@@ -62,7 +62,7 @@
off になっている環境が多いようなので、今回は使わないことにした。
</simpara>
</section>
- <section xml:id="_主な障害">
+ <section xml:id="problems">
<title>主な障害</title>
<simpara>
1行あたりの文字数など、適当に改行を挟めばいいだけではないのか?
@@ -182,541 +182,540 @@
</simpara>
<blockquote>
<itemizedlist>
- <listitem>標準的なインストール構成の PHP で実現できること (デフォルトで有効になっていない拡張等を使わないこと)
- </listitem>
- </itemizedlist>
- </blockquote>
- <simpara>
- に反する
- (というより、「それだとおもしろくもなんともないので、このルールを足した」というのが正しい)。
- </simpara>
- <simpara>
- また、2文字だと文字列がまともに書けないのも辛い。<literal>''</literal> だけで
- 2文字使うので、「1文字の文字列リテラル」というものを書くことができない。PHP
- では文字列リテラル中に生の改行が書けるので
- </simpara>
- <programlisting language="php" linenumbering="unnumbered">
- <![CDATA[
- $a
- ='
- a'
- ;;
- ]]>
- </programlisting>
- <simpara>
- とすると <literal>$a</literal> は <literal>"\na"</literal> になるのだが、余計な改行が入ってしまう。
- </simpara>
- <simpara>
- これらの障害をどのように乗り越えるのか、次節から見ていく。
- </simpara>
-</section>
-<section xml:id="_解説">
- <title>解説</title>
- <section xml:id="_普通の_fizzbuzz">
- <title>普通の (?) fizzbuzz</title>
+ <listitem>標準的なインストール構成の PHP で実現できること (デフォルトで有効になっていない拡張等を使わないこと)</listitem>
+ </itemizedlist>
+ </blockquote>
<simpara>
- まずは普通に書くとしよう。
+ に反する
+ (というより、「それだとおもしろくもなんともないので、このルールを足した」というのが正しい)。
+ </simpara>
+ <simpara>
+ また、2文字だと文字列がまともに書けないのも辛い。<literal>''</literal> だけで
+ 2文字使うので、「1文字の文字列リテラル」というものを書くことができない。PHP
+ では文字列リテラル中に生の改行が書けるので
</simpara>
<programlisting language="php" linenumbering="unnumbered">
<![CDATA[
- <?php
-
- for ($i = 1; $i < 100; $i++) {
- echo (($i % 3 ? '' : 'Fizz') . ($i % 5 ? '' : 'Buzz') ?: $i) . "\n";
- }
+ $a
+ ='
+ a'
+ ;;
]]>
</programlisting>
<simpara>
- 素直に書いた fizzbuzz
- とは言い難いが、このくらいは普通だということにしておかないと、この先がやっていられないので許してほしい。
+ とすると <literal>$a</literal> は <literal>"\na"</literal> になるのだが、余計な改行が入ってしまう。
</simpara>
- </section>
- <section xml:id="_for_の排除">
- <title><literal>for</literal> の排除</title>
<simpara>
- <literal>for</literal>
- は、3文字もある長いキーワードである。こんなものは使えない。<literal>array_</literal>
- 系の関数を使って、適当に置き換えるとしよう。
+ これらの障害をどのように乗り越えるのか、次節から見ていく。
</simpara>
- <programlisting language="php" linenumbering="unnumbered">
- <![CDATA[
- <?php
+ </section>
+ <section xml:id="commentary">
+ <title>解説</title>
+ <section xml:id="commentary--normal-fizzbuzz">
+ <title>普通の (?) fizzbuzz</title>
+ <simpara>
+ まずは普通に書くとしよう。
+ </simpara>
+ <programlisting language="php" linenumbering="unnumbered">
+ <![CDATA[
+ <?php
- $s = range(1, 100);
- array_walk(
+ for ($i = 1; $i < 100; $i++) {
+ echo (($i % 3 ? '' : 'Fizz') . ($i % 5 ? '' : 'Buzz') ?: $i) . "\n";
+ }
+ ]]>
+ </programlisting>
+ <simpara>
+ 素直に書いた fizzbuzz
+ とは言い難いが、このくらいは普通だということにしておかないと、この先がやっていられないので許してほしい。
+ </simpara>
+ </section>
+ <section xml:id="commentary--remove-keywords">
+ <title><literal>for</literal> の排除</title>
+ <simpara>
+ <literal>for</literal>
+ は、3文字もある長いキーワードである。こんなものは使えない。<literal>array_</literal>
+ 系の関数を使って、適当に置き換えるとしよう。
+ </simpara>
+ <programlisting language="php" linenumbering="unnumbered">
+ <![CDATA[
+ <?php
+
+ $s = range(1, 100);
+ array_walk(
$s,
fn($i) =>
- printf((($i % 3 ? '' : 'Fizz') . ($i % 5 ? '' : 'Buzz') ?: $i) . "\n"),
- );
- ]]>
- </programlisting>
- <simpara>
- <literal>array_walk</literal> や <literal>range</literal>、<literal>printf</literal> といった <literal>for</literal>
- よりも長いトークンが現れてしまったが、これは次節で直すことにする。なお、<literal>echo</literal>
- は文 (statement) であり式 (expression) ではないので、式である <literal>printf</literal>
- に置き換えた。
- </simpara>
+ printf((($i % 3 ? '' : 'Fizz') . ($i % 5 ? '' : 'Buzz') ?: $i) . "\n"),
+ );
+ ]]>
+ </programlisting>
+ <simpara>
+ <literal>array_walk</literal> や <literal>range</literal>、<literal>printf</literal> といった <literal>for</literal>
+ よりも長いトークンが現れてしまったが、これは次節で直すことにする。なお、<literal>echo</literal>
+ は文 (statement) であり式 (expression) ではないので、式である <literal>printf</literal>
+ に置き換えた。
+ </simpara>
+ </section>
+ <section xml:id="commentary--shorten-function-invocation">
+ <title>関数呼び出しの短縮</title>
+ <simpara>
+ <literal>range</literal>、<literal>array_walk</literal>、<literal>printf</literal>
+ は長すぎるのでどうにかせねばならない。ここで、PHP
+ の可変関数を使う。可変関数とは、関数名が文字列として入った変数を経由して、関数を呼び出す機能である。
+ </simpara>
+ <programlisting language="php" linenumbering="unnumbered">
+ <![CDATA[
+ <?php
+
+ $r = 'range';
+ $w = 'array_walk';
+ $p = 'printf';
+
+ $s = $r(1, 100);
+ $w(
+ $s,
+ fn($i) =>
+ $p((($i % 3 ? '' : 'Fizz') . ($i % 5 ? '' : 'Buzz') ?: $i) . "\n"),
+ );
+ ]]>
+ </programlisting>
+ <simpara>
+ これで関数を呼び出している所は短くなった。では、<literal>$r</literal> や <literal>$w</literal> や
+ <literal>$p</literal>、また <literal>'Fizz'</literal> や <literal>'Buzz'</literal> はどうやって
+ 1行2文字に収めるのか。次のテクニックへ移ろう。
+ </simpara>
+ </section>
+ <section xml:id="commentary--incompatible-solution">
+ <title>余談: PHP 8.x で動作しなくてもいいなら</title>
+ <simpara>
+ 今回使ったテクニックを説明する前に、余談として、文字列リテラルの短縮法として今回採用しなかったものを紹介する。
+ </simpara>
+ <blockquote>
+ <itemizedlist>
+ <listitem>PHP 7.4〜8.1 で動作すること</listitem>
+ </itemizedlist>
+ </blockquote>
+ <simpara>
+ というルールがない場合、「未定義の定数が評価された場合、その定数の名前が値になる」という
+ PHP 7.x までの仕様が利用できる。例えば、 <literal>Fizz</literal>
+ という文字列が欲しければ、次のようにする。
+ </simpara>
+ <programlisting language="php" linenumbering="unnumbered">
+ <![CDATA[
+ $f
+ =F
+ .i
+ .z
+ .z
+ ;;
+ ]]>
+ </programlisting>
+ <simpara>
+ こうして簡単に文字列を作れる。なお、この仕様は 7.x
+ 時点でも警告を受けるので、<literal>@</literal> 演算子を使って抑制してやるとよい。
+ </simpara>
+ <programlisting language="php" linenumbering="unnumbered">
+ <![CDATA[
+ $f
+ =@
+ F.
+ @i
+ .#
+ @z
+ .#
+ @z
+ ;;
+ ]]>
+ </programlisting>
+ <simpara>
+ むしろ、このことがわかっていたからこそ PHP 8.x
+ での動作を要件に課したところがある。
+ </simpara>
+ </section>
+ <section xml:id="commentary--shorten-string-literals">
+ <title>文字列リテラルの短縮</title>
+ <simpara>
+ 実際に使った手法の説明に移る。
+ </simpara>
+ <simpara>
+ ずばり、文字列同士のビット演算を使う。PHP では、文字列同士でビット演算
+ (<literal>&amp;</literal>、<literal>|</literal>、<literal>^</literal>)
+ をした場合、文字列の各バイトごとに指定したビット演算がなされ、それを結合したものが演算結果となる。
+ </simpara>
+ <programlisting language="php" linenumbering="unnumbered">
+ <![CDATA[
+ $a = "12345";
+ $b = "world";
+
+ // $a ^ $b は次のコードと同じ
+ $result = '';
+ for ($i = 0; $i < min(strlen($a), strlen($b)); $i++) {
+ $result .= $a[$i] ^ $b[$i];
+ }
+
+ echo $result;
+ // => F]AXQ
+ ]]>
+ </programlisting>
+ <simpara>
+ これを踏まえ、次のコードを見てみよう。
+ </simpara>
+ <programlisting language="php" linenumbering="unnumbered">
+ <![CDATA[
+ $x = "x\nOm\n";
+ $y = "\nk!\no";
+ $r = $x ^ $y;
+ echo "$r\n";
+ ]]>
+ </programlisting>
+ <simpara>
+ 実行すると、<literal>range</literal> が表示される。さて、PHP
+ では文字列リテラル中に生の改行を直接書いてもよいのだった
+ (「主な障害」の節を参照のこと)。書きかえてみよう。
+ </simpara>
+ <programlisting language="php" linenumbering="unnumbered">
+ <![CDATA[
+ $x
+ ='x
+ Om
+ ';
+ $y
+ ='
+ k!
+ o'
+ ;
+
+ $r = $x ^ $y;
+ echo "$r\n";
+ ]]>
+ </programlisting>
+ <simpara>
+ さらに <literal>#</literal> を使って適当に調整すると、次のようになる。
+ </simpara>
+ <programlisting language="php" linenumbering="unnumbered">
+ <![CDATA[
+ $x
+ =#
+ 'x
+ Om
+ ';
+ $y
+ ='
+ k!
+ o'
+ ;#
+ $r
+ =#
+ $x
+ ^#
+ $y
+ ;#
+
+ echo "$r\n";
+ ]]>
+ </programlisting>
+ <simpara>
+ 1行あたり2文字で、<literal>range</literal>
+ という文字列を生成することに成功した。他の必要な文字列にも、同様の処理をほどこす。
+ </simpara>
+ <simpara>
+ 備考: <literal>Buzz</literal> 中にある小文字の <literal>u</literal> は、このロジックだと non-printable
+ な文字になってしまう。ここまでのテクニックを駆使すれば回避するのはそう難しくないので、考えてみてほしい。
+ </simpara>
+ </section>
</section>
- <section xml:id="_関数呼び出しの短縮">
- <title>関数呼び出しの短縮</title>
+ <section xml:id="stretched-fizzbuzz">
+ <title>完成系</title>
<simpara>
- <literal>range</literal>、<literal>array_walk</literal>、<literal>printf</literal>
- は長すぎるのでどうにかせねばならない。ここで、PHP
- の可変関数を使う。可変関数とは、関数名が文字列として入った変数を経由して、関数を呼び出す機能である。
+ 完成したものがこちら。
</simpara>
<programlisting language="php" linenumbering="unnumbered">
<![CDATA[
<?php
- $r = 'range';
- $w = 'array_walk';
- $p = 'printf';
-
- $s = $r(1, 100);
- $w(
- $s,
- fn($i) =>
- $p((($i % 3 ? '' : 'Fizz') . ($i % 5 ? '' : 'Buzz') ?: $i) . "\n"),
+ $x
+ =#
+ 'i
+ S'
+ ;;
+ $y
+ ='
+ b!
+ ';
+ $c
+ =#
+ $x
+ ^#
+ $y
+ ;#
+ $x
+ =#
+ 'x
+ Om
+ ';
+ $y
+ ='
+ k!
+ o'
+ ;#
+ $r
+ =#
+ $x
+ ^#
+ $y
+ ;#
+ $x
+ =#
+ 'k
+ Sk
+ ~}
+ Ma
+ ';
+ $y
+ ='
+ x!
+ s!
+ k!
+ ';
+ $w
+ =#
+ $x
+ ^#
+ $y
+ ;#
+ $x
+ =#
+ 'z
+ Hd
+ G'
+ ;#
+ $y
+ ='
+ x!
+ ~!
+ ';
+ $p
+ =#
+ $x
+ ^#
+ $y
+ ;#
+ $x
+ =#
+ 'L
+ [p
+ ';
+ $y
+ ='
+ c!
+ ';
+ $f
+ =#
+ $x
+ ^#
+ $y
+ ;#
+ $x
+ =#
+ 'H
+ [p
+ ';
+ $y
+ ='
+ _!
+ ';
+ $b
+ =#
+ $x
+ ^#
+ $y
+ ;#
+ $b
+ [1
+ ]=
+ $c
+ (#
+ 13
+ *9
+ );
+ $s
+ =#
+ $r
+ (1
+ ,(
+ 10
+ **
+ 2)
+ );
+ $w
+ (#
+ $s
+ ,#
+ fn
+ (#
+ $i
+ )#
+ =>
+ $p
+ ((
+ (#
+ $i
+ %3
+ ?#
+ ''
+ :#
+ $f
+ ).
+ (#
+ $i
+ %5
+ ?#
+ ''
+ :#
+ $b
+ )?
+ :#
+ $i
+ )#
+ .'
+ ')
);
]]>
</programlisting>
+ </section>
+ <section xml:id="outro">
+ <title>感想など</title>
<simpara>
- これで関数を呼び出している所は短くなった。では、<literal>$r</literal> や <literal>$w</literal> や
- <literal>$p</literal>、また <literal>'Fizz'</literal> や <literal>'Buzz'</literal> はどうやって
- 1行2文字に収めるのか。次のテクニックへ移ろう。
+ PHP は、スクリプト言語の中だとシンタックスシュガーが少ない
+ (体感)。この挑戦は不可能に思われたが、PHP
+ マニュアルとにらめっこしていたらなんとかなった。
</simpara>
- </section>
- <section xml:id="_余談_php_8_x_で動作しなくてもいいなら">
- <title>余談: PHP 8.x で動作しなくてもいいなら</title>
<simpara>
- 今回使ったテクニックを説明する前に、余談として、文字列リテラルの短縮法として今回採用しなかったものを紹介する。
+ みんなもプログラムを細長くしよう。
</simpara>
- <blockquote>
- <itemizedlist>
- <listitem>PHP 7.4〜8.1 で動作すること</listitem>
- </itemizedlist>
- </blockquote>
+ </section>
+ <section xml:id="alternative-solution">
+ <title>余談2: 別解</title>
<simpara>
- というルールがない場合、「未定義の定数が評価された場合、その定数の名前が値になる」という
- PHP 7.x までの仕様が利用できる。例えば、 <literal>Fizz</literal>
- という文字列が欲しければ、次のようにする。
+ PHP では、バッククォートを使ってシェルを呼び出せる。これは <literal>shell_exec</literal>
+ 関数と等価である。さて、PHP
+ ではバックスラッシュによる行継続が使えないと書いたが、シェルでは使える
+ (当然だが、呼び出されるシェルに依存する。Bash
+ なら大丈夫だろう。知らんけど)。
</simpara>
<programlisting language="php" linenumbering="unnumbered">
<![CDATA[
- $f
- =F
- .i
- .z
- .z
- ;;
+ <?php
+
+ printf(`
+ e\
+ c\
+ h\
+ o\
+ \
+ 1\
+ 2\
+ 3\
+ `);
]]>
</programlisting>
<simpara>
- こうして簡単に文字列を作れる。なお、この仕様は 7.x
- 時点でも警告を受けるので、<literal>@</literal> 演算子を使って抑制してやるとよい。
+ なお、ここでは簡単のため出力に <literal>printf</literal> をそのまま使っているが、実際には
+ <literal>printf</literal> という文字列を合成して可変関数で呼び出す。
</simpara>
- <programlisting language="php" linenumbering="unnumbered">
- <![CDATA[
- $f
- =@
- F.
- @i
- .#
- @z
- .#
- @z
- ;;
- ]]>
- </programlisting>
<simpara>
- むしろ、このことがわかっていたからこそ PHP 8.x
- での動作を要件に課したところがある。
+ ただし、これでは
</simpara>
- </section>
- <section xml:id="_文字列リテラルの短縮">
- <title>文字列リテラルの短縮</title>
+ <blockquote>
+ <itemizedlist>
+ <listitem>スペースやタブを使用しないこと</listitem>
+ </itemizedlist>
+ </blockquote>
<simpara>
- 実際に使った手法の説明に移る。
+ に違反してしまう。スペースが使えないと引数とコマンドを区切れない。これは困った。
</simpara>
<simpara>
- ずばり、文字列同士のビット演算を使う。PHP では、文字列同士でビット演算
- (<literal>&amp;</literal>、<literal>|</literal>、<literal>^</literal>)
- をした場合、文字列の各バイトごとに指定したビット演算がなされ、それを結合したものが演算結果となる。
+ もうこれ以上は不可能だと思っていたのだが、この記事の執筆中に解決する方法を思いついたので載せておく。
</simpara>
<programlisting language="php" linenumbering="unnumbered">
<![CDATA[
- $a = "12345";
- $b = "world";
+ <?php
- // $a ^ $b は次のコードと同じ
- $result = '';
- for ($i = 0; $i < min(strlen($a), strlen($b)); $i++) {
- $result .= $a[$i] ^ $b[$i];
- }
+ $c = 'chr';
+
+ ${
+ '_
+ '}
+ =#
+ $c
+ (#
+ 32
+ ).
+ $c
+ (#
+ 92
+ );
- echo $result;
- // => F]AXQ
+ printf(`
+ e\
+ c\
+ h\
+ o\
+ ${
+ '_
+ '}
+ 1\
+ 2\
+ 3\
+ `);
]]>
</programlisting>
<simpara>
- これを踏まえ、次のコードを見てみよう。
+ 先程と同じく、<literal>chr</literal> や <literal>printf</literal> を生成する部分は長くなるので省いた。
</simpara>
- <programlisting language="php" linenumbering="unnumbered">
+ <literallayout class="monospaced">
<![CDATA[
- $x = "x\nOm\n";
- $y = "\nk!\no";
- $r = $x ^ $y;
- echo "$r\n";
+ ${
+ '_
+ '}
]]>
- </programlisting>
+ </literallayout>
<simpara>
- 実行すると、<literal>range</literal> が表示される。さて、PHP
- では文字列リテラル中に生の改行を直接書いてもよいのだった
- (「主な障害」の節を参照のこと)。書きかえてみよう。
+ は変数で、中にはスペースとエスケープが入っている
+ (<literal>chr(32) . chr(92)</literal>)。シェルに渡されている文字列は次のようになる。
</simpara>
- <programlisting language="php" linenumbering="unnumbered">
+ <literallayout class="monospaced">
<![CDATA[
- $x
- ='x
- Om
- ';
- $y
- ='
- k!
- o'
- ;
-
- $r = $x ^ $y;
- echo "$r\n";
+ e\
+ c\
+ h\
+ o\
+ \
+ 1\
+ 2\
+ 3\
]]>
- </programlisting>
+ </literallayout>
<simpara>
- さらに <literal>#</literal> を使って適当に調整すると、次のようになる。
+ これは、前掲したコマンドと同じだ。かくして、スペースを陽に書かずにシェルをおおよそ自由に扱えるようになった。Fizzbuzz
+ のワンライナーくらいすぐ書けるだろうから、あとはなんとかなるだろう
+ (試してないけど)。
</simpara>
- <programlisting language="php" linenumbering="unnumbered">
- <![CDATA[
- $x
- =#
- 'x
- Om
- ';
- $y
- ='
- k!
- o'
- ;#
- $r
- =#
- $x
- ^#
- $y
- ;#
-
- echo "$r\n";
- ]]>
- </programlisting>
<simpara>
- 1行あたり2文字で、<literal>range</literal>
- という文字列を生成することに成功した。他の必要な文字列にも、同様の処理をほどこす。
+ ということでこれは別解ということにしておく。
</simpara>
<simpara>
- 備考: <literal>Buzz</literal> 中にある小文字の <literal>u</literal> は、このロジックだと non-printable
- な文字になってしまう。ここまでのテクニックを駆使すれば回避するのはそう難しくないので、考えてみてほしい。
+ ちなみに、PHP 8.2 からは、この記法で Warning が出るようになるようだ。
+ </simpara>
+ <literallayout class="monospaced">
+ <![CDATA[
+ ${
+ '_
+ '}
+ ]]>
+ </literallayout>
+ <simpara>
+ 最新版で警告が出るというのも美しくないので、私としては本編の解法を推す。
</simpara>
</section>
-</section>
-<section xml:id="_完成系">
- <title>完成系</title>
- <simpara>
- 完成したものがこちら。
- </simpara>
- <programlisting language="php" linenumbering="unnumbered">
- <![CDATA[
- <?php
-
- $x
- =#
- 'i
- S'
- ;;
- $y
- ='
- b!
- ';
- $c
- =#
- $x
- ^#
- $y
- ;#
- $x
- =#
- 'x
- Om
- ';
- $y
- ='
- k!
- o'
- ;#
- $r
- =#
- $x
- ^#
- $y
- ;#
- $x
- =#
- 'k
- Sk
- ~}
- Ma
- ';
- $y
- ='
- x!
- s!
- k!
- ';
- $w
- =#
- $x
- ^#
- $y
- ;#
- $x
- =#
- 'z
- Hd
- G'
- ;#
- $y
- ='
- x!
- ~!
- ';
- $p
- =#
- $x
- ^#
- $y
- ;#
- $x
- =#
- 'L
- [p
- ';
- $y
- ='
- c!
- ';
- $f
- =#
- $x
- ^#
- $y
- ;#
- $x
- =#
- 'H
- [p
- ';
- $y
- ='
- _!
- ';
- $b
- =#
- $x
- ^#
- $y
- ;#
- $b
- [1
- ]=
- $c
- (#
- 13
- *9
- );
- $s
- =#
- $r
- (1
- ,(
- 10
- **
- 2)
- );
- $w
- (#
- $s
- ,#
- fn
- (#
- $i
- )#
- =>
- $p
- ((
- (#
- $i
- %3
- ?#
- ''
- :#
- $f
- ).
- (#
- $i
- %5
- ?#
- ''
- :#
- $b
- )?
- :#
- $i
- )#
- .'
- ')
- );
- ]]>
- </programlisting>
-</section>
-<section xml:id="_感想など">
- <title>感想など</title>
- <simpara>
- PHP は、スクリプト言語の中だとシンタックスシュガーが少ない
- (体感)。この挑戦は不可能に思われたが、PHP
- マニュアルとにらめっこしていたらなんとかなった。
- </simpara>
- <simpara>
- みんなもプログラムを細長くしよう。
- </simpara>
-</section>
-<section xml:id="_余談2_別解">
- <title>余談2: 別解</title>
- <simpara>
- PHP では、バッククォートを使ってシェルを呼び出せる。これは <literal>shell_exec</literal>
- 関数と等価である。さて、PHP
- ではバックスラッシュによる行継続が使えないと書いたが、シェルでは使える
- (当然だが、呼び出されるシェルに依存する。Bash
- なら大丈夫だろう。知らんけど)。
- </simpara>
- <programlisting language="php" linenumbering="unnumbered">
- <![CDATA[
- <?php
-
- printf(`
- e\
- c\
- h\
- o\
- \
- 1\
- 2\
- 3\
- `);
- ]]>
- </programlisting>
- <simpara>
- なお、ここでは簡単のため出力に <literal>printf</literal> をそのまま使っているが、実際には
- <literal>printf</literal> という文字列を合成して可変関数で呼び出す。
- </simpara>
- <simpara>
- ただし、これでは
- </simpara>
- <blockquote>
- <itemizedlist>
- <listitem>スペースやタブを使用しないこと</listitem>
- </itemizedlist>
- </blockquote>
- <simpara>
- に違反してしまう。スペースが使えないと引数とコマンドを区切れない。これは困った。
- </simpara>
- <simpara>
- もうこれ以上は不可能だと思っていたのだが、この記事の執筆中に解決する方法を思いついたので載せておく。
- </simpara>
- <programlisting language="php" linenumbering="unnumbered">
- <![CDATA[
- <?php
-
- $c = 'chr';
-
- ${
- '_
- '}
- =#
- $c
- (#
- 32
- ).
- $c
- (#
- 92
- );
-
- printf(`
- e\
- c\
- h\
- o\
- ${
- '_
- '}
- 1\
- 2\
- 3\
- `);
- ]]>
- </programlisting>
- <simpara>
- 先程と同じく、<literal>chr</literal> や <literal>printf</literal> を生成する部分は長くなるので省いた。
- </simpara>
- <literallayout class="monospaced">
- <![CDATA[
- ${
- '_
- '}
- ]]>
- </literallayout>
- <simpara>
- は変数で、中にはスペースとエスケープが入っている
- (<literal>chr(32) . chr(92)</literal>)。シェルに渡されている文字列は次のようになる。
- </simpara>
- <literallayout class="monospaced">
- <![CDATA[
- e\
- c\
- h\
- o\
- \
- 1\
- 2\
- 3\
- ]]>
- </literallayout>
- <simpara>
- これは、前掲したコマンドと同じだ。かくして、スペースを陽に書かずにシェルをおおよそ自由に扱えるようになった。Fizzbuzz
- のワンライナーくらいすぐ書けるだろうから、あとはなんとかなるだろう
- (試してないけど)。
- </simpara>
- <simpara>
- ということでこれは別解ということにしておく。
- </simpara>
- <simpara>
- ちなみに、PHP 8.2 からは、この記法で Warning が出るようになるようだ。
- </simpara>
- <literallayout class="monospaced">
- <![CDATA[
- ${
- '_
- '}
- ]]>
- </literallayout>
- <simpara>
- 最新版で警告が出るというのも美しくないので、私としては本編の解法を推す。
- </simpara>
-</section>
</article>