tag:blogger.com,1999:blog-91971152024-09-17T09:33:07.666+09:00k16's noteShikano Keiichiro (k16) →
<a href="http://twitter.com/golden_lucky">twitter</a> & <a href="https://github.com/k16shikano">github</a> & <a href="http://note.golden-lucky.net/2015/09/blog-post.html">経歴</a> & <a href="http://www.flickr.com/photos/k16/">flickr</a>
k16http://www.blogger.com/profile/02349067627444091120[email protected]Blogger650125tag:blogger.com,1999:blog-9197115.post-29953397134065762012018-10-25T14:41:00.000+09:002018-10-25T18:45:03.836+09:00書籍『ゼロから創る暗号通貨』をどう読むか<p><a href="https://peaks.cc/golden_lucky/cryptocurrency">濵津誠 著『ゼロから創る暗号通貨』(2018年10月、PEAKS発行)</a>の編集をお手伝いしました。この本はどんな本かというと……</p>
<ul>
<li><b>土台となるP2Pネットワークから暗号通貨を自前で作ってみることで、ブロックチェーンを応用したまったく新しいサービスと未来を創るところまで意識できる本</b></li>
<li><b>著者の濵津さん自身が教師役となり、ブロックチェーンの「うさんくさくない」部分の全体がわかるように、読者をひっぱっていってくれる本</b></li>
</ul>
<p>要するに、ブロックチェーンの技術を通して、濵津さんという凄腕技術者が読者のメンターになってくれる本です。これまでクラウドファンディングで出資者しか読めなかったのが、今日から一般にも購入できるようになりました!</p>
<div class="peaks_widget" style="overflow:hidden; padding:20px; border:2px solid #ccc;"><div class="peaks_widget__image" style="float:left; margin-right:15px; line-height:0;"><a target="_blank" id="purchase" href="https://peaks.cc/golden_lucky/cryptocurrency"><img alt="ゼロから創る暗号通貨" style="border:none; max-width:140px;" src="https://s3-ap-northeast-1.amazonaws.com/peaks-images/project004_cover.jpg"></a></div><div class="peaks_widget__info"><p style="margin:0 0 3px 0; font-size:110%; font-weight:bold;"><a target="_blank" id="purchase" href="http://peaks.cc/golden_lucky/cryptocurrency">ゼロから創る暗号通貨</a></p><ul style="margin:0; padding:0;">
<li style="font-size:90%; list-style:none;"><span>著者:</span>
<span>濵津 誠,</span></li>
<li style="font-size:90%; list-style:none;">製本版,電子版</li>
<li style="font-size:90%; list-style:none;"><a target="_blank" id="purchase" style="text-decoration:underline; color:#1DA1F2;" href="http://peaks.cc/golden_lucky/cryptocurrency">PEAKSで購入する</a></li></ul></div></div>
<p>以下は、個人的な回想と、本書でぼくが何をしたかの舞台裏。</p>
<p>
暗号通貨についてざっくりと知りたいなと思って、<a href="https://www.google.co.jp/search?q=%E6%9A%97%E5%8F%B7%E9%80%9A%E8%B2%A8">「暗号通貨」で検索</a>してみると、投資して儲けたい人向けの記事と、通貨としての側面について考察する社会派な記事ばかりがトップに並びます。この結果だけ見ると、<b>だいぶうさんくさい</b>。でも、暗号通貨というかブロックチェーンって技術的には面白そうなトピックだし、キャッチアップはしておきたいな。
</p>
<p>
というわけで、その昔、<a href="https://bitcoin.org/bitcoin.pdf">サトシ・ナカモトの原論文<small>(PDF)</small></a>とされているものを斜めに眺めてみたことがあります。以下、たぶんそのころにぼくが感じたであろうこと。
</p>
<blockquote>
どうやら、ビットコインにおける「コイン」とは、取引の記録をつなげたものらしい。
ということは、そのコインが使われた取引の記録を、そのままコインとして使おうという発想か。
で、この論文の冒頭にあるのが、取引の連鎖としてのコインの構成図というわけね。
ブロック暗号化方式におけるブロックチェーンみたいだな、ああ、それで「ブロックチェーン」っていうのか。
しかし、原論文でその図が出てくるところには、「We define an electronic coin a chain of digital signatures」<small>(電子コインとは、ディジタル署名の連鎖のことである)</small>と書いてあるぞ。
このディジタル署名で、コインを使った人を特定しようというのだろうか。
分散されたタイムスタンプサーバで「Proof of Work」を計算し、その「証拠」をブロックに埋めることで、CPUパワーに基いた安全な取引が実現する?
何をいってるのかさっぱりわからないぞ。
ブロックの図の中に出てくる「nonce」が「証拠」のことなのかな……。
</blockquote>
<p>
論文だからしょうがないかもなんだけど、だいたいこんな感じで、半分くらい読んだところで放置してました。こんな「ふわふわ」した概念を具体的にどうやって「通貨」として使えるように実装できるのか、そもそも、この論文のどのへんが画期的なのか、まったく想像つかないぞ!
</p>
<p>
<a href="https://twitter.com/7gano">PEAKSの永野さん</a>から「暗号通貨の本をクラウドファンディングで出すことになったので編集を手伝ってほしい」という相談を受けたのは、そんなときのことでした<small>(うそです、実際に論文を読んでみたのは4-5年前のこと)</small>。
</p>
<p>
<a href="https://peaks.cc/">PEAKS</a>については、<a href="https://www.lambdanote.com/products/ipv6">『プロフェッショナルIPv6』</a>と同時期にクラウドファンディングの技術書を始めた<small>(<b>シンクロ</b>改行<b>ニシティ</b>)</small>というくらいの情報しか持っておらず、ただiOSとかAndroidとかの現場よりの内容が多い印象だったので、暗号通貨というテーマはかなり意外に感じたのを覚えています。それなのにぼくに編集依頼がくるということは、もしかしたらだいぶ固い感じの内容なのかなあと勝手に想像していました。
</p>
<p>
ところが、著者の濵津さんの原稿をはじめて目にして、肩透かしを受けることになります。原稿に対する第一印象は、<b>「ラノベだこれ」</b>。
</p>
<p>
しかも、その時点で出来上がっている原稿の大半は、ぜんぜん暗号通貨っぽくない。<b>ひたすらPythonでP2Pネットワークを作り始めている</b>のです。確かに暗号通貨って分散ネットワーク上のアプリケーションだし、書名のとおり「ゼロから創る」んだろうけど、本の構成として正直これでいいのだろうか。わざわざ「創る」という表記になってるのも気になる。それに、対話形式の本文って、これまたかなり難易度が高い手法を選んだな……。
</p>
<p>
そんなことを思いつつ、まずは文章になっている情報を整理するつもりで読み始めて、1章と2章を読み終えたところで、この本が<b>対話形式なのは単なる思いつきではなく完全に意図的だな</b>と気づきました。これなら、「マンガでわかる」みたいな本と同じように、頭ごなしに概念から入るのがつらい人向けに最初の一歩から教師役が寄り添って説明していく本にできそう。そして暗号通貨というのは、数年前にぼく自身がぶちあたったように、
<ul><li>なぜそういう概念を導入したいのか</li><li>その概念はどういう技術に落とし込めるのか</li><li>それらを組み合わせて何ができるのか</li></ul>
が見えにくいテーマなのかもしれず、それならば対話形式はもってこいかもしれない。
</p>
<p>
とはいえ、対話形式って、ケレン味を感じさせることなく読ませるのが難しいんですよね。そもそも登場人物の役割分担を書き分けるのが難しい。生徒役がありえないほど高スキルな質問をしてしまう、みたいなことがないようにしないといけない。かといって、先生役がひたすら説明するのもうまくない。ぼくが最初に原稿を見たのは、ちょうどサポーター向けの最初のプレビューが始まっていたころだったのですが、そのへんの調整はまだまだ必要そうな状態に見えました。
</p>
<p>
そこで、まずは教師役の兄と生徒役の弟の口調を整理しつつ、弟のペルソナを「Pythonでコードはごりごり書けるけど技術の背景にある設計思想はまだ読み取れない学生」としつつ、それがぶれないように兄と弟のセリフを整理しました。兄の説明についても、飛躍を埋めるような調整を全体に入れました。ついでに、なぜ暗号通貨の本を読んでいるはずなのにP2Pネットワークを創らされているのか動機を明確にしたり、いま全体のうちどの部分を説明しているのか迷子にならないようにサブ見出しを適宜入れたり、そういう通常の編集も加えていきました。
</p>
<p>
ちょっと驚いたのは、ぼくの本文編集と並行して、<a href="https://twitter.com/hagino3000">hagino3000さん</a>が全体にわたって<a href="https://github.com/hamatz/simplebitcoin">Pythonのコード</a>をレビューされていたことです。<b>これでは弟が凄腕のPythonistaになってしまうー</b>、という危惧を感じないではなかったのですが、これは読者にとってはすごくうれしいことだと思いました。<b>なるほどPEAKSではそういうところにちゃんとコストをかけているのか</b>、という驚きでした。
</p>
<p>
最終的に完成した『ゼロから創る暗号通貨』という本、すでにクラウドファンディングで支援された方々の手元には届いているのですが、今日からPEAKSのサイトで一般発売も開始したようです。
</p>
<div class="peaks_widget" style="overflow:hidden; padding:20px; border:2px solid #ccc;"><div class="peaks_widget__image" style="float:left; margin-right:15px; line-height:0;"><a target="_blank" id="purchase" href="https://peaks.cc/golden_lucky/cryptocurrency"><img alt="ゼロから創る暗号通貨" style="border:none; max-width:140px;" src="https://s3-ap-northeast-1.amazonaws.com/peaks-images/project004_cover.jpg"></a></div><div class="peaks_widget__info"><p style="margin:0 0 3px 0; font-size:110%; font-weight:bold;"><a target="_blank" id="purchase" href="http://peaks.cc/golden_lucky/cryptocurrency">ゼロから創る暗号通貨</a></p><ul style="margin:0; padding:0;">
<li style="font-size:90%; list-style:none;"><span>著者:</span>
<span>濵津 誠,</span></li>
<li style="font-size:90%; list-style:none;">製本版,電子版</li>
<li style="font-size:90%; list-style:none;"><a target="_blank" id="purchase" style="text-decoration:underline; color:#1DA1F2;" href="http://peaks.cc/golden_lucky/cryptocurrency">PEAKSで購入する</a></li></ul></div></div>
<p>
実際に読むとわかりますが、この本では暗号通貨をやるのにP2Pネットワークから本気で作り始めます。それは、P2Pネットワークにおいて個々のノードがブロックチェーンを構成するという点が、リアルな通貨との交換可能性みたいな部分にとどまらず、暗号通貨の技術的な応用可能性が開けてくるところだからです。「<b>土台となるP2Pネットワークから暗号通貨を自前で作ってみることで、ブロックチェーンを応用したまったく新しいサービスと未来を創る</b>」ところまで意識できる内容になっているのが本書の魅力だと思います<small>(それで書名は「作る」じゃなくて「創る」だったんだね)</small>。もちろん、「<b>著者の濵津さん自身が教師役となり、ブロックチェーンの「うさんくさくない」部分の全体がわかるように、読者をひっぱっていってくれる本</b>」という点も魅力です。上記のリンク経由で本を買っていただけると私にキックバックがあるそうなので、暗号通貨のその先にあるブロックチェーンの応用が気になる方、濵津さんみたいな技術者になりたい方は、ぜひ!
</p>
<p>
っていうか、このブログ記事を書くのに、さっきサトシ・ナカモトの論文を読み返してみたんですよ。そしたら、たぶん『ゼロから創る暗号通貨』をひととおり読んだおかげで、するするわかる。ような気がする。
</p>
k16http://www.blogger.com/profile/02349067627444091120[email protected]0tag:blogger.com,1999:blog-9197115.post-87979750437858822872018-08-15T17:41:00.001+09:002018-08-16T06:17:30.873+09:00日本語の編集をしていてよく直すパターン15選(増えるかも)<p>『<a href="https://note.mu/bxjp/n/na006741687b6">校正のバイトをしててよく直す箇所10選|bxjp|note(ノート)</a>』という記事を読んで、よくパターン化されていて素晴らしいって思っていました。ところが、記事の趣旨を勘違いした方からの冷たい反応を受けて有料にされたということで、あまりも残念なので自分の立場で再編してみました。1~10は元記事のパターンに対してぼくの考え方を添えたもの、A以降は、元記事を見てぼくが反射的に思いついたパターンです。</p>
<p>まあ、こういうパターンは便利だけど、パターン化できる修正を積み重ねれば悪文がなくなるほど自然言語は簡単ではないので、編集や校正をする人はたいへんですね。
自分は、こういうパターンも直すけれど、段落の役割を整理する、みたいな修正のほうが専門です。(専門とは?)</p>
<p><b>追記:これは文の書き方指南じゃなくて、文の編集校正で何をやってるか報告です。</b></p>
<hr/>
<h4>1. 順接の「が」が頻出</h4>
<p>順接の「が」は撲滅を目指すべきです。なるべく減らす、とか言ってる場合ではない。</p>
<h4>2. 「も」を使いがち</h4>
<p>「も」が必要以上に使われているのは論外として、「も」の位置も直したほうがいい場合っていうのが意外と多い。つまり、「も」の位置を直したほうがいい場合っていうのも意外と多い。</p>
<h4>3. 「することができる」を使いがち</h4>
<p>発話で「〇〇できる」と短く言い切るのは不安かもしれませんが、書き言葉では「することが」成分はおおむね不要です。ざくざく削ぎ落としていきます。</p>
<h4>4. 途中で主語が入れ替わっている</h4>
<p>書き手が長い文を書いていると、しばしば主語が入れ替わってしまう。ところで、前の文では主語が入れ替わっていて、日本語では許容される場面も多く、徹底するのは難しい気がします。とはいえ、やっぱり読みやすくはないので、たいていの場合は文章ごと書き直します。</p>
<h4>5. 意味のまとまりで「、」を打たない</h4>
<p>読点は意味の区切りとは限らないので難しいなあ(そもそも意味とは)。ただ、発話の調子に合わせて入れるものではない、とだけは言えます。</p>
<h4>6. 列挙するときに余計な語句を入れてくる</h4>
<p>これはよくわからなかった。</p>
<h4>7. そこ漢字?ってところが漢字</h4>
<p>~と言う、無い、出来る、何れも漢字にして欲しく無い。</p>
<h4>8. 同じ表現・言葉が近い位置に出てくる</h4>
<p>同じものは同じ表現にするのが原則。そのうえで、微妙に違う話が同じ表現になるのを避けたい場合、箇条書きにするといった工夫を施す場合があります。</p>
<h4>9. 表現がバラエティ豊かすぎる</h4>
<p>非標準的な語法やレトリックは、多用すると印象が悪いので、きもち控えめに修正することがよくあります。</p>
<h4>10. 同じことを書いている&省略せずに書いている</h4>
<p>どんなに重要な話でも、同じ内容の文が近距離で繰り返されている場合には、ざっくり要約するか、別の表現に書き換えるなどします。</p>
<h4>A. 因果関係を示すために「ため」を使わない</h4>
<p>「ため」は多義的なので、目的を示すための利用に限定していきます。</p>
<h4>B. 「の」でなくてもいい場所から「の」を追放する</h4>
<p>「ぼくのかんがえたさいきょうのまとめ」よりも「ぼくがかんがえたさいきょうのまとめ」</p>
<h4>C. 「イ形容詞+です」を避ける</h4>
<p>わりと多いです。うまくないです。</p>
<h4>D. 「行う」を減らす</h4>
<p>便利なのでつい多用しがちだけど、だいたいは動詞ひとつで言い換えられます。「することができる」と似てるかもしれない。</p>
<h4>E. 目的語の不足や、位置の修正</h4>
<p>「「何を」がないことが多い。」みたいな文だと、わかってる人にしか伝わりません。「読者が、文脈から動詞の対象となるモノを推察するしかない文章が少なくありません。」くらいたっぷり書いてほしいわけです。それをさらに編集で「動詞の対象となるモノを、読者が文脈から推察するしかない文章が少なくありません。」と直したりします。</p>
k16http://www.blogger.com/profile/02349067627444091120[email protected]0tag:blogger.com,1999:blog-9197115.post-26960489514117782352018-07-07T22:04:00.004+09:002018-07-09T08:09:03.450+09:00技術書をクラウドファンディングで出版してみた<p>
あきみちさんから、「IPv6本を出すということで、クラウドファンディングで協賛を呼びかけよう」(原文ママ)というアイデアを聞いたのは、TwitterのDMのやり取りを読み返すと2016年11月23日のことだったらしい。
DMには時刻が表示されないので正確な時間はわからないけど、その後のやり取りがいつの間にか11月24日になっているので、たぶんそういう時間帯だ。
</p>
<p>
それに対するぼくの最初の返答は、「それは既存の出版社だと面倒そうだ」(原文ママ)だ。
言外に「うち(ラムダノート)ならできるよ」が含意されていることは、起業前からいろいろ相談にのってくれていたあきみちさんには間違いなく伝わる。
とはいえ、そのころはまだ<a href="https://www.lambdanote.com/products/tls">『プロフェッショナルSSL/TLS』</a>も制作中だったし、直販ストアもなかったし、ラムダノートは胸を張って「出版社」と言える状態ではなかった。
</p>
<p>
そもそも、あきみちさんやぼくは技術自体というより技術解説でご飯を食べている人間であり、必要としている人がいる内容だからといって、採算度外視では動けない。
当時はまだクラウドファンディングで技術書を作るという先行事例もなく、どれくらい集めればいいのか、どれくらい集まればいいのか、どういうふうに具体化すればいいのか、まったく見当もつかなかった。
にもかかわらずぼくは、あきみちさんにいくつか質問したあとで、「だれにでも通用するやり方じゃないですが、あきみちさんでIPv6の本なら確度高い。」(原文ママ)と応じていた。
はっきりいって軽率である。
まあでも、考えていてもわからないことは、やってみるしかないので、当時のぼくはやってみることにしたのだろう。
</p>
<p>
それから急いで企画書っぽいものを作り、直接支援をお願いできそうな会社にあきみちさんから打診し、ぼくのほうでも<a href="https://www.makuake.com/project/ipv6/">Makuakeに問い合わせを入れた</a>。
<a href="https://professionalipv6.booth.pm/">完成品をCC BY-NC-SAで公開する</a>ことをふくめて、翌月にはだいたいプロジェクトの形が決まった。
当時の企画書の1枚めはこんな感じ。
</p>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmOK2HcqQ1GX1k-ra0TW8O4ANWwzmXRcJ4NCRzREpDvxxAcVwH8pU7tOR1BuygIZBMakiYC-4vC6cBpqeh68EcCPZCwiAS7gMkc4TZTyLXq4p7ZdErcDkTjYMACHLh8dkz72vB/s1600/plan.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="893" data-original-width="637" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmOK2HcqQ1GX1k-ra0TW8O4ANWwzmXRcJ4NCRzREpDvxxAcVwH8pU7tOR1BuygIZBMakiYC-4vC6cBpqeh68EcCPZCwiAS7gMkc4TZTyLXq4p7ZdErcDkTjYMACHLh8dkz72vB/s320/plan.png" width="227" /></a></div>
<p>
このときの企画書をいま見返すと、本の構成も、収益化のモデルも、基本的なコンセプトはこの時点からほとんどずれていない。
<a href="https://www.lambdanote.com/products/ipv6">本の構成については実際に本を読んでもらうとして</a>、ここでは収益化のモデルという視点で現時点で個人的に感じていることをメモしておこうと思う。
</p>
<h2>「こういう本が最小限の負担で読める世界」に出資してもらう</h2>
<p>
<a href="https://www.lambdanote.com/products/ipv6">『プロフェッショナルIPv6』</a>の商売モデルは、たぶんこんな感じになっている。
</p>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpjoB_0hc3GSs4fODVes86pfx02JrG-rAERIYfqvGBz-07wouV1RMdtGuuJckSQxKzJevSqeH0CblV96kVPa8weyMvXBr1hWR2WkLarrX5CltSB65T6_uhFN5AmRQJvh5olAnM/s1600/temp2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="249" data-original-width="595" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpjoB_0hc3GSs4fODVes86pfx02JrG-rAERIYfqvGBz-07wouV1RMdtGuuJckSQxKzJevSqeH0CblV96kVPa8weyMvXBr1hWR2WkLarrX5CltSB65T6_uhFN5AmRQJvh5olAnM/s640/temp2.png" width="640" /></a></div>
<p>
つまり、この本の著者と出版社には、本という商品だけでなく、<b>「こういう本が最小限の負担で読める世界」</b>を実現することへの対価として出資してもらえたし、応援してもらえた(本当にありがとうございます)。
そうした出資を広く集めるうえでクラウドファンディングという方法は相性がよかったし、任意の金額を著者に直接渡せるという電子版の提供方法を手軽に導入できたのは大きかった(BOOTH、まじ便利)。
</p>
<p>
一方、多くの本の企画は、基本的にはこんな商売モデルでやっている。
</p>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-bDDccAdcfMSDIZJjrpDX37LGAKZinZi58yD4u3Hjt20AtWqkfoq-vGYbkyUfFTJOmFoRG37rzer4CimjzQllzkvLiiBpFQXhXB0VOOX2ZHSdqEdBNEfPztIUl-4BzjI9ktdb/s1600/temp.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="87" data-original-width="595" height="92" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-bDDccAdcfMSDIZJjrpDX37LGAKZinZi58yD4u3Hjt20AtWqkfoq-vGYbkyUfFTJOmFoRG37rzer4CimjzQllzkvLiiBpFQXhXB0VOOX2ZHSdqEdBNEfPztIUl-4BzjI9ktdb/s640/temp.png" width="640" /></a></div>
<p>
この方法だと、<b>動物の絵がカバーにある</b>わけでも<b>全国の書店にフリー入帳で配本できる</b>わけでもない新興の出版社から発行される「IPv6の解説書」は、完全に「知る人ぞ知る」ものになっていただろう。
あきみちさんとぼくの実情からすると、最悪、陽の目をみなかった可能性もある。
こうやって多くの人に届けることはできなかったかもしれないし、著者に利益を還元できなかったかもしれないし、うちも資金繰りに困っていたかもしれない。
</p>
<h2>教訓と抱負</h2>
<p>
<a href="https://www.lambdanote.com/products/ipv6">『プロフェッショナルIPv6』</a>は、たぶん、<b>「こういう本が最小限の負担で読める世界が欲しい」</b>という人を巻き込めた。つまり、「読ませたい人」の支援で成立した。
そして、この事実からは、技術書の出版に従事している自分たちにとっての教訓めいたものが導き出せる気がしている。
</p>
<p>
実のところ、技術書の多くは、これまでだって「読ませたい人」からリソースを分けてもらうことで「商売」をしている。
その最たる相手は、印税収入を期待せずに採算度外視で執筆してくれる著者。
それから、謝辞と献本程度の対価で内容のレビューをしてくれる有識者や、やはり献本程度の対価で宣伝をしてくれるインフルエンサー。
みんな、「読ませたい人」として、自分が持っているリソースを本という商品に投下してくれている。
出版社は、そうした人たちの善意に頼ることで、対価を払ってまで読みたいことを自覚している人の総数だけでは成立しないかもしれない本を作って売るという商売をかろうじて維持している。
</p>
<p>
ぼくら版元の編集者の人間は、そのことに意識的でなければならないと思う。
版元の編集者も「読ませたい人」ではあるだろうけど、その実現のために持ち出しで出資をしているわけではないので(むしろ多くの場合は十分な対価を得ている)、気を抜くとこの事実を忘れがちになるので本当に注意しなければならない。
ページあたり数百円とかで編集制作をやってくれる編集プロダクションが版元編集者のコストを肩代わりしている可能性にも意識的であるべき。閑話休題。
</p>
<p>
教訓は、なにも警鐘を鳴らす方向だけではない。
<a href="https://www.lambdanote.com/products/ipv6">『プロフェッショナルIPv6』</a>では、<b>「こういう本が最小限の負担で読める世界が欲しい」</b>という人から直接出資をしてもらったことで、商売として出版できるチャンスが広がった。
あきみちさんという著者が十数年かけてインターネット上で築き上げた人徳があってはじめて実現するクラウドファンディングではあったけれど、とにもかくにもこういう形で出版ができたということは、「読みたいことを自覚していてお金を出してくれる人」の絶対数が多くないことが多い技術書みたいなジャンルの出版にとっては、わりと未来がある話なんじゃないだろうか、とも思う。
</p>
<p>
そんなわけで、<a href="https://www.lambdanote.com/products/ipv6">『プロフェッショナルIPv6』</a>をひとまず公開にまでこぎつけた現時点で個人的に感慨深いのは、クラウドファンディングという手段の面よりも、<b>「こういう本が最小限の負担で読める世界」</b>に出資したいと感じる人にうまく届けられたかな、という点にあったりする。
締め切りに追われるのが精神的につらいのもあって、正直なところ、これからクラウドファンディングで本をばんばん企画していく予定はない。
でも、「こういう本が最小限の負担で読める世界が欲しい」、もうちょっと厳密に言うと、<b>「こういう技術情報がある世界が欲しい」という人や組織に出資してもらえるような企画、あるいは仕掛け</b>を考えて、そのうえでコンテンツの制作をこれからもがんばっていければ嬉しいなという気持ちでいる。
</p>
<h2>宣伝</h2>
<p>
というわけで、ラムダノートの本をよろしくお願いします。
</p>
<p>
<a href="https://www.lambdanote.com/">https://www.lambdanote.com/</a>
</p>
<p>
<a href="https://www.lambdanote.com/collections/ipv6">プロフェッショナルIPv6
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWFxsmRyklof5cSCYtMlvKgenEMbaDgE9ZIZ-7pRXBPDCqGMGgcXz2mKEHcBLf-FwvMuitThaS5YKPoi7QnQpPmlNL-a__XUN4J6rtgfBHvC47LSHZMxwltXQmU_Qyw0WzpT4i/s1600/ipv6-cover.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWFxsmRyklof5cSCYtMlvKgenEMbaDgE9ZIZ-7pRXBPDCqGMGgcXz2mKEHcBLf-FwvMuitThaS5YKPoi7QnQpPmlNL-a__XUN4J6rtgfBHvC47LSHZMxwltXQmU_Qyw0WzpT4i/s320/ipv6-cover.png" width="227" height="320" data-original-width="645" data-original-height="911" /></a></div>
</a>
</p>
k16http://www.blogger.com/profile/02349067627444091120[email protected]0tag:blogger.com,1999:blog-9197115.post-66265846197224857202018-04-30T22:45:00.000+09:002018-05-01T00:26:18.504+09:00コマンド定義の中で\catcodeを変える<p>
LaTeXではシングルクォート記号がデフォルトで「<code>’</code>」になる。Unicodeでいえば、<a href="https://www.fileformat.info/info/unicode/char/2019/index.htm">RIGHT SINGLE QUOTATION MARK(U+2019)</a>。この挙動は、本文ならよいのだけど、等幅フォントにするような場面では都合が悪い。等幅フォントのときにみんなが期待するシングルクォートは「<code>'</code>」である。
</p>
<p>
みんなが期待する挙動なので、当然、そのためのパッケージがすでにある。<a href="https://ctan.org/pkg/upquote"><code>upquote</code>パッケージ</a>である。しかし、この<code>upquote</code>パッケージは、<code>\verb</code>コマンドおよび<code>verbatim</code>環境向けに作られている。<code>fancyverb</code>環境や<code>alltt</code>環境でも使えるが、<code>\texttt</code>コマンド内の挙動には影響しない。つまり、<code>upquote</code>パッケージを使っても、<code>\texttt</code>内のシングルクォート記号は「<code>’</code>」になる。
</p>
<p>
<code>\texttt{...}</code>の中でシングルクォート記号を直立タイプ「<code>'</code>」にするにはどうするか。すぐに思いつくのは、「<code>'</code>」をアクティブ文字にして、OT1/cmttの<code>\char13</code>にするという方法。あるいは、<code>textcomp</code>パッケージで提供されている<code>\textquotesingle</code>にするという方法。実際、<code>upquote</code>パッケージの実装もそのようになっている。その方針をそのまま実装するとこうなる。
</p>
<pre>
\let\orgtexttt\texttt
\def\texttt#1{%
\catcode`'=\active
\def'{\textquotesingle}
\orgtexttt{#1}}
</pre>
<p>
もちろん、これは動かない。この<code>\def</code>の中身はすでにTeXの入力ルーチンで読み込まれているので、<code>\def'{\textquotesingle}</code>の時点では「<code>'</code>」がアクティブ文字になっていない。そのため、ふつうの文字である「<code>'</code>」に対して<code>\def</code>することになってしまうからだ。結果として、「コントロールシーケンスやアクティブ文字であるべき場所にふつうの文字がある」というエラーになる。
</p>
<pre>
! Missing control sequence inserted.
<inserted text>
\inaccessible
</pre>
<p>
こういう場合の常套手段として、「<a href="http://www.tex.ac.uk/FAQ-activechars.htmlhttp://www.tex.ac.uk/FAQ-activechars.html"><code>\lowercase</code>トリック</a>」と呼ばれるものが知られている。このトリックのポイントは、<code>\lowercase</code>というコマンドの引数が、「すべての文字を小文字として解釈してくれて、しかもカテゴリーコードに関しては無視してくれるような世界」になることにある。そういう世界で、「<code>'</code>」のことを、なにか「<code>\def</code>の1つめの引数に置いても怒られない都合がいいアクティブ文字」の小文字にしておく。幸い、TeXには、そのような都合がいい文字がある。「<code>~</code>」だ。<code>\def~{...}</code>であれば、<code>\def\texttt#1{...}</code>の定義部の中にいきなり書いても怒られない。そこで、「<code>~</code>は<code>'</code>の小文字」ということにしておいて、<code>\def~{...}</code>と書けば、この<code>\def</code>により実際には「<code>'</code>」に対する定義が書けることになる。
</p>
<p>
あるアルファベットに対する「小文字」を定義するためのプリミティブは<code>\lccode</code>だ。これを使い、「<code>'</code>」のことを「<code>~</code>の小文字である」ということにして、その文脈で<code>\lowercase{...}</code>内で<code>\def~{\textquotesingle}</code>すればよい。
</p>
<pre>
\def\texttt#1{%
\catcode`'=\active
\begingroup
\lccode`~=`' %
\lowercase{\endgroup
\def~}{\textquotesingle}
\orgtexttt{#1}}
</pre>
<p>
<code>\lccode`~=`'</code>のスコープを定めている<code>\begingroup</code>と<code>\endgroup</code>の組に対し、<code>\lowercase{...}</code>のカッコがきちんと入れ子になっていない。あまつさえ<code>\def~{\textquotesingle}</code>にも「<code>}</code>」がまたがってしまっている。気持ち悪いかもしれないけど、これで問題はない。少なくとも、<code>\def~</code>を<code>\begingroup</code>~<code>\endgroup</code>の中に入れてしまうと、この<code>\def</code>がローカルになってしまうので、「<code>'</code>」がアクティブになるだけなって定義がないままとなりエラーになってしまう。
</p>
<pre>
! Use of ' doesn't match its definition.
</pre>
<p>
まあ、<code>\gdef</code>にすればいいだけだけど。
</p>
<pre>
\def\texttt#1{%
\catcode`'=\active
\begingroup
\lccode`~=`' %
\lowercase{%
\gdef~}{\textquotesingle}\endgroup
\orgtexttt{#1}}
</pre>
<p>
(ところで、<code>\endgroup</code>が<code>\lowercase{</code>の直後で問題ないことの根拠は、正直なところよく理解していない。<code>\lowercase</code>が大文字小文字の対応表をメモリに展開するのが引数を読む前、だからなんだろうなあ。)
</p>
<p>
さて、<code>\lowercase</code>トリックのおかげで「<code>'</code>」がアクティブ化される前に「<code>\def'</code>」と書くことを回避できたので、こでれエラーにならずに動く。しかし、挙動は依然としておかしい。ブロック要素で最初に登場する<code>\texttt</code>の中では「<code>'</code>」の定義が効いておらず、その後ろに出てくる「<code>'</code>」が、<code>\texttt</code>の中だろうが外だろうが<code>\textquotesingle</code>になってしまうのである。
</p>
<pre>
*<b>\texttt{\show'}</b>
> the character '. <color font="green">% \textttの中だけど、文字</color>
...
*<b>\show'</b>
> '=macro:
->\textquotesingle . <color font="green">% \textttの外だけど、アクティブになってる</color>
...
*<b>\texttt{\show'}</b>
> '=macro:
->\textquotesingle . <color font="green">% 2つめの\textttの中ではアクティブに</color>
...
</pre>
<p>
最初に登場する<code>\texttt</code>の中で「<code>'</code>」の定義が効かない原因は、すぐにわかった。<code>\texttt</code>の引数はすでに読み込まれているから、「<code>'</code>」に対する<code>\catcode</code>は効いてないのである。<code>\def</code>に対しては<code>\lowercase</code>トリックのおかげでごまかせたが、この状態では<code>\texttt</code>の引数に対して「<code>'</code>」が<code>\textquotesingle</code>として扱われることはない。
</p>
<p>
この欠陥に対処するには、<code>\texttt</code>の引数が読み込まれるのを遅らせればいい。そういう場合の常套手段は、<a href="http://www.tex.ac.uk/FAQ-actinarg.html">マクロの展開を二段階にしてサブのほうで引数を読み込ませる</a>、というもの。つまりこんなふうにする。
</p>
<pre>
\let\orgtexttt\texttt
\def\texttt{%
\begingroup
\catcode`'=\active
\x@texttt}
\def\x@texttt#1{%
\begingroup
\lccode`~=`' %
\lowercase{\endgroup
\def~}{\textquotesingle}
\orgtexttt{#1}
\endgroup}
</pre>
<p>
これで、目的のマクロそのものは完成した。
</p>
<p>
これにて本件は落着といたす、でもいいんだけど、1つ前の定義が「最初に登場する<code>\texttt</code>より後ろで、<code>\texttt</code>の中だろうが外だろうがシングルクォートが<code>\textquotesingle</code>になってしまう」という挙動だったのが謎い。まったく<code>\textquotesingle</code>にならない、というなら納得できるんだけど、<strike>なぜ<code>\texttt</code>の引数内で閉じているはずの<code>\catcode`'=\active</code>が外に漏れてしまっているのか。</strike>
</p>
<strike>
<p>
どう考えても、オリジナルの<code>\texttt</code>の定義に何かある。
しょうがないので<code>latex.ltx</code>を覗くと、<code>\texttt</code>の定義は事実上こうなっていた。
</p>
<pre>
\DeclareRobustCommand\texttt[1]{%
\ifmmode
\nfss@text{\ttfamily #1}%
\else
\hmode@bgroup
\text@command{#1}%
\ttfamily\check@icl #1\check@icr
\expandafter
\egroup
\fi}
</pre>
<p>
なんなんだよ、この下から3行めの<code>\expandafter</code>。。これのおかげで、<code>\texttt</code>(を再定義したものの中にある<code>\orgtexttt</code>)の引数が読まれるとき、もりもり後ろのほうまで読まれてしまって、<code>\catcode`'=\active</code>がしばらく先まで有効になってしまっていたっぽい。
</p>
<p>
この<code>\expandafter</code>は、<code>\texttt</code>に限らず、NFSSが提供するフォント変更コマンドすべてに登場する(ようなマクロになっている)。これ、なんのために必要なの?
</p>
</strike>
<p>
なにも謎くなかった。先の動作しない<code>\texttt</code>の定義で<code>\catcode`'=\active</code>は閉じてない。ZRさんありがとうございます。
</p>
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ダメな方の \texttt で、例えば<br>\texttt{\show'}<br>を一回展開すると<br>\catcode`'=\active \begingroup …<br>となる。\catcode 文はグループ外だから、\begingroup 以降のゴチャゴチャに関わらず、とにかく ' はアクティブになったまま。</p>— ZR-TeXnobabbler(∉∅) (@zr_tex8r) <a href="https://twitter.com/zr_tex8r/status/990966513023664128?ref_src=twsrc%5Etfw">2018年4月30日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
k16http://www.blogger.com/profile/02349067627444091120[email protected]0tag:blogger.com,1999:blog-9197115.post-85669767650921820772018-03-05T15:34:00.000+09:002018-03-06T07:59:00.383+09:00技術書のレビューの経験則
<p>
出版される前の本の内容は、通常は著者や編集者に代表される「制作サイド」の人間にしか読まれない。
専門性の高い本であれば査読とか監修といったプロセスを有識者にお願いすることはあるけど、そうしたお願いをするときには有償だったりカバーや袖に名前を出したりすることが多いので、これも「制作サイド」の一部とみなしていいだろう。
</p>
<p>
一方、<b>基本的に無償で、完成した書籍の献本と謝辞への掲載くらいを前提に、あくまでもベストエフォートで発行前の本の内容を見てください</b>というお願いを第三者にすることもある。
この場合の第三者というのは、制作中の書籍の想定読者だったり、出版後の書籍を対象読者へ紹介してくれそうな立場の人だったりする。
このようなプロセスを制作に取り入れる習慣は、とくにここ数年のIT系の出版社ではめずらしくなくて、界隈では「レビュー」などと呼ばれている。
</p>
<p>
というわけで、技術書の制作における「レビュー」について、自分の経験をもとに知見を整理しておきたい。
自分の経験をもとにはしているけど、たぶん日本で技術書のレビューをまわしてきた経験数では上位にいるはずなので、独りよがりではあるかもだけど意味がなくはないはず。
</p>
<blockquote style="background-color:#ddffff;padding:10px;">
余談だけど、たぶんこういう出版前の状態を有志にボランティアでレビューしてもらうという文化を技術書界隈で積極的に始めたのはアスキーなんじゃないかなと思う。
少なくともぼくが最初にこういうプロセスの存在を知ったのは、アスキーの256本とかで執筆兼レビューのためにメーリングリストを使っているのを見たときだった。
彼らがどこまで意識的にこれをプロセス化していたのかは知らないけれど、この記事は、彼らがやっていたプロセスをぼくの前職のチームの先輩だった森田さんが取り込み、いろいろな著者、訳者に協力してもらいながら発達させてきた手法がベースになっている。
</blockquote>
<h2>技術書のレビューのパターン</h2>
<p>
まず、レビューと一口にいっても王道のプロセスがあるわけではなくて、依頼方法およびレビュアーどうしのインタラクションの有無によっていくつかの形に分類できる。
</p>
<style>
table {width: 80%; border-collapse: collapse; margin: auto;}
tr:nth-child(even) {background-color: #f2f2f2;}
th {background-color: #f2f2f2; width:4em;}
td {text-align: center;background-color: #ffffff;}
table, th, td {border: 1px solid black;}</style>
<table>
<tr>
<th style="max-width:4em;"></th><th style="max-width:3em;">レビュー内容は制作サイドだけが見たい</th><th style="max-width:3em;">レビュー内容が他のレビュアーにも見えてよい</th>
</tr>
<tr>
<th>制作サイドで知己がある人に依頼</th>
<td>①</td>
<td>②</td>
</tr>
<tr>
<th>制作サイドで知己がない人に依頼</th>
<td>③</td>
<td>④</td>
</tr>
<tr>
<th>不特定多数</th>
<td>⑤</td>
<td>⑥</td>
</tr>
</table>
<p>
上記の表のいずれのパターンに該当するかによって、レビューの具体的な手法やツールがだいたい決まる。
</p>
<h2>技術書のレビューの手法</h2>
<p>
とはいえ、実際にはレビューの具体的な手法やツールがまずあり、その結果として上記の表のいずれかに当てはまるという状況が多いだろう。
いずれにしても、誰にどういう方法でレビューをしてもらうかは、レビューに使うツールやプロセスに依存する。
そこで、次はツールという観点から上記の表の各セルとの適正について整理してみよう。
</p>
<h3>バグトラッキングシステムを利用する方法</h3>
<p>
②と④の場合は、プライベートな<b>バグトラッキングシステム</b>を使うことが多い。自分がかかわるプロジェクトだと、一昔前は<a href="https://trac.edgewall.org/">Trac</a>のチケット、いまではGitHubのissueとしてフィードバックをもらっている。
もちろん、TracやGitHubなどのシステム側で不特定多数の参加を許可するようにすれば、⑥の場合にも使える。
</p>
<p>
バグトラッキングシステムを使うメリットとしては、あるレビュアーが見つけた問題を制作サイドやレビュー陣営全体で共有しやすいことが挙げられる。原稿のバージョン管理をしている場合にはリポジトリに関連付けられたバグトラッキングシステムを使えるので、フィードバックへの対応履歴を管理しやすいというのも魅力。ひとことでいえば、<b>レビュアーとレビューを受ける側のトータルでの負担が最小化される方法</b>だといえる。
</p>
<p>
<b>レビュアーどうしでチケットやissueで議論ができる</b>ので、著者や編集者だけ、つまり制作サイドだけでは思いつかないような解決策が出たり、特定のレビュアーの偏った意見なのかそうでないのかを客観的に判断する材料ができたりするというメリットもある。
</p>
<p>
デメリットは、レビュアーが見つけた問題をチケットやissueにするときに、<b>指摘したい場所を一意に伝えにくい</b>こと。ほとんどの場合、レビュアーが見る対象というのは、原稿ソースに技術的にアクセスができる場合でも、組版されたPDFである。そのため、一般には「mページのk行め」のような指示方法になるしかないのだけれど、これには次の難点がある。
</p>
<ul>
<li>
レビューを受け取る側ではPDFでなく原稿ソースのほうを見ているので、「mページのk行め」という情報は使わず、指摘内容からキーワードをgrepして該当箇所を探している。つまり、「mページのk行め」まで粒度が細かい情報は無駄になってしまうことが多い。原稿ソースが頻繁に更新される環境だと、レビュー対象のPDFと制作進行中のPDFとで場所の乖離がさらに激しくなる
</li>
<li>
「mページのk行め」のような指摘は、他のレビュアーにとっても優しくないので、指摘のダブりが意外と発生しやすい。ダブりを防ぐために修正ずみの問題をすぐにクローズしないといった運用をしても、なおダブる。そもそも修正ずみの問題をクローズできないのでは、バグトラッキングシステムを使う利点が半減してしまう
</li>
</ul>
<p>
場所の指示がめんどうであることに加えて、バグトラッキングシステムを利用することには、<b>レビュアーが他のレビュアーの意見を読めてしまうことによるデメリット</b>もある。
</p>
<ul>
<li>
うまく回ればレビュアーどうしの議論によって問題の文脈がはっきりするのだが、ときには議論の発散という形でデメリットになる場合もある
</li>
<li>
声が大きい有名人がレビュアーにいることで他のレビュアーが委縮してしまい指摘しづらい雰囲気ができたり、そのようなレビュアーの意見に流される可能性がある
</li>
</ul>
<p>
まとめると、バグトラッキングシステムを使った技術書のレビューには、手軽に問題を管理できる一方で、指摘箇所を一意に特定するのが困難であり、他のレビュアーとのインタラクションが不可避であるというデメリットがある。
そのため、冒頭の表における②のような<b>著者や編集者が議論をコントロールしやすいレビュアーの集合である場合に向いた手法</b>だといえる。
④の場合には、レビューの要件を具体的に明文化しておく必要があるだろう(もちろん②のケースでも明文化したほうがいいんだろうけど)。
一方、レビュアーが他のレビュアーの意見によってバイアスを受けるのを避けたい場合(①、③、⑤)、自転車小屋の屋根の色をめぐる議論に巻き込まれたくないという場合(⑥)には、使えない。
</p>
<h3>問題点を個別に直接送ってもらう方法</h3>
<p>
複数のレビュアーがバグトラッキングシステムで相互に意見を交わしながら技術書のクオリティを上げていく作業は、うまく回ると本当に楽しい。それ自体がエンターテインメントだったと感じることも少なくない。
しかし、そういう場が醸成されるまでには時間がかかるし、そもそも成功するとは限らない。オープンソースプロジェクトに慣れている著者かどうかという文化的な違いによる困難もある。
前述したように、レビュアーが他のレビュアーの意見によってバイアスを受けることを避けたい場合もある。
</p>
<p>
そこで、著者 and/or 編集者が個別にレビューを依頼し、<b>一対一でフィードバックを返してもらう</b>というケースもかなり多い。
その場合には、メールで指摘をもらったり、PDFのコメント機能を使ってもらったり、最近だとDropboxのコメント機能を使うこともある(Google Driveにも同様の機能はあるので使えるかもしれない)。
</p>
<p>
この方法は、<b>フィードバックをもらうという一点に特化</b>すればもっとも優れている。
Acrobatのレビュー機能やDropboxのコメント機能を使えば、バグトラッキングシステムでは不可避だった指摘箇所を一意に特定する難しさがある程度は解消できるという利点もある。
</p>
<p>
難しいのは、<b>なんといっても人選</b>。
バグトラッキングシステムを利用すれば十数人規模になってもハンドリング可能だけど、個別にやり取りをする負荷を考えると、数人に抑えたいところ。となると、ピンポイントで適切な人に依頼するのが現実的だといえるだろう。
そういうわけで、冒頭の表における①や③に向いた方法だといえる。
⑤でも使えなくはないけれど、というか⑤をやりたいときはこの方法しかないんだけど、制作サイドが個別のやり取りの負荷を覚悟する必要がある。
</p>
<h3>クラウド上で共有したPDFにコメントを付けてもらう方法</h3>
<p>
DropboxにPDFを置くと、閲覧できる人が誰でも文字列をハイライトしてコメントをつけられるようになる。
この機能は、個別に指摘をもらう場合だけでなく、複数のレビュアーから同時に指摘を受ける場合にも使える。
Dropboxによる方法のメリットは、<b>実施前の手間</b>が最小であること。なにしろ、Dropboxに置いてリンクを伝えるだけでいい。
<b>モダンブラウザがあれば説明不要で直観的に指摘箇所を一意に特定できる</b>のもお手軽さにつながる。
</p>
<p>
デメリットは、<b>DropboxのPDFビューアーはPDFの仕様に準拠していない独自の拡張で、次のような不自由がある</b>こと。
</p>
<ul>
<li>
書籍全体の検索ができない場合がある。検索対象になるのはブラウザが描画ツリーを構築した部分だけ
</li>
<li>
コメントのステータスが未解決と解決済みの2つしかないので、複数のレビュアーからの指摘がダブらないようにするにはすべて未解決にしておくしかない。そのため、レビューを締め切るまで取り込み作業がしにくい
</li>
<li>
個々のコメントにURLが付かないので、議論が始まったコメントや見逃したコメントを通知をたどって追いかけるしかない
</li>
<li>
PDFデータにはコメントが埋め込まれないので、ダウンロードしてPDFリーダーでコメントを管理することも、PDFデータからコメントを抜き出すこともできない
</li>
</ul>
<p>
このような制約があるので、DropboxでPDFにコメントをもらう方法をうまくまわすには、PDFのページ範囲を小さく章単位などに絞ったり、レビューの締め切りまではコメントを解決済みステータスにしないようにしたり、少し工夫がいる。
それでも、指摘箇所を一意に特定しやすいというメリットは大きいので、Slackなどの他メディアでレビュアーと制作サイドが気軽に議論ができる②のような状況であれば、かなり魅力的だと思う。
</p>
<p>
もうひとつ、Dropboxに代表される共有PDFへのコメント書き込みには、<b>指摘がミクロに偏りがち</b>になってしまうという見過ごせない欠点がある。
この欠点を補うにも、レビュアーと制作サイドとが雑談できる場の用意が重要な気がしている。
</p>
<p>
なお、この方法で技術書のレビューが可能なのはDropboxだけではない。
Google Docsにも指摘が行単位になるけど同様の機能はあるし、Adobe Readerにも共有レビューという機能がある。
PDFの仕様にそったアノテーション機能であるAdobe Readerの共有レビューが使えるのがベストなんだけど、Adobe ReaderがLinuxベースの環境で事実上使えなかったり、macOSでもインストールしてない人がいたりするから、つらい。
</p>
<h2>技術書のレビューをする側の心得</h2>
<p>
ここまでは、技術書のレビューを受ける側に向けた話だった。
ここでは、<b>レビューをするときにどんなことを意識したらいいか</b>についてざっくり書いてみる。
ただし、ぼく自身はレビューを受ける側の立場に立つことが多いので、主にレビューを受ける側の視点が多分に混ざります。
</p>
<h3>レビューでがんばって探しちゃだめな問題</h3>
<p>
レビューで何を見るべきかを要約するのは難しいけど、がんばって見てはいけない問題というのはある。
建前としては「気づいたことを何でも指摘してほしい」なんだけど、何に気付くかは「何に気付こうと思って読んでいるか」に多分に影響されるので、<b>「この点については意識的に探す必要がない」を意識するのはけっこう重要。</b>
</p>
<ul>
<li>
誤字脱字など、日本語上のミス
</li>
<li>
漢字や送り仮名などの表記ゆれ
</li>
<li>
レイアウトの不備
</li>
</ul>
<p>
これらは、「気づいたなら指摘しておく」という態度で読めば十分で、レビューというプロセスでがんばって探すべき問題ではない。
逆に言うと、<b>制作サイドの心得として、これらの問題をなるべくつぶした状態でレビューを開始すべき</b>ともいえる。
</p>
<p>
なんだけど、時間的な制約もあるので、現実にはそうでない原稿をレビューすることになる機会もある。
そういう問題が多く残っている状態でレビューをすることになった場合には、上記のような問題を一生懸命に探してあげるのではなく、「この章は誤字脱字が目立つけどあとで修正されるのですよね?」といった大局的なコメントを残すのがよい。
<b>技術書のレビューの主眼は、あくまでも第三者の目を取り入れることであり、校正作業のボランティアではない</b>のだから。
</p>
<p>
レイアウトについても同様で、完成途中のPDFを見るとどうしてもアラが目立つけど、それはやはりレビュアーが気を配る部分ではない。
「レイアウトの不備で有意義なレビューが困難である」といった指摘に留めよう。
</p>
<h3>ミクロな指摘より、マクロな指摘を</h3>
<p>
誤字やレイアウトの不備にも関係するけれど、第三者であるレビュアーが<b>ミクロに指摘したくなるような原稿の問題は、もっと広いスコープでの問題</b>という場合が少なくない。
なんか日本語がわかりにくいなあと思って、語の位置を変えたり読点を追加したりしたミクロな修正案を出すのは、実は解決になっていないことが多い。
レビュアーがミクロな指摘で解消を試みた問題の根本的な原因は、より広いスコープで原稿の問題を解消できる人、つまり制作サイドでないと対処できないことが多い。
</p>
<p>
レビュアーとしては、なんか日本語がわかりにくいなあと感じる箇所があったら、「〇〇ということが言いたいんだと思うんだけど、なんか日本語がわかりにくいなあ」と指摘するのがベター。
〇〇すらわからないなら、「文意が不明」といったコメントでも十分。
</p>
<h3>自分にとって理想的な本にする機会ではない</h3>
<p>
技術書のレビューは、校正作業のボランティア募集にならないためにも、制作プロセスではかなり後の工程になる。
つまり、レビュアーとしては、本のコンセプトや表現方法、近日中の出版については了解しているということが前提になる。
したがって、内容に間違いがあると考えられるなら指摘すべきだけど、<b>本の表現に対して調整を要求する場ではない</b>という自覚は必要である。
</p>
<p>
文章に対するレビューというのは、センシティブなプロセスだ。指摘者以外にとってどちらでもいい話であることも少なくない。
どちらでもいい話に「どちらでもいい」というのは精神力がいるものなので、はじめから不採用前提くらいの気持ちだとみんなが楽になる。
たとえば、同じ内容ならこっちを説明すべきとか、説明の日本語表現はこっちのほうがいいとか、そういう指摘についての最終的な決定権は制作サイドにゆだねる。
制作サイドもまじえて議論になり、最終的な文章表現をなにか決定しないといけなくなったところで、代替案の作文をするくらいが双方の負担にならず、ちょうどいい。
</p>
<p>
逆に、<b>著者や編集者には、無慈悲な独裁者となる覚悟が必要</b>だといえる。
そういう意味ではオープンソースのコミッターと同じなのかも。
報われないかもしれない指摘であるという点について双方が納得していないと、レビューは回らない。
</p>
<h2>実践例</h2>
<p>
いままさに進行中の本の大規模レビューは、冒頭の表だと④、もしくは⑥に近いプロジェクトである。
そこで、指摘箇所を一意に特定する部分の困難さを回避しつつ、指摘の重複回避や原稿(他のプライベートリポジトリ)への取り込み状況の管理を可能するために、次のようなレビュー方法を採用した。
</p>
<ul>
<li>
フィードバックはPDFのページ単位で受ける。そのために、各ページ用のGitHub issueをあらかじめ全ページぶん用意しておく
</li>
<li>
指摘をするときの負荷を下げるために、PDFの各ページに、各ページ用GitHub issueへのリンクを埋め込んでおく。そこをクリックすれば、そのページに対するコメントを書き込めるページがブラウザで開くしくみ
</li>
</ul>
さらに、上で紹介した経験則を踏まえて、レビュアーには下記のようなお願いをしている。
<blockquote style="background-color:#ddffff;padding:10px;">
<p>
PDFを読んでページごとのissueに指摘を追記していってください。代案は不要です。なお、マンパワーの都合でissue上では無反応の可能性が高いです。ごめんなさい。
</p>
<ul>
<li>
具体的に指摘をいただきたいポイント
<ul>
<li>
内容の間違い
</li>
<li>
解説がほしいトピック
</li>
<li>
意味が取れない段落
</li>
</ul>
</li>
<li>
下記の指摘も歓迎です(grepをかけるので存在の指摘だけで十分です)
<ul>
<li>
技術用語の不統一
</li>
<li>
スペルミス、誤字、脱字
</li>
</ul>
</li>
<li>
下記については、指摘は不要です(最終までには自然に直ります)
<ul>
<li>
日本語表記(漢字や送り仮名)の不統一
</li>
<li>
レイアウトの不備
</li>
<li>
その他、局所的な日本語の問題
</li>
</ul>
</li>
</ul>
</blockquote>
<p>
前半で述べたように、そもそも適切なレビューの手法は要求事項によって変わってくるので、<b>これがベストな技術書のレビュー手法というわけではない</b>。
最大で十数人くらい、著者が中心になってSNSなどで直接連絡がつく範囲に依頼するなら、いまのところDropboxへのコメントはかなり手軽に思える。
ピンポイントでお願いする人がいる場合も、DropboxへのコメントやPDFへのアノテーションがベストだろう。
一方、ある程度の議論が予測されたり、原稿のバージョン管理との親和性が優先されるなら、これからもGitHubのissueを使うと思う。
</p>
<p>
そしていずれにせよ、レビュアーに何を見てもらいたいか(見る必要がないのか)、レビューにあたって最終決定権は制作サイドの独断的な判断になることについては、何らかの形でレビュアーと制作サイドとで意識共有ができているべき。
</p>
k16http://www.blogger.com/profile/02349067627444091120[email protected]0tag:blogger.com,1999:blog-9197115.post-17645599730039215612018-01-12T14:13:00.001+09:002018-01-12T14:49:43.840+09:00RubyでつくるRuby発売中カート埋め込みのテスト。デフォルトだと書籍ページへのリンクにはならないのかな。カートに入れてしまったときに画面に常駐するカートボタンは、数をゼロにすると消えるようです。
<div id='product-component-9d7ba324e51'></div>
<script type="text/javascript">
/*<![CDATA[*/
(function () {
var scriptURL = 'https://sdks.shopifycdn.com/buy-button/latest/buy-button-storefront.min.js';
if (window.ShopifyBuy) {
if (window.ShopifyBuy.UI) {
ShopifyBuyInit();
} else {
loadScript();
}
} else {
loadScript();
}
function loadScript() {
var script = document.createElement('script');
script.async = true;
script.src = scriptURL;
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(script);
script.onload = ShopifyBuyInit;
}
function ShopifyBuyInit() {
var client = ShopifyBuy.buildClient({
domain: 'lambdanote-store.myshopify.com',
apiKey: '8dc2e94862a29f0bfdcccaf96483d7f3',
appId: '6',
});
ShopifyBuy.UI.onReady(client).then(function (ui) {
ui.createComponent('product', {
id: [8982519049],
node: document.getElementById('product-component-9d7ba324e51'),
moneyFormat: '%C2%A5%7B%7Bamount_no_decimals%7D%7D',
options: {
"product": {
"variantId": "all",
"width": "240px",
"contents": {
"imgWithCarousel": false,
"variantTitle": false,
"description": false,
"buttonWithQuantity": false,
"quantity": false
},
"styles": {
"product": {
"text-align": "left",
"@media (min-width: 601px)": {
"max-width": "100%",
"margin-left": "0",
"margin-bottom": "50px"
}
},
"compareAt": {
"font-size": "12px"
}
}
},
"cart": {
"contents": {
"button": true
},
"styles": {
"footer": {
"background-color": "#ffffff"
}
}
},
"modalProduct": {
"contents": {
"img": false,
"imgWithCarousel": true,
"variantTitle": false,
"buttonWithQuantity": true,
"button": false,
"quantity": false
},
"styles": {
"product": {
"@media (min-width: 601px)": {
"max-width": "100%",
"margin-left": "0px",
"margin-bottom": "0px"
}
}
}
},
"productSet": {
"styles": {
"products": {
"@media (min-width: 601px)": {
"margin-left": "-20px"
}
}
}
}
}
});
});
}
})();
/*]]>*/
</script>k16http://www.blogger.com/profile/02349067627444091120[email protected]0tag:blogger.com,1999:blog-9197115.post-3847415226254023312017-12-31T10:36:00.000+09:002017-12-31T14:52:39.931+09:002018年賀状 <style type="text/css">
<!--
.comment {
/* font-lock-comment-face */
color: #5f615c;
font-style: italic;
}
.function-name {
/* font-lock-function-name-face */
color: #a40000;
}
.keyword {
/* font-lock-keyword-face */
color: #346604;
}
.string {
/* font-lock-string-face */
color: #5c3566;
}
.variable-name {
/* font-lock-variable-name-face */
color: #b35000;
}
a {
color: inherit;
background-color: inherit;
font: inherit;
text-decoration: inherit;
}
a:hover {
text-decoration: underline;
}
-->
</style>
<p>
年賀状書いた。
</p>
<pre>
<span class="comment">%!</span>
<< <span class="variable-name">/PageSize</span> [285 420] >> setpagedevice
<span class="comment">% excerpt from Bill Casselman's </span>
<span class="comment">% "Mathematical Illustrations - a manual of geometry and PostScript"</span>
<span class="function-name">/ctransform</span> { load
1 <span class="keyword">dict</span> <span class="keyword">begin</span>
<span class="variable-name">/f</span> exch <span class="keyword">def</span>
[{[3 1 roll f {moveto}]}
{[3 1 roll f {lineto}]}
{[7 1 roll
f 6 2 roll
f 6 2 roll
f 6 2 roll
{curveto}]}
{[{closepath}]}
pathforall]
newpath
{aload pop <span class="keyword">exec</span>} <span class="keyword">forall</span>
<span class="keyword">end</span>
} <span class="keyword">def</span>
<span class="function-name">/f</span> {<span class="variable-name">/y</span> exch <span class="keyword">def</span>
<span class="variable-name">/x</span> exch <span class="keyword">def</span>
x y fsub 5 y mul cos mul
y x fsub 3 y mul cos mul
} <span class="keyword">def</span>
<span class="function-name">/fsub</span> { <span class="comment">% u = sin (a √(30 - (b^2 / 10))) * 460 </span>
<span class="variable-name">/b</span> exch <span class="keyword">def</span>
<span class="variable-name">/a</span> exch <span class="keyword">def</span>
a 30 b dup mul 10 div sub sqrt mul sin 460 mul
} <span class="keyword">def</span>
<span class="function-name">/setrandcolor</span> { <span class="comment">% def</span>
<span class="variable-name">/r1</span> {rand 5 mod 3 div} <span class="keyword">def</span>
<span class="variable-name">/r2</span> {rand 7 mod 6 div} <span class="keyword">def</span>
<span class="variable-name">/r3</span> {rand 5 mod 6 div} <span class="keyword">def</span>
r1 r2 r3 setrgbcolor
} <span class="keyword">def</span>
1 1 20 { <span class="comment">% for</span>
<span class="variable-name">/n</span> exch <span class="keyword">def</span>
newpath
<span class="variable-name">/ShowcardGothic-Reg</span> findfont 4 scalefont setfont
-0.4 9 moveto <span class="string">(2018)</span> <span class="keyword">true</span> charpath
-0.1 6 moveto <span class="string">(1820)</span> <span class="keyword">true</span> charpath
0 3 moveto <span class="string">(2018)</span> <span class="keyword">true</span> charpath
-0.1 0 moveto <span class="string">(1820)</span> <span class="keyword">true</span> charpath
<span class="variable-name">/f</span> ctransform
<span class="keyword">gsave</span>
clip
newpath
<span class="variable-name">/j</span> {
<span class="variable-name">/x</span> exch <span class="keyword">def</span>
rand x mod x div 30 mul
} <span class="keyword">def</span>
0 5 400 {
<span class="variable-name">/i</span> exch <span class="keyword">def</span>
10 j setlinewidth
setrandcolor
0 i moveto
300 i lineto
stroke
} <span class="keyword">for</span>
<span class="keyword">grestore</span>
currentlinewidth 2 mul setlinewidth
0.1 0 0 setrgbcolor
stroke
3 410 moveto
<span class="variable-name">/Georgia-Bold</span> findfont 5 scalefont setfont
0.3 0.2 0.2 setrgbcolor
n =string cvs show
<span class="string">(/20)</span> show
<span class="keyword">showpage</span>
} <span class="keyword">for</span>
</pre>
<p style=" margin: 12px auto 6px auto; font-family: Helvetica,Arial,Sans-serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 14px; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none; display: block;"> <a title="View 2018 on Scribd" href="https://www.scribd.com/document/368147593/2018#from_embed" style="text-decoration: underline;" >2018</a> by <a title="View Keiichiro Shikano's profile on Scribd" href="https://www.scribd.com/user/69531250/Keiichiro-Shikano#from_embed" style="text-decoration: underline;" >Keiichiro Shikano</a> on Scribd</p><iframe class="scribd_iframe_embed" title="2018" src="https://www.scribd.com/embeds/368147593/content?start_page=1&view_mode=scroll&access_key=key-ohQgFxBhzcommOLvOStk&show_recommendations=true" data-auto-height="false" data-aspect-ratio="0.6787057938299473" scrolling="no" id="doc_90785" width="400" height="600" frameborder="0"></iframe>
<p>
今年は球体を作ってみたいなと思って、はじめはエッシャーふうの非ユークリッド空間の円盤への写像を「2018」のパターンで埋めようと思ったのだけど、<a href="https://www.d.umn.edu/~ddunham/isis4/index.html">ちょっと調べたら</a>、それをやるには3つか5つの頂点を持つような「2018」をデザインしてそれを中心から外周へと再帰的に貼り付けていくことになりそうで、デザイン力が要求されるし、コードを書く時間もないから、やめ。
正方形を円へと等角写像で膨らませて輪郭を作りつつ、sinをとって膨らみ感を強調し、x軸で多少オフセットして、全体にそれっぽく見せることでごまかしています。
</p>
<p>
フォントは<a href="https://fontzone.net/font-details/showcard-gothic">ShowCard Gothic</a>というボリューム感のあるフォントを選びました。
</p>
<p>
にしても、はじめてPostScript手書きで年賀状を作ってからもう10年になるのかあ。
ということで、これを機に過去のぶんもすべてGitHubにまとめておきました。
</p>
<ul>
<li><a href="https://github.com/k16shikano/new-year-cards">New Year Cards in PostScript<br>https://github.com/k16shikano/new-year-car</a></li>
</ul>
<p>
もともとPostScriptしばりというわけでもなく、なんとなく西暦の文字列を使って世界で1枚だけの年賀状をアルゴリズミックに生成するつもりしかなくて、2009年はPostScriptじゃないしコードも残っていなかった(Gaucheで書き捨てた)。
まあでも、よく10年続いたなと思う。
</p>
<p>
10年続きはしたけれど、年に一回しか書かないこともあり、PostScript力にはたいした進歩が感じられませんね。
</p>
k16http://www.blogger.com/profile/02349067627444091120[email protected]0tag:blogger.com,1999:blog-9197115.post-42470724263382498132017-12-24T14:48:00.000+09:002017-12-24T14:52:31.238+09:00TeXでつくるMarkdownパーサ<style type="text/css">
.hll { background-color: #ffffcc }
.c { color: #8f5902; font-style: italic } /* Comment */
.err { color: #a40000; border: 1px solid #ef2929 } /* Error */
.g { color: #000000 } /* Generic */
.k { color: #204a87; font-weight: bold } /* Keyword */
.l { color: #000000 } /* Literal */
.n { color: #000000 } /* Name */
.o { color: #ce5c00; font-weight: bold } /* Operator */
.x { color: #000000 } /* Other */
.p { color: #000000; font-weight: bold } /* Punctuation */
.cm { color: #8f5902; font-style: italic } /* Comment.Multiline */
.cp { color: #8f5902; font-style: italic } /* Comment.Preproc */
.c1 { color: #8f5902; font-style: italic } /* Comment.Single */
.cs { color: #8f5902; font-style: italic } /* Comment.Special */
.gd { color: #a40000 } /* Generic.Deleted */
.ge { color: #000000; font-style: italic } /* Generic.Emph */
.gr { color: #ef2929 } /* Generic.Error */
.gh { color: #000080; font-weight: bold } /* Generic.Heading */
.gi { color: #00A000 } /* Generic.Inserted */
.go { color: #000000; font-style: italic } /* Generic.Output */
.gp { color: #8f5902 } /* Generic.Prompt */
.gs { color: #000000; font-weight: bold } /* Generic.Strong */
.gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.gt { color: #a40000; font-weight: bold } /* Generic.Traceback */
.kc { color: #204a87; font-weight: bold } /* Keyword.Constant */
.kd { color: #204a87; font-weight: bold } /* Keyword.Declaration */
.kn { color: #204a87; font-weight: bold } /* Keyword.Namespace */
.kp { color: #204a87; font-weight: bold } /* Keyword.Pseudo */
.kr { color: #204a87; font-weight: bold } /* Keyword.Reserved */
.kt { color: #204a87; font-weight: bold } /* Keyword.Type */
.ld { color: #000000 } /* Literal.Date */
.m { color: #0000cf; font-weight: bold } /* Literal.Number */
.s { color: #4e9a06 } /* Literal.String */
.na { color: #c4a000 } /* Name.Attribute */
.nb { color: #204a87 } /* Name.Builtin */
.nc { color: #000000 } /* Name.Class */
.no { color: #000000 } /* Name.Constant */
.nd { color: #5c35cc; font-weight: bold } /* Name.Decorator */
.ni { color: #ce5c00 } /* Name.Entity */
.ne { color: #cc0000; font-weight: bold } /* Name.Exception */
.nf { color: #000000 } /* Name.Function */
.nl { color: #f57900 } /* Name.Label */
.nn { color: #000000 } /* Name.Namespace */
.nx { color: #000000 } /* Name.Other */
.py { color: #000000 } /* Name.Property */
.nt { color: #204a87; font-weight: bold } /* Name.Tag */
.nv { color: #000000 } /* Name.Variable */
.ow { color: #204a87; font-weight: bold } /* Operator.Word */
.w { color: #f8f8f8; text-decoration: underline } /* Text.Whitespace */
.mb { color: #0000cf; font-weight: bold } /* Literal.Number.Bin */
.mf { color: #0000cf; font-weight: bold } /* Literal.Number.Float */
.mh { color: #0000cf; font-weight: bold } /* Literal.Number.Hex */
.mi { color: #0000cf; font-weight: bold } /* Literal.Number.Integer */
.mo { color: #0000cf; font-weight: bold } /* Literal.Number.Oct */
.sb { color: #4e9a06 } /* Literal.String.Backtick */
.sc { color: #4e9a06 } /* Literal.String.Char */
.sd { color: #8f5902; font-style: italic } /* Literal.String.Doc */
.s2 { color: #4e9a06 } /* Literal.String.Double */
.se { color: #4e9a06 } /* Literal.String.Escape */
.sh { color: #4e9a06 } /* Literal.String.Heredoc */
.si { color: #4e9a06 } /* Literal.String.Interpol */
.sx { color: #4e9a06 } /* Literal.String.Other */
.sr { color: #4e9a06 } /* Literal.String.Regex */
.s1 { color: #4e9a06 } /* Literal.String.Single */
.ss { color: #4e9a06 } /* Literal.String.Symbol */
.bp { color: #3465a4 } /* Name.Builtin.Pseudo */
.vc { color: #000000 } /* Name.Variable.Class */
.vg { color: #000000 } /* Name.Variable.Global */
.vi { color: #000000 } /* Name.Variable.Instance */
.il { color: #0000cf; font-weight: bold } /* Literal.Number.Integer.Long */
</style>
<p>
<b>この記事は<a href="https://adventar.org/calendars/2229">TeX & LaTeX Advent Calendar 2017</a>の24日めのために書きました。</b>
</p>
<h2>TeXの中でMarkdownを書ける</h2>
<p>
先月のことなんですが、TeXの、TeXによる、TeXのためのMarkdownパーサをつくました。
</p>
<ul>
<li><b>markdown-tex<br/><a href="https://github.com/k16shikano/markdown-tex">https://github.com/k16shikano/markdown-tex</a></b></li>
</ul>
<p>
TeXで実装されてるので、当然、TeXで書く文書のなかで、シームレスにMarkdownを使えます。
具体的には、こんな感じに、<code>\begin{markdown}</code>から<code>\end{markdown}</code>のなかにMarkdown記法が書けます。
</p>
<pre>
<span class="k">\documentclass</span><span class="nb">{</span>article<span class="nb">}</span>
<span class="k">\usepackage</span><span class="nb">{</span>md<span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>document<span class="nb">}</span>
<span class="k">\begin</span><span class="nb">{</span>markdown<span class="nb">}</span>
# markdown-tex
markdown processor in TeX.
As inline styles, `tt`, *italic*, and **bold** are available.
## subsection
Here is a enumerate list.
1. enumerate
1. in
1. the markdown way
This is an itemize list.
* this block
* will be
* itemized
And a quotation.
> Quote Somethin
> Really **Awesome**!
<span class="k">\end</span><span class="nb">{</span>markdown<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>document<span class="nb">}</span>
</pre>
<p>
これをふつうにTeXで処理すると、記法から期待されるようなPDFができるわけです。
</p>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj45QwJvql87vStqxEEjDd8ESuEvQ0TD35aacG8JXSK1KF4WaaIXLazUKjDmLtCUSjqNesCV4iWoZRBAFzbmTQrwIvZJmlVqxo3a0JppTTQJvTFjkHrXL2qG7u46Cq7arB_RDQ7/s1600/md.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj45QwJvql87vStqxEEjDd8ESuEvQ0TD35aacG8JXSK1KF4WaaIXLazUKjDmLtCUSjqNesCV4iWoZRBAFzbmTQrwIvZJmlVqxo3a0JppTTQJvTFjkHrXL2qG7u46Cq7arB_RDQ7/s400/md.png" width="400" height="321" data-original-width="630" data-original-height="505" /></a>
<p>
とはいっても、先月の時点でサポートしていた記法はそんなに多くなくて、これくらい。
</p>
<ul>
<li>行頭の「<code>#</code>」の個数に応じた見出し化</li>
<li>行頭の「<code>*</code>」で箇条書き</li>
<li>行頭の「<code><</code>」でインデント</li>
<li>行頭の数字で連番箇条書き</li>
<li>行頭スペース4個でインデントするとコードブロック化</li>
<li><code>`..`</code>で囲むとインライン等幅</li>
<li><code>*..*</code>で囲むとインラインイタリック</li>
<li><code>**..**</code>で囲むとインライン強調</li>
</ul>
<p>
これ以外の要素を書きたかったら、いったん<code>\end{markdown}</code>して、生のTeXを書いてください。TeXなので、組版に関することなら、なんでもできます。
</p>
<h2>Markdownの中でTeXを書ける</h2>
<p>
この記事を読んでいる人はみんな<a href="https://texconf2017.tumblr.com/">TeX Conf 2017</a>に参加しているので既知だと思いますが、念のため補足すると、このMarkdownパーサはTeX Conf 2017で発表した「TeXは軽量マークアップ言語の夢を見るか」のために作ったものです。
この発表では、Markdownをはじめとするマークアップ記法と、TeX(LaTeX)によって得られる表現力との関係について考察しました。
「Markdownについて話すのにMarkdownパーサの実装経験がなければ刺されるかも」という強迫観念から取り組んだ、概念実証のための実装です。
</p>
<iframe src="//www.slideshare.net/slideshow/embed_code/key/NqZgmrY6Tc1apl" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/k16shikano/tex-80841192" title="TeXは軽量マークアップの夢を見るか" target="_blank">TeXは軽量マークアップの夢を見るか</a> </strong> from <strong><a href="https://www.slideshare.net/k16shikano" target="_blank">Keiichiro Shikano</a></strong> </div>
<p>
で、TeXのなかでMarkdownを使えるからといってうれしいことはあまりないし、それで済ませるつもりだったですが、せっかくTeXなので、先日ちょっと手を入れて<code>\TeX</code>くらいは生で書けるようにしました。
その副作用で、コントロールシーケンスや数式も入れられるようになりました!
</p>
<pre>
# markdown-tex
markdown processor in TeX.
As inline styles, `tt`, *italic*, and **bold** are available.
Inline equation in <span class="k">\TeX</span> notation <span class="s">$</span><span class="nv">\int</span><span class="nb">_</span><span class="m">0</span><span class="nb">^</span><span class="m">1</span><span class="nv">\frac</span><span class="nb">{</span><span class="m">1</span><span class="nb">}{x}dx </span><span class="o">=</span><span class="nb"> </span><span class="nv">\infty</span><span class="s">$</span>.
<span class="k">\hfill</span> December 24 2017
## subsection
Here is a enumerate list.
1. enumerate
1. in
…
</pre>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhD7rNP5G8Dlm1ulYmeoF9th8dIDpJfWS1NmSs-9grLABXWt57Kob_Eqnn9d_0wbmRlGqIvahvYuemC_m0V6-zA0x2WX6fFWvSYmgeMBTD-MfFB-a5TgAJm8bX9BJnYjoWs7ZRd/s1600/md2.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhD7rNP5G8Dlm1ulYmeoF9th8dIDpJfWS1NmSs-9grLABXWt57Kob_Eqnn9d_0wbmRlGqIvahvYuemC_m0V6-zA0x2WX6fFWvSYmgeMBTD-MfFB-a5TgAJm8bX9BJnYjoWs7ZRd/s400/md2.png" width="400" height="181" data-original-width="604" data-original-height="273" /></a>
<p>
しかし、実はこれは誇大広告で、厳密にいうと2つの条件を満たすマクロやコマンドだけがMarkdown記法の中で使えます。
</p>
<p>
1つめの制約は、完全展開できる必要があるという点です。
たとえば、<code>\sqrt</code>は使えません。
これは、<code>latex.ltx</code>における<code>\sqrt</code>の定義では<code>\@ifnextchar</code>が利用されていて、そのなかでは展開されない<code>\futurelet</code>が使われているからです。
</p>
<p>
なんで完全展開可能性が必要かというと、Markdown記法の構文解析を簡単にするために、対象となるトークンリストをいったん「完全展開された文字列」へと変換しているからです。
これにはexpl3の<code>\tl_set_rescan:Nnx</code>を使っています。
その際、TeXの入力を完全展開すると空白文字が集約されてしまってMarkdown記法として構文解析できなくなるので、これらは文字列とみなして完全展開しています。
</p>
<pre>
<span class="k">\tl</span><span class="nb">_</span>set<span class="nb">_</span>rescan:Nnx <span class="k">\md</span><span class="nb">_</span>tokens
<span class="nb">{</span>
<span class="k">\char</span><span class="nb">_</span>set<span class="nb">_</span>catcode<span class="nb">_</span>letter:n <span class="nb">{</span> 32 <span class="nb">}</span><span class="c">% SPACE</span>
<span class="nb">}</span> <span class="nb">{</span> <span class="k">\BODY</span> <span class="nb">}</span>
</pre>
<p>
これで<code>\md_tokens</code>変数に「完全展開された文字列」が入るので、それを構文解析し、それをTeXの胃袋に送ってPDFを作らせる、というのが先月までの実装でした。
そんなわけで、この状態でMarkdown記法の中に<code>\TeX</code>と書くと、このマクロが完全展開された<code>T\kern -..5ex\hbox E\kern -.\@m</code>がそのままPDFに出てきてしまう状態でした。
</p>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigxbsVmBAI2aLOdpgGuJhqR3n6mUTfASAYEBazpevcSUkxfGtZmdu5gUjGPllwZiiW4XpAjb-JjXFi0-BU6ps8ANyL6Xb6g6ghrpBgF7Q-90iLxFPesqJFN0TMx4wn9kzT_ExK/s1600/tex-espanded.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigxbsVmBAI2aLOdpgGuJhqR3n6mUTfASAYEBazpevcSUkxfGtZmdu5gUjGPllwZiiW4XpAjb-JjXFi0-BU6ps8ANyL6Xb6g6ghrpBgF7Q-90iLxFPesqJFN0TMx4wn9kzT_ExK/s400/tex-espanded.png" width="400" height="57" data-original-width="448" data-original-height="64" /></a>
<p>
では、Markdown記法の中に<code>\TeX</code>と書いて期待する出力結果を得るにはどうすればいいでしょうか?
完全展開をやめればよさそうですが、前述したようにスペースの扱いの都合があるので、文字列にしてからパースするという方針は変えがたい。
となると、完全展開された文字列をパースするときにTeXのプリミティブをパースしてコントロールシーケンスに変換し直し、それをTeXの胃袋に送ればいいのではないか?
</p>
<p>
というわけで、そんなようなコードを追加して、無事に<code>\TeX</code>のようなマクロがMarkdown記法のなかに埋め込めるようになりました。
</p>
<pre>
<span class="k">\cs</span><span class="nb">_</span>new:Npn <span class="k">\inside</span><span class="nb">_</span>cs:Nnnn #1#2#3#4 <span class="nb">{</span>
<span class="k">\tl</span><span class="nb">_</span>set:Nn <span class="k">\car</span><span class="nb">_</span>line <span class="nb">{</span> <span class="k">\tl</span><span class="nb">_</span>head:n <span class="nb">{</span> #4 <span class="nb">}</span> <span class="nb">}</span>
<span class="k">\tl</span><span class="nb">_</span>set:Nn <span class="k">\cdr</span><span class="nb">_</span>line <span class="nb">{</span> <span class="k">\tl</span><span class="nb">_</span>tail:n <span class="nb">{</span> #4 <span class="nb">}</span> <span class="nb">}</span>
<span class="k">\tl</span><span class="nb">_</span>if<span class="nb">_</span>head<span class="nb">_</span>eq<span class="nb">_</span>charcode:nNTF <span class="nb">{</span> #4 <span class="nb">}</span> <span class="nb">{</span> <span class="k">\sp</span><span class="nb">_</span>letter <span class="nb">}</span>
<span class="nb">{</span>
<span class="k">\tl</span><span class="nb">_</span>put<span class="nb">_</span>right:Nn #2 <span class="nb">{</span>
<span class="k">\cs</span>:w #3 <span class="k">\cs</span><span class="nb">_</span>end:
<span class="nb">}</span>
<span class="k">\exp</span><span class="nb">_</span>args:NNnff <span class="k">\parse</span><span class="nb">_</span>to<span class="nb">_</span>end<span class="nb">_</span>line<span class="nb">_</span>with:Nnnn <span class="nb">{</span> #1 <span class="nb">}</span> <span class="nb">{</span> #2 <span class="nb">}</span> <span class="nb">{</span> <span class="nb">}</span> <span class="nb">{</span> <span class="k">\cdr</span><span class="nb">_</span>line <span class="nb">}</span>
<span class="nb">}</span>
<span class="nb">{</span>
<span class="k">\tl</span><span class="nb">_</span>set:Nx <span class="k">\so</span><span class="nb">_</span>far <span class="nb">{</span> #3<span class="k">\car</span><span class="nb">_</span>line <span class="nb">}</span>
<span class="k">\exp</span><span class="nb">_</span>args:NNnff <span class="k">\inside</span><span class="nb">_</span>cs:Nnnn <span class="nb">{</span> #1 <span class="nb">}</span> <span class="nb">{</span> #2 <span class="nb">}</span> <span class="nb">{</span> <span class="k">\so</span><span class="nb">_</span>far <span class="nb">}</span> <span class="nb">{</span> <span class="k">\cdr</span><span class="nb">_</span>line <span class="nb">}</span>
<span class="nb">}</span>
<span class="nb">}</span>
</pre>
<p>
ただし、実装をサボっているので、非標準的(?)な利用方法のコントロールシーケンスはパースできません。
たとえば、<code>\hbot{foo}</code>はいいけど、<code>\hbox to 10pt{foo}</code>とかはだめ。
これがもう1つの制約です。
</p>
<h2>今回のオチ</h2>
<p>
にしても、ここまでにやったことを振り返ると、事実上TeXでTeXをパースしているわけで、むだなことをした感が半端ない……。
</p>
<ol>
<li>TeX記法の入力をTeXでパースし、トークンリストが作られた(TeXの仕事)
<li>トークンリストをMarkdown記法としてパースするために、完全展開して文字列化した(<code>\tl_set_rescan:Nnx</code>)
<li>その文字列からコントロールシーケンスを取り出すのに、あらためてTeX記法のパーサを実装に追加した(<code>\cs_new:Npn \inside_cs:Nnnn</code>)
</ol>
k16http://www.blogger.com/profile/02349067627444091120[email protected]0tag:blogger.com,1999:blog-9197115.post-87537453920217126662017-12-23T12:46:00.000+09:002017-12-23T14:34:27.576+09:00なぜ原稿をテキストで書かなければいけないのか<p><b>これは<a href="https://adventar.org/calendars/2660">編集とライティングにまつわるアレコレ Advent Calendar 2017</a>の23日めの記事です。</b></p>
<p>
原稿をどういう形式・記法で書くべきなのか、という質問をときどき受けます。
一瞬だけ悩むけど、だいたい答えはこうなります。
</p>
<blockquote>
<b>「記法はなんでもいいけど、できればテキスト形式で」</b>
</blockquote>
<p>
今日は、この答えの背景を話します。
</p>
<p>
まずは「なんでもいい」の部分から。
</p>
<h2>記法はなんでもいい</h2>
<p>
出版社や編集者によっては細かく原稿の記法を指定しているようですが、ぼくは特に原稿の記法を決めていません。
これは、そういう記法を決めることができずにここまできた、というのが正直な理由です。
つまり、ぼくの怠慢なんですが、なにも考えずに怠慢であったというよりは、積極的に怠慢になろうと考えた結果なので、そのへんを少し吐露してみます。
</p>
<p>
原稿の記法を決めるということは、執筆者の脳内にあるものを<b>吐き出してもらうための形</b>を決めるということです。
脳内にあるものを他者に見せるための形を決めるわけではありません。
</p>
<p>
しかし、書き手が脳内を吐き出すという行為には、「<b>どう見せたいか</b>」という書き手自身の気持ちがどうしても混ざります。
この、「どう見せたいか」っていうのは、書く内容に合わせて思いつくものだったり、文章化が難しいから逃げるという側面もあったりするので、書く前から全パターンを網羅しきれるものでもありません。
</p>
<p>
で、脳内にあるものを吐き出した原稿と呼ばれる何かを、読者向けの見せ方を意識しながら整理する、そんな専門職があります。
編集者っていうんですけど、編集者によっては「あるドメインの読者にとってうれしい見せ方」から「適切な吐き出し記法」を逆算し、それを自分のキャリアのどこかの時点できちんと整備して、知見として執筆者と共有できている人がいます。
ぼくはそれをサボってきたので、そういう知見をとくに提供できず、「なんでもいいです」という頼りない返事になってしまうというわけでした。
</p>
<p>
ただし、ここからが重要なんですが、考えなしに「なんでもいいです」といっているわけでもありません。
言い訳っぽいですが、吐き出し記法に付随する見え方のほうを意識して見え方に頼った書き方をしてしまったり、汎用のブロック要素を利用した見せ方に依存する書き方が生み出されたり、そういうのを繰り返した結果として、「原稿の記法はあらかじめ決定しないほうがうまくいく」となって現在に至っています。
適切な吐き出し記法をいろいろ考えた結果、適切な吐き出し記法を汎用化すると(少なくともぼくには)うまくいかない、というジレンマに陥ったわけです。
ポジティブにいうと、好きな記法で吐き出してもらうのが執筆者とぼくにとって楽なケースが多いと判断したということです。
</p>
<h2>
できればテキスト形式で
</h2>
<p>
すでに結論めいたものを書いてしまってますが、どう見せるかの検討に移ってよいのは、脳内にある概念をとりあえず文字列として吐き出し、それを文章にして、さらに段落としてしっかり構成した<b>あと</b>です。
もうちょっと正確にいうと、段落の構成を試行錯誤するのと並行して、ようやく見せ方を考えられるようになります。
</p>
<p>
こんなふうに言うと、「はじめに構成をかっちり固めてから書くんじゃ」という声が聞こえてきそうですが、怒られを恐れずにいえば、それは幻想です。
文章を書く前から段落の構成をかっちり固めるには、相当の訓練とあきらめが必要です。
むしろ、文字列をダンプしたものから段落を試行錯誤して練り上げることこそが、文章作成の王道だといえるでしょう。
</p>
<p>
原稿がテキストであることが重要なのは、これが主な理由です。
<b>文字列、文章、段落を行ったり来たりするイテレーション</b>を、コンピュータを使って回しまくるには、<b>テキストデータ</b>がいちばん好都合なのです。
だから、テキストで書いてください。
</p>
<p>
さらに、テキストとして吐き出されていれば、編集者が文章や段落をつくる手伝いができます。
テキストであればどの環境でもエディタで編集できるから、という面もありますが、もっと大きいのは、テキストであれば差分をとったりバージョン管理システムを利用したりすることで、<b>編集者の作業を執筆者から見て透明にできる</b>からです。
</p>
<p>
脳内にある情報を原稿として吐き出すのは、たいへんです。それをさらに文章や段落にするのも、けっこうたいへんです。
だから、後者のほうを手伝う職業として、編集がいるわけです。
しかし、原稿から文章や段落にする過程で、原稿のポイントが失われたり、もともとの執筆者が意図していない情報が紛れ込んだりするのは問題です。
この過程では、「編集者がやったこと」がつまびらかになっている必要があります。
つまり、編集者の作業が執筆者にとって透明である必要があります。
それがコンピュータで不自由なくできるのも、いまのところテキスト形式だけなので、その点でも原稿はテキストにしたいという結論になります。
</p>
<h2>
原稿はソースコード、組版結果はバイナリコード
</h2>
<p>
前述したように、原稿をテキスト形式で書き出し、テキスト形式のまま編集することは、編集者の作業の透明性を高めます。
編集者の作業が透明であるということは、作業結果がすべて執筆者の手元で再現できるということでもあります。
しかも、バージョン管理システムを使えば、元の原稿に対する差分(の積み重ね)という形で再現できます。
</p>
<p>
これは、執筆者が自身の吐き出した原稿をソースコードとして保持し、そのゆくすえを終始自分の管理下におけるという意味でもあります。
わりと見逃されてる点だと感じてるんですが、「原稿を人に見せる形にまで加工するプロセスが、原稿に責任がある本人にとってアンタッチャブルな状態」って、書き手にとっても編集する側にとっても、けっこう怖くないですか?
データとしてアクセスできなければ、どこがどう変わったかをgrepしたり、あとで気づいた用語の間違いを全体にわたって機械的に変換したり、そういう作業が死ぬほどめんどくさくなります。
気に喰わない文章や段落を試行錯誤して手直しすることも、気軽にできなくなってしまいます。
少なくとも、あとは版面に情報を適切に固定するだけという状態になるまでは、編集者はいうまでもなく執筆者自身も原稿にアクセスできるほうがいいはずです。
</p>
<p>
<b>原稿に責任がある人が、原稿への計算機によるアクセスを奪われないため</b>には、そもそも原稿がそれにかなった形式である必要があります。
その形式として妥当なのは、テキストでしょう。
執筆者にもDTPアプリケーションを執筆に使ってもらう、もしくは、執筆者が利用できるワープロソフトで組版もするという可能性もありえなくはないですが、こうした方法は先に言及した「適切な吐き出し形式」に似たジレンマに陥ります。
「こう見えてほしい」という気持ちを前提にして吐き出しをすると、しっかりした文章や段落を構成するのが困難になるのです。
書いている最中に見せ方を工夫したくなってしまうのは、早すぎる最適化の罠だといってもいいでしょう。
まして、WYSIWYG環境で書くのは、バイナリコードを直接いじっているようなものです。
<small>(そもそも、見た目の先にある組版という専門性が要求されるプロセスに、非専門家が手軽に介入できる状態はどうなのかという問題もあります。
原稿がどう見えてほしいかと、その要求をどう実装するかには、さらに一段階ギャップがあるのです。)</small>
</p>
<p>
なんだか、ドキュメントにおける構造とスタイルの分離という、よくある話に収斂しているような気もしますね。
実際、気のせいじゃありません。
この記事で言いたかったことを、構造とスタイルの分離という話に翻訳すると、次のように要約できます。
</p>
<ul>
<li><b>ドキュメントの構造となる部分の試行錯誤では、テキスト形式を使うのが作業面でもっとも理にかなっている</b></li>
<li><b>ドキュメントの構造となる部分は、原稿に責任がある人から最後までアクセスを取り上げるべきでない部分でもあり、それに都合がいいのはテキスト形式である</b></li>
</ul>
<p>
なお、この記事の趣旨は「執筆や編集にはテキストエディタが最高」ではないので、べつにWordとかGoogle Docs、あるいはIDEなどを執筆や編集に使ってもぜんぜん問題ないです。
ただし注意が必要なのは、それらツールにネイティブな形式(.docとか)をソースにしてしまうと、ここに挙げたようなテキストであることの利点が生かせないということです。
なので、どんなツールで書くにしろ、どこかの時点ではテキスト形式にして、それを最終的なソース原稿とするのが無難だとおもいます。
</p>
<h2>
記法が決まらないと前に進めないならMarkdown的なやつで
</h2>
<p>
というわけで、文章を書くときは、「<b>とにかく脳内をダンプし、試行錯誤して段落を組み立てる</b>」のが基本です。
繰り返しになりますが、脳内を吐き出すときの記法は、どう見えてほしいかという気持ちに無意識に依存してしまいます。
その依存を断ち切り、どう見えてほしいかはいったん忘れて文と段落の構成に集中するというのが、一次脱稿でいい状態にもっていくコツ(はやく脱稿するコツではない)です。
「<b>段落だけを書く</b>」という覚悟で望みましょう。
どんな本にも適用できる決定版の見せ方はないけど、万能の書き方というのは実はあるので、<a href="http://amzn.to/2jTpr7b">パラグラフライティングをしっかりやってください</a>。
</p>
<p>
とはいえ、そうはいっても脳内を吐き出すときの記法に何かしら制約があるほうがいいっていう人も少なくないと思います。
段落だけとかストイックすぎて無理、見出しの指定方法やインラインの強調方法とか決まってないと書けない、とくに技術書ではコードブロックや図も入れたい、という要求は当然ありますよね。
</p>
<p>
そんなときは、とりあえず、Markdownふうの記法を使っておきましょう。
ここで、CommonMarkか、それともGitHubFlavoredか、といったことを気にする必要はありません。
見ためを確認したり、そこからワンパスでHTMLやPDFを生成することが目的ではないからです。
ちょっとしたブログ記事ならともかく、どんなMarkdown方言であれ、どのみちMarkdownだけをソースにして本は作れません。
Markdownだけで本が作れたら、XMLとかLaTeXとかとっくに滅んでますね。
</p>
<h2>
まとめ
</h2>
<p>この記事では、なぜ自由な記法のテキスト形式が原稿の執筆と編集で優位性があるかについて、下記の2点に注目して主張しました。</p>
<ul>
<li>どう見せるかは考えず、段落の書き込みに集中するためには、見せ方と表裏一体な記法には惑わされないほうがよい</li>
<li>内容に責任をもつ著者や編集者が、自分たちには手が出せない状態になる直前まで計算機を使って原稿を操作するには、データ形式としてテキストが好都合</li>
</ul>
<p>そのうえで、これらの要求を満足するならツールはテキストエディタでなくてもよいこと、シンプルな段落以外の要素として脳内をダンプする手法としてのMarkdownふう記法の可能性について考えました。</p>
<p>
Markdownについては、また明日なにか書くかもしれません。
</p>k16http://www.blogger.com/profile/02349067627444091120[email protected]0tag:blogger.com,1999:blog-9197115.post-64065919626875580992017-12-06T09:00:00.000+09:002017-12-06T09:58:38.370+09:00英語圏のIT系技術書ブランドについての雑感<p>
<b>この記事は<a href="https://adventar.org/calendars/2258">pyspa Advent Calendar 2017</a>の6日めのために書きましたが、アマゾンアソシエイト目的です。</b>
</p>
<h2>『退屈なことはPythonにやらせよう』が出た</h2>
<p>
2017年にブレイクしたPythonの本といえば、オライリー・ジャパンから発行された<a href="http://amzn.to/2Ayy5iB">『退屈なことはPythonにやらせよう』</a>ですよね。
</p>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=487311778X&linkId=39ce90fc969a9d3dd7865036c0a4ac2f"></iframe>
<p>
実はこの本、そのむかし、自分でも翻訳発行をひそかに検討していたのです。
当時の翻訳者候補の方とのDMをさかのぼってみたら、少なくとも2015年7月以前の話でした。
「非プログラマーでもプログラミングしようぜ」という趣旨で著された本書は、わたし自身の書籍企画の方向性によくマッチしていました。
それで本書に目を付けたのですが、いかんせん分量は多いし、Pythonは日本だと入門者向け言語としていまいち盛り上がらないし(当時の話です)、なにより例題があんまりぐっとこないねという話で、そのときは企画化をパスするという結論を出しました。
これは余談にして重要なポイントでもあるんですが、<a href="http://www.geekpage.jp/blog/?id=2017-12-1-1">それから起きた出来事</a>を思うと、このとき本書を自分が企画化しなかったのは別の意味でも正解でした。
</p>
<p>
それから数年たち、Pythonブームという絶好のタイミングで本書が日本語化され、たくさんの人に読まれるに至ったのは、掛け値なしにとてもうれしいことです(ほんとだよ)。
逃がした魚は大きい的な気持ちもないではないですが、ぶっちゃけると、オライリーという看板で出たことが本書の日本での普及にとってとても大きなことだったと思います。
</p>
<p>
さて、ここで「アレ?」と思う人がいるかもしれません。
「この本はオライリーなのに、オライリーの編集者じゃないおまえが企画を検討してたって、いったいどういうこと?」
</p>
<h2>オライリーの本はO'Reillyの本とは限らない</h2>
<p>
『退屈なことはPythonにやらせよう』の原書は、O'Reilly Mediaではなく、No Starch Pressという北米の出版社による発行です。
</p>
<p>
<a href="https://www.nostarch.com/">https://www.nostarch.com/</a>
</p>
<p>
この出版社の名前を聞くのは初めてという人でも、コンピュータ書に関する情報を気にしている方なら、その発行タイトルのなかには知っているものが少なからずあるでしょう。
No Starch Press発行の本で翻訳されているものを、思いつく限りざっと並べてみます(もちろん全部ではありません(たぶん))。
</p>
<ul>
<li>『<a href="http://amzn.to/2AxOl3s">退屈なことはPythonにやらせよう</a>』</li>
<li>『<a href="http://amzn.to/2BLVCgi">すごいHaskellたのしく学ぼう! </a>』</li>
<li>『<a href="http://amzn.to/2AxOnZ8">Land of Lisp</a>』</li>
<li>『<a href="http://amzn.to/2AtKmqp">すごいErlangゆかいに学ぼう! </a>』</li>
<li>『<a href="http://amzn.to/2Ay5oSQ">Rubyのしくみ</a>』</li>
<li>『<a href="http://amzn.to/2jVZUJF">たのしいプログラミング Pythonではじめよう! </a>』</li>
<li>『<a href="http://amzn.to/2AzjEL0">プログラマの考え方がおもしろいほど身につく本</a>』</li>
<li>『<a href="http://amzn.to/2Aua2Dm">サイバーセキュリティプログラミング</a>』</li>
<li>『<a href="http://amzn.to/2AuKeaf">Hacking: 美しき策謀</a>』</li>
<li>『<a href="http://amzn.to/2Ay65eU">Pythonからはじめる数学入門</a>』</li>
</ul>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=487311778X&linkId=e76af51529a39c408687b8dbb95186b9"></iframe>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=4274068854&linkId=879f6341f37ce49a4214f2733558be27"></iframe>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=4873115876&linkId=9c360f195d489c585c7a8b3caaf7dfa2"></iframe>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=4274069125&linkId=bec21ffc05641f562a1efdac9ec69631"></iframe>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=4274050653&linkId=c4ef07be384ff7cdfa778f2a3104aa0a"></iframe>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=4274069443&linkId=2ebe7c1de8ff65d9a9621e904f26dac4"></iframe>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=4048869558&linkId=fa2e47f044a4ad1bdc4029aceffa0939"></iframe>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=4873117313&linkId=0e249bc3f5fca14c2ef09b1a812992ff"></iframe>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=4873115140&linkId=3f6c66cc7f683b9779d270140a04f752"></iframe>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=4873117682&linkId=d1edda5f824adbf34686f5727f029f32"></iframe>
<p>
そうそうたるラインナップですよね。
さらに面白いことに、No Starch Pressは『マンガでわかる統計学』などの英語版の出版社でもあります。
</p>
<ul>
<li>『<a href="http://amzn.to/2BLpCZG">The Manga Guide to Statistics</a>』</li>
<li>『<a href="http://amzn.to/2Ayz2rb">The Manga Guide to Linear Algebra</a>』</li>
<li>『<a href="http://amzn.to/2jVCTGH">The Manga Guide to the Universe</a>』</li>
</ul>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=1593271891&linkId=fbfe179302be325aeda60f7965ebbdf0"></iframe>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=1593274130&linkId=354f90c64f5fae93d5d76f3061cde1c1"></iframe>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=1593272677&linkId=4356762379950bf569c7c642baa60460"></iframe>
<p>
いまではこんなにすごいNo Starch Pressですが、もとはBill Pollockという人が立ち上げた小さな出版社でした。
2006年にBillさんに会ったころもまだまだ小さい出版社でしたが、この10年くらいで一気に魅力的なラインナップを増やし、いまではIT系技術書界隈でかなりの存在感を示しています。
ここでまた余談だけど重要なポイントとして、2006年にBillさんに『マンガでわかる統計学』の版権買ってよという話をするとき、「エディターです」と自己紹介したら、「おれはパブリッシャーだぜ」と冗談で返されたのが自分のなかではものすごい衝撃で、いつかおれもパブリッシャーって名乗るぞとぼんやり思ったのでした
(もっともBillさんはぼくのことさえ覚えてない気がする)。
</p>
<p>
話をもどすと、上記のNo Starch Pressの翻訳書のなかには、『退屈なことはPythonにやらせよう』以外にも、いくつかオライリー・ジャパン発行のものが含まれています。
つまりオライリー・ジャパンから発行されている翻訳書は、必ずしも世界的な技術書ブランドであるO'Reilly Mediaのタイトルだけではないのです。
オライリー・ジャパンの中の人は、No Starch Pressをはじめ、さまざまな海外の出版社からこれはと思う良タイトルをO'Reilly Mediaに限らず探してきて翻訳発行しているわけです。
これぞO'Reillyというカバーだけど動物の版画でない本がけっこうあるのは(宇宙人までいる)、そういうわけなのです。
</p>
<p>
No Starch Press以外で、日本ではO'Reillyブランドの技術書として誤認されてるんじゃないかなと感じてる本としては、たとえばこんな例があります。
</p>
<ul>
<li>『<a href="http://amzn.to/2BLxH0g">コンピュータシステムの理論と実装</a>』</li>
<li>『<a href="http://amzn.to/2Ayz4iN">SQLアンチパターン</a>』</li>
<li>『<a href="http://amzn.to/2AteIJS">Go言語によるWebアプリケーション開発</a>』</li>
<li>『<a href="http://amzn.to/2AxiUGd">シングルページWebアプリケーション</a>』</li>
<li>『<a href="http://amzn.to/2BOj3FB">入門 React</a>』</li>
<li>『<a href="http://amzn.to/2jWjkhH">Effective Python</a>』</li>
</ul>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=4873117127&linkId=6e532a38397ddec05be52b588161304e"></iframe>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=4873115892&linkId=edf179f6fc5aa7ed77dbd7c247d55e25"></iframe>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=4873117526&linkId=38d87709da17617c6835962cce6df704"></iframe>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=4873116732&linkId=0f933cc821b2205c16879fa3d5f44814"></iframe>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=4873117194&linkId=1cbca12888bb5ed882dee3163bb2dc7e"></iframe>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=4873117569&linkId=46e075f5c0830e9587f03229851ff70d"></iframe>
<p>
上記6点は、すべて原書出版社がちがいます。当ててみよう。<small>(<a href="https://twitter.com/CardinalXaro/status/938203973198102529">Hayao(-ε-δ) さんに教えていただいたので</a>アソシエイト効果がありそうなほうを追記しました。Hayao(-ε-δ) さんありがとうございます!)</small>
</p>
<p>
なお、逆のパターンである「O'Reillyの本がオライリーから出ているとは限らない」も真です。
ただし、最近はO'Reilly Mediaのラインナップの魅力が落ちてるのと、O'Reillyブランドで魅力的なのはオライリー・ジャパンがしっかり出してくるので、ほぼオライリー・ジャパンから出てきているように見えます。
</p>
<h2>動物だけではない英語圏の技術書ブランド</h2>
<p>
ここまで長々とアマゾンアソシエイトを張りまくってきましたが、ここからが本記事のタイトルでもある「<b>雑感</b>」です。
</p>
<p>
2017年現在の<b>英語圏における</b>IT系出版社のブランド地図は、たとえば2000年代前半のそれとはかなり変動しています。
2000年代前半は、その当時で創業20年くらいのイケイケO'Reilly Mediaに圧倒的なブランド力がありました。
しかし現在は、この記事でも一押しのNo Starch Pressはじめ、やはり中堅どころの<a href="https://www.manning.com/">Manning Publications</a>など、現時点で創業20年前後を迎えている中小の出版社のほうがむしろ精力的に面白い書籍を生み出している印象があります。
彗星のごとく登場してあっというまに手堅い出版社となった<a href="https://pragprog.com/">Pragmatic Bookshelf</a>も、これから創業20年前後にかけて、もうひと化けするかもしれません。
</p>
<p>
そうした出版社に比べると、すでに40年近い歴史を持つO'Reilly Mediaは、経営規模で見ても大手出版社として網羅的なラインナップを擁し、中小出版社の書籍の発売元として流通を支える存在にまで成長していますが、発行書籍の面白さとかクオリティという点では最近ぱっとしないなというのが率直な感想です。
それに呼応するように、いま企画が好調なオライリー・ジャパンが、少なくとも翻訳書についてO'Reillyタイトル依存でなくなっているというのは感慨深いところです。
そういえばオライリー・ジャパンも、いまちょうど創業20年ちょっとですね。
</p>
<p>
一方、O'Reilly Mediaよりさらに老舗のPearsonや、そのハイエンドコンピュータ書籍のレーベルとしてのAddison-Wesleyは、タイトル数こそ多くないですが、IT系技術書出版社としての信頼感はいまなお顕在だなあと感じることがわりとあります。
タイトルに対する信頼感という意味では、The MIT PressやCambridge University Pressなどの大学出版系も依然として強くて、これからも日本語で読めるようにしていくべきだと思えるような本はこのへんの老舗出版社のものがますます多くなるのかも、と思っています。
</p>
<p>
精力的といえば、英国を拠点に爆発的にラインナップを増やして一気に存在感を増した<a href="https://www.packtpub.com/">Packt</a>という出版社もあります。
Packtの特徴は、とにかく最速であらゆるIT系のトピックについて書籍の形をしたものをそろえるという戦略です。
そうしたラインナップ網羅主義は、ある意味ではO'Reilly Mediaが目指してきたところだとも思います。
ラインナップ網羅主義には、個別のタイトルの出来不出来をケアできないという面があるので、個人的には避けていきたい方向性ですが、いかんせん展開が速いので、Packtの傾向にも注目だけはしていこうと思っています。
</p>
<h2>今回のオチ</h2>
<p>
日本語圏におけるIT系技術書の状況については、あまり大きなことを言える立場にないですが、いろんな人たちの紆余曲折とか踏ん張りとか地道な出版活動とかあって、いろんなブランドが盛り上がったり、消えたり、地に落ちたり、新しく誕生したりしています。
</p>
<p>
そんななかで、この記事をここまで読んでアマゾンアソシエイトを踏まなかった方には、<a href="https://lambdanote.com">2017年に4つのタイトルを発売して始動したラムダノートというIT系技術書出版社</a>の名前を覚えてもらえるとうれしいです。
</p>
k16http://www.blogger.com/profile/02349067627444091120[email protected]0tag:blogger.com,1999:blog-9197115.post-55339374248623353552017-12-03T21:41:00.001+09:002017-12-06T04:44:11.519+09:00TeXでつくる『RubyでつくるRuby』<style type="text/css">
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.bn { color: #40a070; } /* BaseN */
code span.fl { color: #40a070; } /* Float */
code span.ch { color: #4070a0; } /* Char */
code span.st { color: #4070a0; } /* String */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.ot { color: #007020; } /* Other */
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.fu { color: #06287e; } /* Function */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code span.cn { color: #880000; } /* Constant */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.ss { color: #bb6688; } /* SpecialString */
code span.im { } /* Import */
code span.va { color: #19177c; } /* Variable */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.op { color: #666666; } /* Operator */
code span.bu { } /* BuiltIn */
code span.ex { } /* Extension */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.at { color: #7d9029; } /* Attribute */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
</style>
<p>
<b>この記事は<a href="https://adventar.org/calendars/2229">TeX & LaTeX Advent Calendar 2017</a>の3日めのために書きましたが、宣伝目的です。</b>
</p>
<p><a href="https://adventar.org/calendars/2229">TeX & LaTeX Advent Calendar 2017</a>の重点テーマは「TeXでつくるアレ」とのことですが、偶然にも2017年、よく似たタイトルの<a href="https://www.lambdanote.com/products/ruby-ruby">『RubyでつくるRuby』</a>(遠藤侑介著)という本が出ました。
プログラミング言語を学ぶときの例題としてプログラミング言語をつくる以上に格好のネタはない、という趣旨の本です。</p>
<a href="https://www.lambdanote.com/collections/frontpage/products/ruby-ruby">
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJQThK9uiWHlM6RFNU9CnQ8AKTCxaBCHLyxIjlDsXm2rRhuBT1pegeRRl8LT7smvS5wu7TfjTa-RlifzDdT-G4JI6x3aY3SSt1kyOUww7HeRHG2qMaX27hzHrbzJvhJvkQbYnI/s1600/ruby-ruby-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJQThK9uiWHlM6RFNU9CnQ8AKTCxaBCHLyxIjlDsXm2rRhuBT1pegeRRl8LT7smvS5wu7TfjTa-RlifzDdT-G4JI6x3aY3SSt1kyOUww7HeRHG2qMaX27hzHrbzJvhJvkQbYnI/s200/ruby-ruby-1.png" width="141" height="200" data-original-width="400" data-original-height="569" /></a></div></a>
<ul>
<li><a href="https://www.lambdanote.com/products/ruby-ruby">ラムダノートの直販で『RubyでつくるRuby』を買う</a></li>
<li><a href="https://honto.jp/netstore/pd-book_28490380.html">Hontoで『RubyでつくるRuby』を買う</a></li>
<li><a href="https://www.amazon.co.jp/Ruby%E3%81%A7%E3%81%A4%E3%81%8F%E3%82%8BRuby-%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89%E5%AD%A6%E3%81%B3%E3%81%AA%E3%81%8A%E3%81%99%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9E%E5%85%A5%E9%96%80-%E9%81%A0%E8%97%A4%E4%BE%91%E4%BB%8B/dp/4908686017/ref=sr_1_3?m=A2KDK3NSLPB7MM&s=merchant-items&ie=UTF8&qid=1512203621&sr=1-3">ラムダノートのAmazonマーケットプレイスで『RubyでつくるRuby』を買う</a></li>
</ul>
<p>プログラミング言語をつくるというと、なにやら難しく聞こえるかもしれませんが、<a href="https://www.lambdanote.com/products/ruby-ruby">『RubyでつくるRuby』</a>では、わずか150ページのなかにそのエッセンスを凝縮しています。
本文の理解を助けるかわいらしいイラストもフルカラーでふんだんに用意されているので、はじめてプログラムを書いてみようかなという人でも、おそらく(願わくば)読み通せる内容です。
電子書籍はなく、古き良き紙の本のみですが、電子版がいいという人は<a href="http://ascii.jp/elem/000/001/230/1230449/">Ascii.jpでもとになった連載が読める</a>ので、そちらをどうぞ!</p>
<h2>プログラミング言語の処理系が扱うデータは「木」</h2>
<p><a href="https://www.lambdanote.com/products/ruby-ruby">『RubyでつくるRuby』</a>では、プログラミング言語Rubyで書かれたプログラムを処理して実行するプログラミング言語を、プログラミング言語Rubyでつくります。
つまり、本書の読者が書くことになるプログラムが処理するのは、Rubyのプログラムです。</p>
<p>Rubyに限りませんが、多くのプログラミング言語では、プログラマーが書いたプログラムを実行する前に、そのプログラムをまず「木」と呼ばれる種類のデータへと変換します。
この「木」は、その名のとおり樹木のような姿をしていて、「枝がのびる節」と「葉」があります。</p>
<p>このへんは、文章で説明するよりも、絵で見るほうがはやいでしょう。
たとえば、次のようなRubyのプログラム(四則演算だけですが)がどんな木になるかというと……</p>
<div class="sourceCode"><pre class="sourceCode ruby"><code class="sourceCode ruby">(<span class="dv">1</span> + <span class="dv">2</span>) / <span class="dv">3</span> * <span class="dv">4</span> * (<span class="dv">56</span> / <span class="dv">7</span> + <span class="dv">8</span> + <span class="dv">9</span>)</code> </pre></div>
<p style="text-indent:0em;">こんな木になります。式で見るより、項どうしの演算の関係がわかりやすいですね。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKTDtVwPxKOEPAc338m69YrvRDfIFZySMy43gArKRWt1UgvENhs2c3QwMgbQ8gAc9FcjwsVMpaF1zsDpt8Oy_Q-XJVrrhkKdND38hmlHs_blo4CBMFEWxvSqq5mDhUiB4VEPKO/s1600/4-tree-09.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKTDtVwPxKOEPAc338m69YrvRDfIFZySMy43gArKRWt1UgvENhs2c3QwMgbQ8gAc9FcjwsVMpaF1zsDpt8Oy_Q-XJVrrhkKdND38hmlHs_blo4CBMFEWxvSqq5mDhUiB4VEPKO/s320/4-tree-09.png" width="320" height="307" data-original-width="669" data-original-height="641" /></a></div>
<p>本書の解説には「木」を扱う場面がたくさん出てくるので、説明文やコードに加えてこんな具合に木の絵をたくさん用意できれば、いま説明しているデータの姿がどんなようすなのか「ひとめ」でわかります。
なので、ぜひ木の絵はたくさん載せたい。</p>
<p>かといって、こういう木の絵をぜんぶイラストレーターさんに描いてもらうのもたいへんです。
描くほうだけでなく、間違ってないかチェックするほうもめんどくさい。
それなりの見た目で、なおかつ間違いなくプログラムの木を描くには、どうすればいいでしょうか?</p>
<p>そう、TeXを使えばいいのです。
実際、上に例として出した木もTeXで生成しています。</p>
<h2 id="tex">TeXで木を描く</h2>
<p>というわけで、前置きが長くなりましたが、<a href="https://www.lambdanote.com/products/ruby-ruby">『RubyでつくるRuby』</a>の木の絵をTeXでどう描いたかをちょっと紹介します。
書籍<a href="https://www.lambdanote.com/products/ruby-ruby">『RubyでつくるRuby』</a>では、プログラムの木を、Rubyにおける配列表現からTeXで生成しました。
これなら手間もかからず、なにより作図にともなう間違いもありません。</p>
<h3 id="tikz-qtree">tikz-qtreeパッケージの使い方</h3>
<p>木は、プログラムに限らずいろいろな場面に出てくるデータ構造なので、関連するTeXパッケージがわりとたくさん出そろっています。
そのなかで<a href="https://www.lambdanote.com/products/ruby-ruby">『RubyでつくるRuby』</a>の木を描くのに選んだのは、 <code>tikz-qtree</code> というTikZベースのパッケージです。</p>
<p><a href="https://ctan.org/pkg/tikz-qtree" class="uri">https://ctan.org/pkg/tikz-qtree</a></p>
<p>この <code>tikz-qtree</code> パッケージを選んだ理由のひとつは、上下逆向きの木構造を手軽に描けることです。
木構造を描くときは、根を上にする(つまり本物の樹木でいったら上下逆)ことが多いのですが、本書の場合にはイラストにある本物っぽい木の絵とシームレスに読み替えてもらいたいので、根を下にして木構造を描ける機能が重要だったのです。</p>
<p> <code>tikz-qtree</code> のミニマルな例を示します。これは <code>2 * 4</code> というRubyプログラムの「木」の例です。</p>
<div class="sourceCode"><pre class="sourceCode latex"><code class="sourceCode latex"><span class="bu">\documentclass</span>[tikz,convert={outext=.png}]{<span class="ex">standalone</span>}
<span class="bu">\usepackage</span>{<span class="ex">tikz-qtree</span>}
<span class="kw">\begin</span>{<span class="ex">document</span>}
<span class="kw">\begin</span>{<span class="ex">tikzpicture</span>}
<span class="fu">\Tree</span> [.*
[2
<span class="fu">\node</span>[draw]{4};
]]
<span class="kw">\end</span>{<span class="ex">tikzpicture</span>}
<span class="kw">\end</span>{<span class="ex">document</span>}</code> </pre></div>
<p> <code>\Tree[ ]</code> のなかに、木を描いてきます。
<code>[ ]</code> を入れ子にすると、その中に書いたものが子どもの要素になります。
要素としてスペース区切りで値を書き込めば、それが葉になります。
子を持つ要素には、値の前に「 <code>.</code> 」をつけます。
上の例では、根にあたる「 <code>*</code> 」に「 <code>.</code> 」が必要です。
さらに上の例では、TikZの <code>\node</code> 命令がそのまま使えることを示すために、「4」のほうだけ枠をつけてみました( <code>\node</code> 命令なので末尾に <code>;</code> を忘れずに!)。</p>
<p>上記を <code>tree.tex</code> として保存し、以下のようにpdflatexで処理すれば……</p>
<div class="sourceCode"><pre class="sourceCode sh"><code class="sourceCode bash">$ <span class="ex">pdflatex</span> --shell-escape tree.tex</code> </pre></div>
<p style="text-indent:0em;">こんな絵が得られます。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjRB1cpSg-6XfQBuq7OzfCPb4NsICVF2YtOaVEs0ufJrM9DI2kVR0_nYzGgDtulrTwJUPFCcnu8Nh03R9hcOtuuSK5sE3-WxLdIfMmWWO5ML8IyGLPyI71UxFzsAin6-cZ8QPw/s1600/4-tree.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjRB1cpSg-6XfQBuq7OzfCPb4NsICVF2YtOaVEs0ufJrM9DI2kVR0_nYzGgDtulrTwJUPFCcnu8Nh03R9hcOtuuSK5sE3-WxLdIfMmWWO5ML8IyGLPyI71UxFzsAin6-cZ8QPw/s320/4-tree.png" width="111" height="320" data-original-width="107" data-original-height="309" /></a></div>
<p>この木の上下をさかさまにするには、 <code>tikzpicture</code> 環境に <code>[grow'=up]</code> というオプションをつけるだけです。</p>
<div class="sourceCode"><pre class="sourceCode latex"><code class="sourceCode latex"><span class="bu">\documentclass</span>[tikz,convert={outext=.png}]{<span class="ex">standalone</span>}
<span class="bu">\usepackage</span>{<span class="ex">tikz-qtree</span>}
<span class="kw">\begin</span>{<span class="ex">document</span>}
<span class="kw">\begin</span>{<span class="ex">tikzpicture</span>}[grow'=up]
<span class="fu">\Tree</span> [.*
[2
<span class="fu">\node</span>[draw]{4};
]]
<span class="kw">\end</span>{<span class="ex">tikzpicture</span>}
<span class="kw">\end</span>{<span class="ex">document</span>}</code> </pre></div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfAoXP41wBnBTTSOyxPAKooo6dtq3_mGnYsZ1EwSHtStHVNnajRp5mDM8qjYIkYM2PoyjlCArij2PCj_sZeLt9etvDXRHrnmR9m2k0vVsD9NW35RjGAimmnqxXcJDISSgPMhFg/s1600/4-tree-upside.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfAoXP41wBnBTTSOyxPAKooo6dtq3_mGnYsZ1EwSHtStHVNnajRp5mDM8qjYIkYM2PoyjlCArij2PCj_sZeLt9etvDXRHrnmR9m2k0vVsD9NW35RjGAimmnqxXcJDISSgPMhFg/s320/4-tree-upside.png" width="113" height="320" data-original-width="107" data-original-height="304" /></a></div>
<p>このままだと絵として味気ないので、色をぬったり、枠の形を変えたり、線の幅を調整したりするわけですが、そのへんはTikZの <code>\node</code> をごにょごにょいじるというつまらない話なので割愛します。
<a href="https://ctan.org/pkg/pgf">TikZのマニュアル</a>(むかしは400ページくらいでしたが、いまでは1000ページ超)を片手にがんばってみてください。</p>
<h3 id="tikz">TikZソースを木のソースから生成する</h3>
<p>木の見た目を整えたら、毎回TikZを手描きするのはばかばかしいので、プログラムで生成するようにします。
<a href="https://www.lambdanote.com/products/ruby-ruby">『RubyでつくるRuby』</a>で描きたいのはプログラムを表す木で、その木はRubyコードとしてはこんなふうな姿をしています。</p>
<div class="sourceCode"><pre class="sourceCode ruby"><code class="sourceCode ruby">[<span class="st">"*"</span>, <span class="dv">2</span>, <span class="dv">4</span>]</code> </pre></div>
<p>本当は、 <code>2</code> とか <code>4</code> が何ものであるかを表すために、もうちょっとメタ情報がついていますが、だいたいこんな感じです。
(そもそも、配列でプログラムの木を表すのはあくまでも<a href="https://www.lambdanote.com/products/ruby-ruby">『RubyでつくるRuby』</a>の中に限定した話で、じっさいのRubyではまったくべつの表現方法です。)</p>
<p>これはどう見てもS式なので、カンマを削除してGaucheで直接読み込んで変換し、 <code>tikz-qtree</code> パッケージを使った木を描くTeXソースを吐くようにしましょう。</p>
<div class="sourceCode"><pre class="sourceCode scheme"><code class="sourceCode scheme">(use srfi<span class="dv">-13</span>)
(use text.tree)
(<span class="kw">define</span><span class="fu"> </span>(deco-b b)
#<span class="st">"</span><span class="ch">\\</span><span class="st">node[text=white,inner sep=4pt,drop shadow,fill={rgb:blue,5;white,1;green,1},draw,rounded corners]{</span><span class="ch">\\</span><span class="st">small ~b};"</span>)
(<span class="kw">define</span><span class="fu"> </span>(deco-l l)
#<span class="st">"</span><span class="ch">\\</span><span class="st">node[text=white,inner sep=2pt,drop shadow,fill={rgb:green,6;white,1;black,4},draw,ellipse]{</span><span class="ch">\\</span><span class="st">mystrut</span><span class="ch">\\</span><span class="st">smash{~l}};"</span>)
(<span class="kw">define</span><span class="fu"> *before-tikz* </span><span class="st">"\</span>
<span class="st">\n</span><span class="ch">\\</span><span class="st">begin{tikzpicture}[grow'=up] \</span>
<span class="st">\n </span><span class="ch">\\</span><span class="st">tikzset{ \</span>
<span class="st">\n every tree node/.style={font=</span><span class="ch">\\</span><span class="st">ttfamily</span><span class="ch">\\</span><span class="st">large}, \</span>
<span class="st">\n edge from parent/.append style={very thick}} \</span>
<span class="st">\n </span><span class="ch">\\</span><span class="st">Tree "</span>)
(<span class="kw">define</span><span class="fu"> *end-tikz* </span><span class="st">"\n</span><span class="ch">\\</span><span class="st">end{tikzpicture}\n</span><span class="ch">\\</span><span class="st">clearpage\n"</span>)
(<span class="kw">define</span><span class="fu"> *before-doc* </span><span class="st">"\</span>
<span class="st">\n</span><span class="ch">\\</span><span class="st">documentclass[tikz,border=10pt,convert={outext=.png}]{standalone} \</span>
<span class="st">\n</span><span class="ch">\\</span><span class="st">def</span><span class="ch">\\</span><span class="st">mystrut{</span><span class="ch">\\</span><span class="st">rule{0pt}{1.3ex}} \</span>
<span class="st">\n</span><span class="ch">\\</span><span class="st">usepackage{tikz} \</span>
<span class="st">\n</span><span class="ch">\\</span><span class="st">usepackage{tikz-qtree} \</span>
<span class="st">\n</span><span class="ch">\\</span><span class="st">usetikzlibrary{shapes.geometric,shadows}% \</span>
<span class="st">\n</span><span class="ch">\\</span><span class="st">begin{document}\n"</span>)
(<span class="kw">define</span><span class="fu"> *end-doc* </span><span class="st">"\n</span><span class="ch">\\</span><span class="st">end{document}\n"</span>)
(<span class="kw">define</span><span class="fu"> </span>(tikzqtree ts)
(<span class="kw">list</span> *before-tikz* (mkqtree ts) *end-tikz*))
(<span class="kw">define</span><span class="fu"> </span>(mkqtree ts)
(<span class="kw">cond</span> ((<span class="kw">null?</span> ts) <span class="st">""</span>)
((<span class="kw">pair?</span> ts) (mkbranch
(<span class="kw">car</span> ts)
(map mkqtree (<span class="kw">cdr</span> ts))))
(<span class="kw">else</span> (mkleaf ts))))
(<span class="kw">define</span><span class="fu"> </span>(mkbranch b l)
(<span class="kw">list</span> <span class="st">"[."</span> (deco-b (x->string b)) <span class="st">"\n "</span> l <span class="st">"]"</span>))
(<span class="kw">define</span><span class="fu"> </span>(mkleaf l)
(<span class="kw">list</span> (deco-l (x->string l)) <span class="st">" "</span>))
(<span class="kw">define</span><span class="fu"> </span>(main args)
(<span class="kw">call-with-input-file</span> (<span class="kw">cadr</span> args)
(<span class="kw">lambda</span> (p)
(print
(tree->string
(<span class="kw">list</span>
*before-doc*
(map tikzqtree (port->sexp-list p))
*end-doc*))))))</code> </pre></div>
<p>カンマをプログラムで削除しないのは、カンマなしならS式としてそのまま<code>read</code>できるからです。この手のユーティリティはコーディングが簡単なほうに倒してガッっと書いてしまうのが肝要だと思います。</p>
<h3>実行結果</h3>
<p>最初に紹介した、わりと複雑なかっこうをしている次のようなRubyの計算式について、プログラムの木を描いてみましょう。</p>
<div class="sourceCode"><pre class="sourceCode ruby"><code class="sourceCode ruby">(<span class="dv">1</span> + <span class="dv">2</span>) / <span class="dv">3</span> * <span class="dv">4</span> * (<span class="dv">56</span> / <span class="dv">7</span> + <span class="dv">8</span> + <span class="dv">9</span>)</code> </pre></div>
<p>この計算式は、<a href="https://www.lambdanote.com/products/ruby-ruby">『RubyでつくるRuby』</a>ではこんな感じの木(配列の配列)として表されます。</p>
<div class="sourceCode"><pre class="sourceCode ruby"><code class="sourceCode ruby">[<span class="st">"*"</span>, [<span class="st">"*"</span>, [<span class="st">"/"</span>, [<span class="st">"+"</span>, <span class="dv">1</span>, <span class="dv">2</span>], <span class="dv">3</span>], <span class="dv">4</span>], [<span class="st">"+"</span>, [<span class="st">"+"</span>, [<span class="st">"/"</span>, <span class="dv">56</span>, <span class="dv">7</span>], <span class="dv">8</span>], <span class="dv">9</span>]]</code> </pre></div>
<p>この一行をファイルに保存して、カンマだけエディタで削除し、先ほどのGaucheスクリプトで読み込むと……</p>
<div class="sourceCode"><pre class="sourceCode sh"><code class="sourceCode bash">$ <span class="ex">gosh</span> mktree.scm temp.rb > temp.tex</code> </pre></div>
<p style="text-indent:0em;">こんな気持ちの悪いLaTeXのソースができます。</p>
<div class="sourceCode"><pre class="sourceCode latex"><code class="sourceCode latex"><span class="bu">\documentclass</span>[tikz,border=10pt,convert={outext=.png}]{<span class="ex">standalone</span>}
<span class="fu">\def</span>\mystrut{\rule{0pt}{1.3ex}}
<span class="bu">\usepackage</span>{<span class="ex">tikz</span>}
<span class="bu">\usepackage</span>{<span class="ex">tikz-qtree</span>}
<span class="fu">\usetikzlibrary</span>{shapes.geometric,shadows}<span class="co">%</span>
<span class="kw">\begin</span>{<span class="ex">document</span>}
<span class="kw">\begin</span>{<span class="ex">tikzpicture</span>}[grow'=up]
<span class="fu">\tikzset</span>{
every tree node/.style={font=<span class="fu">\ttfamily\large</span>},
edge from parent/.append style={very thick}}
<span class="fu">\Tree</span> [.<span class="fu">\node</span>[text=white,inner sep=4pt,drop shadow,fill={rgb:blue,5;white,1;green,1},draw,rounded corners]{<span class="fu">\small</span> *};
[.<span class="fu">\node</span>[text=white,inner sep=4pt,drop shadow,fill={rgb:blue,5;white,1;green,1},draw,rounded corners]{<span class="fu">\small</span> *};
[.<span class="fu">\node</span>[text=white,inner sep=4pt,drop shadow,fill={rgb:blue,5;white,1;green,1},draw,rounded corners]{<span class="fu">\small</span> /};
[.<span class="fu">\node</span>[text=white,inner sep=4pt,drop shadow,fill={rgb:blue,5;white,1;green,1},draw,rounded corners]{<span class="fu">\small</span> +};
<span class="fu">\node</span>[text=white,inner sep=2pt,drop shadow,fill={rgb:green,6;white,1;black,4},draw,ellipse]{<span class="fu">\mystrut\smash</span>{1}}; <span class="fu">\node</span>[text=white,inner sep=2pt,drop shadow,fill={rgb:green,6;white,1;black,4},draw,ellipse]{<span class="fu">\mystrut\smash</span>{2}}; ]<span class="fu">\node</span>[text=white,inner sep=2pt,drop shadow,fill={rgb:green,6;white,1;black,4},draw,ellipse]{<span class="fu">\mystrut\smash</span>{3}}; ]<span class="fu">\node</span>[text=white,inner sep=2pt,drop shadow,fill={rgb:green,6;white,1;black,4},draw,ellipse]{<span class="fu">\mystrut\smash</span>{4}}; ][.<span class="fu">\node</span>[text=white,inner sep=4pt,drop shadow,fill={rgb:blue,5;white,1;green,1},draw,rounded corners]{<span class="fu">\small</span> +};
[.<span class="fu">\node</span>[text=white,inner sep=4pt,drop shadow,fill={rgb:blue,5;white,1;green,1},draw,rounded corners]{<span class="fu">\small</span> +};
[.<span class="fu">\node</span>[text=white,inner sep=4pt,drop shadow,fill={rgb:blue,5;white,1;green,1},draw,rounded corners]{<span class="fu">\small</span> /};
<span class="fu">\node</span>[text=white,inner sep=2pt,drop shadow,fill={rgb:green,6;white,1;black,4},draw,ellipse]{<span class="fu">\mystrut\smash</span>{56}}; <span class="fu">\node</span>[text=white,inner sep=2pt,drop shadow,fill={rgb:green,6;white,1;black,4},draw,ellipse]{<span class="fu">\mystrut\smash</span>{7}}; ]<span class="fu">\node</span>[text=white,inner sep=2pt,drop shadow,fill={rgb:green,6;white,1;black,4},draw,ellipse]{<span class="fu">\mystrut\smash</span>{8}}; ]<span class="fu">\node</span>[text=white,inner sep=2pt,drop shadow,fill={rgb:green,6;white,1;black,4},draw,ellipse]{<span class="fu">\mystrut\smash</span>{9}}; ]]
<span class="kw">\end</span>{<span class="ex">tikzpicture</span>}
<span class="fu">\clearpage</span>
<span class="kw">\end</span>{<span class="ex">document</span>}</code> </pre></div>
<p>これをコンパイルすると……</p>
<div class="sourceCode"><pre class="sourceCode sh"><code class="sourceCode bash">$ <span class="ex">pdflatex</span> --shell-escape temp.tex</code> </pre></div>
<p style="text-indent:0em;">冒頭に掲載したような、こんなきれいなpngファイルが得られるというわけでした。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisc3Dy4h2GUm1dM7DJNwwrL8KFc1oTIElKfAutVrcgXv9JEdHC53E0rI6BnkxeFHP_xyj8iC3Cbe0SRGoqfV5xF6pmT9ITXm052dvD95gR8Q1ynooJSAiMUhFHJbxeIzlH0gZ2/s1600/4-tree-09.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisc3Dy4h2GUm1dM7DJNwwrL8KFc1oTIElKfAutVrcgXv9JEdHC53E0rI6BnkxeFHP_xyj8iC3Cbe0SRGoqfV5xF6pmT9ITXm052dvD95gR8Q1ynooJSAiMUhFHJbxeIzlH0gZ2/s320/4-tree-09.png" width="320" height="307" data-original-width="669" data-original-height="641" /></a></div>
<h2>まとめ</h2>
<p><a href="https://www.lambdanote.com/products/ruby-ruby">『RubyでつくるRuby』</a>を読むと、このような「木」がプログラムそのものだということがわかります。
このように生成された図だけでなく、hirekoke画伯描きおろしカラーイラストも豊富に掲載された<a href="https://www.lambdanote.com/products/ruby-ruby">『RubyでつくるRuby』</a>をいますぐ買おう!</p>
<a href="https://www.lambdanote.com/collections/frontpage/products/ruby-ruby">
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJQThK9uiWHlM6RFNU9CnQ8AKTCxaBCHLyxIjlDsXm2rRhuBT1pegeRRl8LT7smvS5wu7TfjTa-RlifzDdT-G4JI6x3aY3SSt1kyOUww7HeRHG2qMaX27hzHrbzJvhJvkQbYnI/s1600/ruby-ruby-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJQThK9uiWHlM6RFNU9CnQ8AKTCxaBCHLyxIjlDsXm2rRhuBT1pegeRRl8LT7smvS5wu7TfjTa-RlifzDdT-G4JI6x3aY3SSt1kyOUww7HeRHG2qMaX27hzHrbzJvhJvkQbYnI/s200/ruby-ruby-1.png" width="141" height="200" data-original-width="400" data-original-height="569" /></a></div></a>
<ul>
<li><a href="https://www.lambdanote.com/products/ruby-ruby">ラムダノートの直販で『RubyでつくるRuby』を買う</a></li>
<li><a href="https://honto.jp/netstore/pd-book_28490380.html">Hontoで『RubyでつくるRuby』を買う</a></li>
<li><a href="https://www.amazon.co.jp/Ruby%E3%81%A7%E3%81%A4%E3%81%8F%E3%82%8BRuby-%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89%E5%AD%A6%E3%81%B3%E3%81%AA%E3%81%8A%E3%81%99%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9E%E5%85%A5%E9%96%80-%E9%81%A0%E8%97%A4%E4%BE%91%E4%BB%8B/dp/4908686017/ref=sr_1_3?m=A2KDK3NSLPB7MM&s=merchant-items&ie=UTF8&qid=1512203621&sr=1-3">ラムダノートのAmazonマーケットプレイスで『RubyでつくるRuby』を買う</a></li>
</ul>
<p>繰り返しになりますが、電子版はラムダノートでは出版していないものの、<a href="http://ascii.jp/elem/000/001/230/1230449/">Ascii.jpでもとになった連載が読めます</a>。ぜんぶ無料!</p>
k16http://www.blogger.com/profile/02349067627444091120[email protected]0tag:blogger.com,1999:blog-9197115.post-8509474713721251942017-08-21T12:36:00.000+09:002017-08-21T12:39:50.416+09:00LLイベント2017の「第2プログラミング言語鑑定団」で鹿野が話したことまとめ<p>プログラミング好きにもいろいろあって、仕事で使ってる道具をもっと知りたいという人もいれば、自分が使ったことない道具の話を知りたいという人もいれば、道具はなんでもいいから面白い話がしたいという人もいます。
久しぶりに参加したLLイベントは、そんな多様なプログラミング好きが「<b>全員がアウェーな立場</b>」で交流するという、貴重で面白い機会でした。
実際、「LL」の1つめのLには去年までは「<b>Lightweight</b>」という意味があり、その単語が示す特徴をもった言語のイベントのようにどうしても見えてたんですが、今年からはそういう区切りも公けになくし、Lは「<b>Learn</b>」の意味になったとのことです。</p>
<p>その<a href="https://ll.jus.or.jp/2017/">LLイベント2017</a>で、「第2プログラミング言語鑑定団」というセッションに出させてもらいました。
司会の<a href="https://twitter.com/koyhoge">小山さん</a>が「<b>Teratail, Yahoo知恵袋などから、それらしい質問をかき集めてマージ</b>」した6パターンの「<b>次に学ぶ言語は何がいい?</b>」に対し、鑑定団の一人としてお勧め言語を紹介せよというのがミッションでした。
ぼく以外の鑑定団のメンバーは、<a href="https://twitter.com/sasakipochi">ささけんさん</a>、<a href="https://twitter.com/takano32">高野さん</a>、<a href="https://twitter.com/takahashim">高橋さん</a>。一癖あるすごいITエンジニアばっかりだー。このメンバーが集まるというだけで、LLイベントすごいって気持ちになりました。
</p>
<p>いっぽう、ぼく自身はただの書籍編集者です。
自分の仕事に必要な道具を作ったり環境を整えたりはするけどエンジニアというわけではないし、プログラミングは好きで勉強はするけど研究者ではないし、
本職ではない人間になんという無茶ぶりかと思って最初は躊躇したのですが、たぶん、この記事を書かせてもらったことをきっかけに声をかけてもらえたんだろうなあ。
</p>
<p><iframe class="embed-card embed-blogcard" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" title="いま学ぶべき第二のプログラミング言語はコレだ! 未来のために挑戦したい9つの言語とその理由 - エンジニアHub|若手Webエンジニアのキャリアを考える!" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Femployment.en-japan.com%2Fengineerhub%2Fentry%2F2017%2F05%2F19%2F110000" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://employment.en-japan.com/engineerhub/entry/2017/05/19/110000">employment.en-japan.com</a></cite></p>
<p>なお、上記の記事は「ElixirとRustとHaskellにちょっと興味がある人向けの紹介記事を各界の第一人者に書いてもらおう」という企画の<b>前フリ</b>なので、そういう目線でやさしい気持ちで読んでもらうと幸いです。
<a href="https://employment.en-japan.com/engineerhub/entry/2017/06/12/110000">Elixir</a>と<a href="https://employment.en-japan.com/engineerhub/entry/2017/07/10/110000">Rust</a>はすでに公開中。今月中にHaskellも公開される予定です(宣伝)。
</p>
<h2>ほかの鑑定団の回答</h2>
<p>そもそもブログで自分の回答を書くつもりはなかったんですが、ささけんさんがさっくりと自分の回答をまとめて公開したので、まとめざるを得なくなった。</p>
<iframe src="//www.slideshare.net/slideshow/embed_code/key/LstjuJexmXCpwN" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/sasakipochi/ll2017" title="LL2017 プログラミング言語鑑定団 資料" target="_blank">LL2017 プログラミング言語鑑定団 資料</a> </strong> from <strong><a href="https://www.slideshare.net/sasakipochi" target="_blank">Ken SASAKI</a></strong> </div>
<p>[高野さんと高橋さんが何か公開されたらリンクはる予定地]</p>
<h2>鹿野はどんな言語を勧めたか</h2>
<p>想定質問は事前に見せてもらってたのですが、じゃあその質問に対して何を答えることが求められてるんだろうというのは、正直なところ当日になってもわからなくて、会場に着くまでは「ちょっとまずいかもなあ」と暗い気持ちでいました。
で、それを一緒に来ていた同僚に愚痴ったところ、「<b>お勧め本を紹介したらいいじゃん</b>」という画期的な入れ知恵をしてもらい、その路線でいくことに決めたのでした。
</p>
<h3>質問1</h3>
<blockquote style="background-color:#e0ffff"><p>
文系の大学4年生のときにプログラミングが好きになり、独学で C と Java の初歩を学びました。卒業後Web 制作会社に入社し、HTML, CSS,JavaScript を習得しました。Web周辺だけでは将来が不安なので、次に何を学ぶべきか考えています。アドバイスをいただけないでしょうか。
</p></blockquote>
<p>この質問を最初にみたときは「知らんがな」という思いしか去来せず、サイコロでも投げて決めろと言いたかったのですが、言語じゃなくて書籍であれば紹介すべきものがすぐに思いつきました。
五十嵐先生の『プログラミング in OCaml』です。なので、回答は「OCaml」にしました。
</p>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=B00QRPI1AS&linkId=0e23084fc2924d37d29990c778ab95a6"></iframe>
<p>あらかじめ断っておくと、ぼくはOCamlを実用してるわけではありません。
OCamlのコードをいじったのは、『型システム入門』を作ったとき、OCamlで書かれた原著者ビルド環境を日本語pLaTeX向けに改修したときくらいです。
ですが、この本は、OCamlを使うつもりがとくにない人でも、独力でプログラミングを学んできたような人であれば、読むといいことがたくさん書いてあると思っています。
具体的には、OCamlというプログラミング言語でのプログラムの書き方だけでなく、どうしてそういう機構になっているのかがいちいち詳しく解説されており、プログラミング言語の理論についても味見できるようになっています。
この質問者はWeb周辺の技術を追いかける以外の勉強をしたいようだし、そういう意味でもぴったりではないかと思いました。
</p>
<h3>質問2</h3>
<blockquote style="background-color:#e0ffff"><p>
文系大学に通う学生ですが、昔からゲームが好きで、将来はゲームクリエイターになりたいと考えています。そうはいってもプログラミングはまだできないし、特筆したスキルもありません。ゲームクリエイターに関する書籍を読んで、将来こんなゲームを作りたいと夢を膨らませています。私がゲーム開発者になるためにはどの言語から学ぶのがよいでしょうか?
</p></blockquote>
<p>ゲーム作りたいといってる時点で、プログラミング言語を選んでる場合じゃなく、むしろどのゲームエンジンを使ってみればいいかという話なんですよね。
なので、回答は「Unity」か「Unreal Engine」にしました。
</p>
<p>書籍として紹介したのは、『Unreal Engine 4で極めるゲーム開発』です。無責任にも自分では読んでないんですが、<a href="http://blog.shibu.jp/article/171607536.html">渋川さんが激烈に勧めている</a>ので間違いないでしょう。
</p>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=4862462553&linkId=2ffa713f1c459d35e7f6630a27ff7be1"></iframe>
<h3>質問3</h3>
<blockquote style="background-color:#e0ffff"><p>
Web制作会社でサーバサイドを開発しているソフトウェアエンジニアです。現在使っているプログラミング言語はRubyでフレームワークはRailsです。最近世の中でAIや機械学習がブームになっていて、私もそちら方面のスキルを磨いてより高度な作業をできるようになりたいと考えています。AIや機械学習を使いこなすのに最適なプログラミング言語は何でしょうか?
</p></blockquote>
<p>機械学習で縛られてる設問なので、Pythonからは逃げられないような気がします。ということで、回答としては「Python」。
</p>
<p>でも、たぶんPythonを学べばどうなるものでもなく、線形代数なんかを地道に復習したほうがいいような気もします。
そのへんからかみ砕いて解説されているという点で、書籍は『ゼロから作るDeep Learning』をお勧めにしました。
</p>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=4873117585&linkId=7d69a948dd421ccc073ec809b86b7d80"></iframe>
<h3>質問4</h3>
<blockquote style="background-color:#e0ffff"><p>
SIerとして大手案件の2次下請けを仕事にしています。主に使っている言語はJavaでフレームワークはStrutsです。噂ではStrutsにもSIerにも未来はもう無いそうで、転職して他の仕事もできるようになりたいのですが、これまでJavaしか使ったことがないのでどうしたら良いか分かりません。これから学ぶのならば、なるべく長く役に立つ技術が良いと思うのですが、何がよいでしょうか。
</p></blockquote>
<p>「長く役に立つ」といったら、これまで長く使われてきた実績があり、これからもそう簡単に消えることはないであろう言語しかないだろうということで、「Common Lisp」か「Haskell」と回答しました。
</p>
<p>書籍はそれぞれ『実践Common Lisp』と『すごいHaskell』を紹介。このへんは我田引水させてもらいました。
</p>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=4274067211&linkId=c166ede98bd2f5ba346cbb3532c9ee20"></iframe>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=4274068854&linkId=ce887696b6fcd937af083c70e6f975ad"></iframe>
<h3>質問5</h3>
<blockquote style="background-color:#e0ffff"><p>
プログラミング初心者です。Webサイト作成のためにPHPの学習中ですが、他の言語にも興味があります。しかしなかなか難しいのもあって効率的なプログラミング学習法はないかと頭を悩ませているところです。そこで、おもしろそうと興味を持てば学習がはかどるのではと考えました。面白いプログラミング言語とその理由を教えてください。
</p></blockquote>
<p>面白いプログラミング言語といったら、とりあえずこれを押さえておけということで、「Brainfuck」です。
とはいえ、Brainfuckでプログラムを書くんじゃなく、好きな言語でBrainfuckを作ってみたらという提案をしました。
やっぱり、プログラミング言語ってこういうことなんだという実感を得るには、なんでもいいから作ってみるのがいちばんで、そのためにもBrainfuckの実装には一度は挑戦してみると楽しいと思います。
</p>
<p>というわけで、お勧めした書籍は『Rubyで作る奇妙なプログラミング言語』。
</p>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=4839927847&linkId=363df0c56a732dc60de6d405d7acba3e"></iframe>
<h3>質問6</h3>
<blockquote style="background-color:#e0ffff"><p>
インフラ運用エンジニアをしています。使える言語はシェルです。仕事ではたくさんのOSSを使用していますが、これらは書かれている言語がC,PHP,Python,Ruby,Node.js,Javaなど多岐にわたります。最近は自動化がブームですが、OSSを使って自動化をやっていくために、どのような言語を学ぶのがよいでしょうか。
</p></blockquote>
<p>OSSのツールを利用していくのに知っておいたほうがいい言語で、質問に出ていないものといって思いつくものは、「Go」しかありませんでした。
というわけで書籍としては『プログラミング言語Go』です。
</p>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=4621300253&linkId=4434d94564fe832329a882bf4c6d58e4"></iframe>
<p>いま思い返すとPerlとかLuaという選択肢もありえましたが、やっぱりあの場でお勧めする言語としてはGoしかありませんでした。
なぜなら、Goは<a href="https://www.lambdanote.com/">ラムダノート</a>から近日中に新刊が出る予定だからです。
<a href="http://ascii.jp/elem/000/001/235/1235262/">アスキーjpで連載していた「Goならわかるシステムプログラミング」</a>の書籍化です!
昨日のLLイベントでも「低レイヤをかじることの重要性」は何度か強調されていて、そのたびにCやアセンブラというキーワードが出ててましたが、いまならそれこそGoで楽に学べます。
そういう趣旨で好評の連載に、著者の渋川さんが少し話を追加して、10月くらいに出せるように頑張って制作中。お楽しみに(宣伝)。
</p>
<h3>質問7(会場からの飛び入り質問)</h3>
<blockquote style="background-color:#e0ffff"><p>
小学三年生の息子がプログラミングをはじめるのに、Scratchのほかにどんな選択肢がありますか?
</p></blockquote>
<p>小学生にプログラミングを教えるときって、ビジュアル言語じゃない形でコンピュータの開発環境に触れる機会も必要だと思ってるんですよね。
かといって、汎用言語はそこそこ覚えないといけないことが多くてつらい。
そこで、覚えることが最小限で、コンピュータの生っぽいところを意識できる言語があればいいんですが、その条件を満たす言語はSchemeくらいしかありませんよね(異論は認める)。
というわけで「Scheme」をお勧めしました。
</p>
<p>参考書籍はもちろん『計算機システムの構造と解釈』です(いまおもうと『Scheme手習い』という手もあった)。
</p>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=4798135984&linkId=2da68294e7bf22988bcfee6380a8ba5f"></iframe>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=4274068269&linkId=5c59b44d0341c4b3f30402557155206c"></iframe>
k16http://www.blogger.com/profile/02349067627444091120[email protected]0tag:blogger.com,1999:blog-9197115.post-47335927424968108102017-06-21T13:20:00.000+09:002017-06-21T13:20:26.378+09:00編集というサービスの内容(技術書編)技術書の編集者が原稿に対して何を提供するものなのか、整理してみた。順番には意味があります。<br />
<br />
<ol>
<li>原稿をDTP担当者が作業できるデータにする</li>
<li>誤字脱字、非標準的な表記を直す</li>
<li>表記を統一する</li>
<li>文法の間違い、不適切な言い回しを直す</li>
<li>構成の不備、内容の間違いを指摘する</li>
<li>構成の不備、内容の間違いを直す</li>
<li>冗長な内容、文脈から外れる記述を欄外に追い出したり、段落構成を手直ししたりする</li>
<li>段落や文を、文脈に合わせた相に書き直す</li>
<li>行間をうめる</li>
<li>解説画像やイラスト、索引などのメタ情報を作る</li>
<li>原稿を書く</li>
<li>【番外】企画する</li>
</ol>
<br />
どこまでやってほしいか、できるか、追加料金がいくら必要なのかというのを、著者・版元編集者・下請け編集者の間ではっきりさせると、みんなが幸せになる気がする。(だいたい編集外注するときって「編集作業一式」の「ページあたりの単価」になりがちで、しかしその「一式」には上記のような幅があるわけだから、人によって高いとか安いとか感じ方がいろいろ変わってしまうよね……。)<br />
<br />
本として書店に並ぶまでに必要な作業は上記のほかにもいっぱいあり(装幀の企画と手配、権利、印刷製本、流通に関連するいろいろな仕事などなど)、上記に挙げた編集業務を担当編集者がぜんぶやるべきという話ではないはず。<br />
<br />
たとえば、上記のうち5までは担当編集者が直接やるけど、残りは外部の査読者だったり編集者だったりを雇うことにするとか、あるいは、そこは著者の仕事であると最初から割り切る(ということを著者との間で同意しておく)ほうが、結果的に読者が手にする本にとって最善というケースもあるかもしれない。<br />
<br />
なお、<a href="https://www.lambdanote.com/pages/page">弊社</a>では上記のすべてに対応した編集業務の受注が可能です。お気軽にご相談ください。k16http://www.blogger.com/profile/02349067627444091120[email protected]0tag:blogger.com,1999:blog-9197115.post-87046306551965550152016-12-30T23:24:00.001+09:002016-12-31T01:24:54.356+09:002017年賀状<p>
年賀状書いた。
</p>
<style type="text/css">
<!--
.comment {
/* font-lock-comment-face */
color: #99968b;
}
.constant {
/* font-lock-constant-face */
color: #e5786d;
}
.function-name {
/* font-lock-function-name-face */
color: #0000cd;
}
.keyword {
/* font-lock-keyword-face */
color: #4b0082;
font-weight: bold;
}
.string {
/* font-lock-string-face */
color: #006400;
}
.variable-name {
/* font-lock-variable-name-face */
color: #800000;
}
a {
color: inherit;
background-color: inherit;
font: inherit;
text-decoration: inherit;
}
a:hover {
text-decoration: underline;
}
-->
</style>
<pre>
<span class="constant">%!PS</span>
<< <span class="variable-name">/PageSize</span> [285 420] >> setpagedevice
<span class="function-name">/setrandcolor</span> {<span class="comment">% def</span>
<span class="variable-name">/r1</span> {rand 5 mod 3 div} <span class="keyword">def</span>
<span class="variable-name">/r2</span> {rand 4 mod 4 div} <span class="keyword">def</span>
<span class="variable-name">/r3</span> {rand 3 mod 4 div} <span class="keyword">def</span>
r1 r2 r3 setrgbcolor
} <span class="keyword">def</span>
<span class="function-name">/f</span> {<span class="comment">% def</span>
dup dup dup
4 mod 0 eq {<span class="string">(2)</span> 4 1 roll -1 0 rmoveto} <span class="keyword">if</span>
4 mod 1 eq {<span class="string">(0)</span> 3 1 roll -3 0 rmoveto} <span class="keyword">if</span>
4 mod 2 eq {<span class="string">(1)</span> 2 1 roll -3 0 rmoveto} <span class="keyword">if</span>
4 mod 3 eq {<span class="string">(7 )</span> -5 0 rmoveto} <span class="keyword">if</span>
} <span class="keyword">def</span>
<span class="function-name">/i</span> 4 <span class="keyword">def</span>
<span class="function-name">/lineto-chars</span> { <span class="comment">% def</span>
<span class="variable-name">/ex</span> x <span class="keyword">def</span> <span class="variable-name">/ey</span> y <span class="keyword">def</span>
<span class="variable-name">/y</span> exch <span class="keyword">def</span> <span class="variable-name">/x</span> exch <span class="keyword">def</span>
<span class="variable-name">/d</span> x ex sub dup mul y ey sub dup mul add sqrt <span class="keyword">def</span>
<span class="variable-name">/R</span> y ey sub x ex sub atan <span class="keyword">def</span>
R rotate
{ d 0 le <span class="comment">% ifelse</span>
{ <span class="keyword">exit</span> }
{ setrandcolor
<span class="variable-name">/ra</span> rand 5 mod 3 div 10 mul 22 add <span class="keyword">def</span>
<span class="variable-name">/Georgia-Bold</span> findfont
[25 0 0 ra 0 0] makefont setfont
i f show
<span class="variable-name">/i</span> i 1 add <span class="keyword">def</span>
<span class="variable-name">/d</span> d 7 sub <span class="keyword">def</span> }
<span class="keyword">ifelse</span>
} <span class="keyword">loop</span>
0 R sub rotate
} <span class="keyword">def</span>
1 1 20 { <span class="comment">% for</span>
<span class="variable-name">/n</span> exch <span class="keyword">def</span>
newpath
0 0 moveto
135 45 moveto
85 140
110 165
110 130 curveto
0 0 moveto
150 130 moveto
155 190
210 140
130 40 curveto
flattenpath
{<span class="variable-name">/y</span> exch <span class="keyword">def</span> <span class="variable-name">/x</span> exch <span class="keyword">def</span>}{lineto-chars}{}{} pathforall
<span class="keyword">gsave</span>
32 230 moveto
0.9 0.1 0.2 setrgbcolor
<span class="variable-name">/Georgia-Bold</span> findfont [90 0 0 100 0 0] makefont setfont
<span class="string">(2017)</span> show
<span class="keyword">grestore</span>
<span class="keyword">showpage</span>
} <span class="keyword">for</span>
</pre>
<p style=" margin: 12px auto 6px auto; font-family: Helvetica,Arial,Sans-serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 14px; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none; display: block;"> <a title="View 2017 on Scribd" href="https://www.scribd.com/document/335353556/2017#from_embed" style="text-decoration: underline;" >2017</a> by <a title="View Keiichiro Shikano's profile on Scribd" href="https://ja.scribd.com/user/69531250/Keiichiro-Shikano#from_embed" style="text-decoration: underline;" >Keiichiro Shikano</a> on Scribd</p><iframe class="scribd_iframe_embed" src="https://www.scribd.com/embeds/335353556/content?start_page=1&view_mode=scroll&access_key=key-H5s9BRjwBPKndFJOkZyG&show_recommendations=true" data-auto-height="false" data-aspect-ratio="0.6787057938299473" scrolling="no" id="doc_74616" width="400" height="600" frameborder="0"></iframe>
<p>
PSの解説でよく登場する、パスに沿った文字列描画の簡易版です。
まずflattenpathしてカレントパスをlinetoの配列に変換したあと、各linetoが描く直線がX軸になるまで回転→linetoの長さまで数字を順番に書く→回転を戻す、を繰り返しています。
どのへんが簡易版かというと、グリフを書き終わったポイントは当然ながらオリジナルのパスからはずれているのだけど、そこへ戻す処理をさぼっています。そのため、ベースになるパス(ハート型)よりも文字列の描く図形のほうが肥大していく、それもフォントや処理系によってずれ幅がけっこう違ってしまう、という緩い仕様です。
このコードはWindowsのDistillerに合わせてあります。
gsだと、なぜかずれがもう一回り大きい。
</p>
<p>
過去のやつ。
</p>
<ul>
<li><a href="http://note.golden-lucky.net/2015/12/2016.html">2016年</a></li>
<li><a href="http://note.golden-lucky.net/2015/01/2015.html">2015年</a></li>
<li><a href="http://note.golden-lucky.net/2013/12/2014.html">2014年</a></li>
<li><a href="http://note.golden-lucky.net/2012/12/2013.html">2013年</a></li>
<li><a href="http://note.golden-lucky.net/2011/12/pagesize-setpagedevice-fun-9-dup-9-le.html">2012年</a></li>
<li><a href="http://note.golden-lucky.net/2010/12/2011.html">2011年</a></li>
<li><a href="http://note.golden-lucky.net/2009/12/setpagedevice-1-1-25-n-exch-def-0-12.html">2010年</a></li>
<li><a href="http://note.golden-lucky.net/2008/12/blog-post.html">2009年</a></li>
<li><a href="http://note.golden-lucky.net/2007/12/blog-post_29.html">2008年</a></li>
</ul>
k16http://www.blogger.com/profile/02349067627444091120[email protected]0tag:blogger.com,1999:blog-9197115.post-58277823503838255842016-12-24T02:54:00.000+09:002016-12-24T03:30:26.748+09:00JSONをTeXで組版する<p>
昨今、ドキュメント技術の主戦場といったらウェブです(ワールドワイドなほう)。
ウェブ上ではさまざまな構造化テキストが飛び交っています。
まっさきに思いつくのは、HTMLをはじめとする、ブラウザがネイティブにレンダリングできる構造化テキストでしょう。
</p>
<p>
しかしブラウザにはJavaScriptという強力なプログラミング言語の実装が組み込まれているので、<b>HTML以外の構造化テキスト</b>をサーバから取得して整形する場合も少なくありません。
そのようなデータ形式のひとつに<a href="http://www.json.org/json-ja.html"><b>JSON</b></a>があります。
</p>
<!--
<p>
実際、全世界のTeXパッケージが集約されているCTANでも、JSONフォーマットでパッケージの一覧や各種パッケージの情報を公開しています。
</p>
<ul>
<li><a href="https://www.ctan.org/help/json/packages">CTANのパッケージ一覧のJSONクエリ</a></li>
<li><a href="https://www.ctan.org/help/json/package">CTANの各パッケージのJSONクエリ</a></li>
</ul>
-->
<p>
最近のWebサービスでは、サーバからHTMLを送らずにJSONデータだけを送り、ブラウザがそれをJavaScriptで解析して画面表示をすべて動的に作っている場合もあるようです。
この場合にブラウザがやっていることは、ある種の自動組版だといえるでしょう。
そもそもブラウザによるHTMLのレンダリング自体が自動組版だという見方もできますが、それよりさらに抽象化した、<b>JSONを原稿とする自動組版</b>という考え方です。
必ずしもページ全体をJSONから表示していなくても、たとえばJSONデータから表を生成してdiv要素に差し込むといった局所的な組版もありえると思います。
</p>
<h2>ブラウザとJavaScriptでできることがTeXでできないはずがない</h2>
<p>
というわけで、TeXでJSON組版をしてみました。
題材としては、<a href="https://www.ctan.org/help/json/package">CTANの各パッケージのJSONクエリ</a>とかも考えたのですが、残念ながらCTANではパッケージの詳細説明の項目にプレーンテキストではなくHTMLが直書きされている場合があるようです。
TeXで扱うのにHTMLタグは邪魔でしかありません。
まさかCTANともあろうものが、TeXでJSONデータを利用することを考えていなかったなんて。
</p>
<p>
それに、どうせならもっとクリスマスらしい題材にしたいところです。
クリスマスといえばホワイトクリスマス、ホワイトクリスマスといえば雪だるま。雪だるまを組版するなら天気予報でしょう。
OpenWeatherMapという会社のサイトで天気予報をはじめとする気象データをJSONにより取得できるので、これを組版していきましょう。
</p>
<ul>
<li><a href="http://openweathermap.org/api">Weather API - OpenWeatherMap</a></li>
</ul>
<h2>天気予報JSONデータの取得</h2>
<p>
まずはデータの取得です。TeXからHTTPリクエストを発行する汎用の手法はないので、cURLでもwgetでも好きなものを使ってください。
OpenWeatherMapでサインアップしてAPPIDを手に入れれば、たとえば下記のようなURLによって、東京の5日後までの3時間おき予報データが取得できます。
</p>
<pre>
http://api.openweathermap.org/data/2.5/forecast?q=Tokyo,jp&APPID=0000000000000
</pre>
参考までに、取得できるのはこんな形のJSONデータです。
<pre>
{"city":{
"id":1850147,
"name":"Tokyo",
"coord":{"lon":139.691711,"lat":35.689499},
"country":"JP",
"population":0,
"sys":{"population":0}},
"cod":"200",
"message":0.0103,
"cnt":37,
"list":[
{"dt":1482483600,
"main":
{"temp":9.94,
"temp_min":8.84,
"temp_max":9.94,
"pressure":1015.88,
"sea_level":1017.11,
"grnd_level":1015.88,
"humidity":71,"temp_kf":1.1},
"weather":[
{"id":802,
"main":"Clouds",
"description":"scattered clouds",
"icon":"03n"}],
"clouds":{"all":36},
"wind":{"speed":6.71,"deg":318.003},
"rain":{},
"sys":{"pod":"n"},
"dt_txt":"2016-12-23 09:00:00"},
...
</pre>
<h2>JSONデータのTeXによるパーズ</h2>
<p>
JSONデータを取得できたら、パーズします。JSONを読むパッケージが見当たらなかったので、ざっくり再帰下降パーザを書きました。<a href="http://hak7a3.hatenablog.com/entry/2016/12/17/122422">TeXは関数型言語</a>なので、素直に書けますね。
</p>
<ul>
<li><a href="https://github.com/k16shikano/jsonlite/blob/master/jsonlite.sty">https://github.com/k16shikano/jsonlite/blob/master/jsonlite.sty</a></li>
</ul>
<p>
公開APIは以下の3つ。
</p>
<blockquote style="background-color:#e0ffff">
<dl>
<dt><b>・<code>\readJson #1 #2</code></b></dt><dd>第一引数に渡したコントロールシーケンスに、第二引数に渡したJSONデータが格納される</dd>
<dt><b>・<code>\readJsonValueById #1 #2 #3</code></b></dt><dd>第一引数に渡したコントロールシーケンスに、第二引数に渡したJSONデータの、第三引数の名前に対応する値が格納される</dd>
<dt><b>・<code>\showJsonValueById #1 #2</code></b></dt><dd>第一引数に渡したJSONデータの、第二引数の名前に対応する値が入力に残る</dt>
</dl>
</blockquote>
<p>
ちょっと例を見てみましょう。青字になっているのがJSONデータです。
</p>
<pre>
\documentclass{article}
\usepackage{<font color="red">jsonlite</font>}
\begin{document}
\readJson{\json}{<font color="blue">{"id":[1,2,3], "class":"foo", "data":{"id":"456"}, "info":"Is this a text?"}</font>}
\readJsonValueById{\jsonId}{\json}{"id"} <font color="green">%=> expl3 sequence</font>
\readJsonValueById{\jsonData}{\json}{"data"} <font color="green">%=> id:456</font>
\readJson{\jsonJsonData}{<font color="blue">{\jsonData}</font>}
\showJsonValueById{\jsonJsonData}{"id"} <font color="green">%=> 456</font>
\end{document}
</pre>
<h2>天気予報JSONデータを表組する</h2>
<p>
OpenWeatherMap社から提供される天気予報JSONデータから、都市名、予報の時刻、予想天気、予想気温を取ってきて、LaTeXの表として組みましょう。
各時刻の予報は、<code>"list"</code>という名前の配列の各要素になっているようです。
この配列に対するmapで、表の各行を整形するという戦略にします。
実は<code>jsonlite</code>パッケージではJSONの配列を<code>expl3</code>のシーケンスとして保持するので、シーケンス用のmapが使えます。
</p>
<pre>
\NewDocumentCommand{\showForecast}{ m }{%
\begin{longtable}{ l | c | r}
日時 & 空模様 & 気温 \\\hline
\endfirsthead
日時 & 空模様 & 気温 \\\hline
\endhead
<font color="red">\seq_map_function:cN #1 \format_forecast:n</font>
\end{longtable}
}
</pre>
<p>
TeX言語のくせにシーケンスとかmapとか、お前はなにを言ってるのだ、という感じかもしれませんが、2016年にもなればそういうものなんです。
そもそも<a href="http://hak7a3.hatenablog.com/entry/2016/12/17/122422">TeXは関数型言語</a>なのだからシーケンスに対するmapくらいできないはずがありません。
</p>
<p>
あとは、<code>\format_forecast:n</code>を書いていくだけなんですが、
OpenWeatherMap社のデータで<code>"weather"</code>がさらに配列になっていたりして無駄にめんどくさいので解説は省略します。
<code>jsonlite</code>パッケージと同じディレクトリに完全なコードを置いてあるので参考にしてください。
</p>
<ul>
<li><a href="https://github.com/k16shikano/jsonlite/blob/master/weather-forecast.tex">https://github.com/k16shikano/jsonlite/blob/master/weather-forecast.tex</a></li>
</ul>
<p>
天気記号のサポート数がそこそこあるDejaVuSansを使いたかったので、XeLaTeXで実行してみた結果がこれです。<a href="http://acetaminophen.hatenablog.com/entry/2016/12/23/144042">DejaVuSansの☃</a>はどことなく品がいいですね。
</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizjqqXgw_iEMJuSFOaAeFENaAcMtYyt759xD3cqEewpR3HM8xzP6Gmd7EM7hOpQKghT4HNmTTGMGpa8qqru2fWbyguZ7NeCk7YT2QCXCzNZ8nj6ZnU21Efr7RQqFDlxmaeIS94/s1600/brzozie.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizjqqXgw_iEMJuSFOaAeFENaAcMtYyt759xD3cqEewpR3HM8xzP6Gmd7EM7hOpQKghT4HNmTTGMGpa8qqru2fWbyguZ7NeCk7YT2QCXCzNZ8nj6ZnU21Efr7RQqFDlxmaeIS94/s640/brzozie.png" width="640" height="416" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUtaqpV68ZFsFrO1AiPbrYrM-wHEYIAkgbXkzOT-yU5EM69UciP-Uf42bPN_hnmm5XGCJrS9sGSkWtmxRc0ksgsrLrfTHlJ9N631A_p_S8icYPESFzZRx5hNehgRh_jxEX6I9T/s1600/tokyo.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUtaqpV68ZFsFrO1AiPbrYrM-wHEYIAkgbXkzOT-yU5EM69UciP-Uf42bPN_hnmm5XGCJrS9sGSkWtmxRc0ksgsrLrfTHlJ9N631A_p_S8icYPESFzZRx5hNehgRh_jxEX6I9T/s640/tokyo.PNG" width="640" height="424" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwd6ihsQDBHAsgs6hskvoqLZ6OPUNq5sJlHCniy2IjisISr7AxyT_cg-llXGEZQwb8FHPK0soyOAKvAa633BlXJ5n_yIFObe9k7YVfSqWvnG1njuvDRD2SG6Ch6tpFGPn3-G2p/s1600/moscow.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwd6ihsQDBHAsgs6hskvoqLZ6OPUNq5sJlHCniy2IjisISr7AxyT_cg-llXGEZQwb8FHPK0soyOAKvAa633BlXJ5n_yIFObe9k7YVfSqWvnG1njuvDRD2SG6Ch6tpFGPn3-G2p/s640/moscow.PNG" width="640" height="460" /></a></div>
<p>
ところで、<a href="https://www.google.co.jp/maps/place/%E3%83%9D%E3%83%BC%E3%83%A9%E3%83%B3%E3%83%89+%E3%83%96%E3%82%B8%E3%83%A7%E3%82%B8%E3%82%A7/@53.3020963,19.4586316,11z/data=!3m1!4b1!4m5!3m4!1s0x471d1a4f2cc176d7:0x292f0c1cc230807c!8m2!3d53.3029491!4d19.6079083">Brzozie(ブジョジェ)</a>という地名がどこなのか気になった人がいるかもしれません。ブジョジェはポーランドの湖水地方で、バホテク湖があるところです。来年のTUG2017は、このバホテク湖で毎年開催されているBachoTeXというイベントと合同で5月に開催されることになっています。なんとか参加するぞ。
</p>
<p>そしてこの記事は、<a href="http://www.adventar.org/calendars/1734#list-2016-12-17">第五回となるTeX&LaTeXアドベントカレンダー</a>の24日めの記事です。
昨日は<a href="http://acetaminophen.hatenablog.com/entry/2016/12/23/144042">アセトアミノフェンさん</a>(この記事を見てDejaVuSansを使うことを思いつきました)、明日の最終日は<a href="https://twitter.com/zr_tex8r">ZRさん</a>です。
</p>
k16http://www.blogger.com/profile/02349067627444091120[email protected]0tag:blogger.com,1999:blog-9197115.post-1017868198127279322016-12-03T00:51:00.000+09:002016-12-03T00:51:00.031+09:00独立系出版社をやるという覚悟について<p>
カナダ最大の都市であるトロントから北に向かって1時間ちょっと、荒野だか畑だか牧場だかよくわからない広大な土地を走り抜けたところに、エリンという小さな村があります。
19世紀に開拓された当時からメインストリートであったと思われる道が、川の蛇行している部分を堰き止めるように貫いていて、その両脇だけで主な商圏が形成されているような素朴な村です。
</p>
<p>
そんな小さな村に、なんと出版社があります。
その名も<a href="http://www.porcupinesquill.ca/index.html">The Porcupine’s Quill</a>。
直訳すると「ヤマアラシの針」ですね。
言うまでもなく独立系の出版社で、大手からは陽の目を見るのが難しいカナダ発の文学者やアーティストの作品を手掛けているようです。
</p>
<p>
今年の7月、この《ヤマアラシの針出版》を訪問する機会がありました。
世界中のTeX関係者が集まるTUGという会合があるんですが、2016年の開催地がトロントで、その一環として《ヤマアラシの針出版》の見学会が組まれていたのです。
トロントからエリン村まで農道(もしくは牧道)を延々とかっ飛ばし、パン屋さんの前でマイクロバスを降りると、その何軒か隣の靴屋みたいな建物が《ヤマアラシの針出版》の本社でした。
</p>
<p>
<a data-flickr-embed="true" href="https://www.flickr.com/photos/k16/28522458572/in/photostream/" title="SDIM0346"><img src="https://c5.staticflickr.com/9/8157/28522458572_028cdf751c_c.jpg" width="800" height="534" alt="SDIM0346"></a><script async src="//embedr.flickr.com/assets/client-code.js" charset="utf-8"></script>
</p>
<p>
こんなカナダのど田舎に本社を構えているというだけで十分に話として面白いんですが、この出版社、他の多くの出版社と違って、印刷から製本まで本づくりのすべてを自前でやっています。
それも、ドイツ製のオフセット印刷機やら製本機やらを社内に一式すべて用意し、経営者であるティムさんと奥さんのエルクさんが手作業で本を作っているのです。
ちなみに、やや出来過ぎ感がありますが、お二人の姓は「インクスター」さんといいます。
</p>
<p>
これが、さっきの建物の地下にあるHeidelberg Kordというオフセット印刷機。とてもよく手入れされていて、油でてかてかしています。インクが香ばしい。
</p>
<p>
<a data-flickr-embed="true" href="https://www.flickr.com/photos/k16/28011820054/" title="SDIM0336"><img src="https://c7.staticflickr.com/9/8744/28011820054_ce8125d995_c.jpg" width="800" height="534" alt="SDIM0336"></a><script async src="//embedr.flickr.com/assets/client-code.js" charset="utf-8"></script>
</p>
<p>
こちらは建物の1階に実装されている、本をかがるための機械。ファンシーな窓の鎧戸と陽光のせいで博物館の展示物っぽいけど、むちゃくちゃ軽快に稼働します。
</p>
<p>
<a data-flickr-embed="true" href="https://www.flickr.com/photos/k16/28012729453/" title="SDIM0333"><img src="https://c6.staticflickr.com/8/7311/28012729453_e1674a0afe_c.jpg" width="800" height="534" alt="SDIM0333"></a><script async src="//embedr.flickr.com/assets/client-code.js" charset="utf-8"></script>
</p>
<p>
正直なところ、訪問前にはそれほど大きな期待はしていませんでした。
自分とは畑違いの文芸系の出版社っぽいし、そもそも出版社の仕事なんてどこも大差ありません。
</p>
<p>
しかし実際に《ヤマアラシの針出版》でティムさんから「どういう考えで本を企画し、作り、それを売ってきたか」を語ってもらい、ビンテージな機械が力学を駆使して本を作り上げるようすを目の当たりにすると、いちいち唸りっぱなしでした。
出版社っていうのは、こんなふうに本を作って売るっていう仕事であり、その骨格がまさにいま自分の目の前に展開されてるんだなと。
</p>
<ul>
<li>出版社の仕事なんて、確かにどこも大差ないけれど、誠実にやっていくと結局は「モノづくり」になるんだよなという気持ち。</li>
<li>電子書籍もいいけど、モノとしての物理は単純に強いなという気持ち。</li>
<li>年間ノルマで本の形を整えなくても、こんなふうに、やりたい人がやりたいように出版をやれるのが健全だよなという気持ち。</li>
<li>ぼくも、完全に同じやり方ではないかもだけど、こんなふうにして本にかかわっていくぞという気持ち。</li>
</ul>
<p>
なにをかくそう、ぼくも自分で出版をやりたいと思って、昨年2015年の12月1日にラムダノート株式会社という会社を作りました。
今年2016年の7月にThe Porcupine’s Quillを訪問して、自分が仕事としてやりたいことは「本を作って買ってもらうこと」なんだなと再確認しました。
来年2017年の2月ころには、最初のタイトルとして、TLSの関連書を発行する予定です。
年が明けてしばらくしたら直販サイトで予約できるようにする予定(予定)なので、ご期待ください。
</p>
<p>
そういえば、この最初のタイトルは翻訳ものなんですが、原書を発行しているロンドンの出版社もやっぱり独立系出版社でした。
そっちもそっちで4月に訪問してたくさん刺激を受けたので、翻訳発行後にあらためてどこかで話ができればいいなと思います。
</p>
<p>
なお、この記事はラムダノート株式会社の設立にあたって出資して頂いた株式会社時雨堂の社長になんか書けといわれ、<a href="http://www.adventar.org/calendars/1435#list-2016-12-02">pyspaアドベントカレンダー2016</a>のエントリーとして書きました。pyspaには脱サラする直前からずっと癒されてきました。でも、昨日は<a href="https://www.ianlewis.org/jp/kubernetes-python">イアンさん</a>、明日はモリヨシさんだし、あきらかに場違いな記事だろこれ。
</p>
k16http://www.blogger.com/profile/02349067627444091120[email protected]0tag:blogger.com,1999:blog-9197115.post-46044914311717584842016-07-01T10:36:00.000+09:002016-07-01T10:36:46.792+09:00主観でプログラミング言語5種類をあっさり解説<p>
現在プログラミング言語は200種類存在していると言われてるようですが、これはたぶんLisp族の言語だけを数えた値です。
</p>
<p>
あるプログラミング言語(汎用のもの)がどんな用途に適しているかは、人によって大きく意見が分かれるので、用途を絞ったからといって適したプログラミング言語が決められるわけではありません。そもそも今日の世界における用途が明日の世界にも存在するとは限らないし。
</p>
<p>
この記事では、ぼくがHello Worldくらいは書いたことがある言語5種類をあっさりと解説しようと思ったけど、そんな知識もないので、「プログラミングしてみたい人向け、言語に関する5つのアドバイス」です。学習しない言語の選択に役立ててください。
</p>
<h2>Go</h2>
<p>
それなりに具体的で明確な「Cを使う」理由があるのでない限り、Cで学べるようなプログラミングはGoで学んだほうがいいと思います。
</p>
<h2>HaskellかOCaml</h2>
<p>
これといった目的もなくプログラミングを始めたいなら、静的型付き言語で始めるほうがいろいろ実りがあると思います。異論は認めるけど。
HaskellやOCamlであれば、現代的なアプリケーションを試しに作ってみるのに必要なライブラリもそれなりに充実しています。
</p>
<h2>Scheme</h2>
<p>
Schemeがいいのは、コンピュータがなくてもプログラミングを学べる点です。Schemeの実装は黒板だと言われるくらいです。
</p>
<h2>正規表現</h2>
<p>
特定のアプリを意識した言語でプログラミングし始めるよりも、正規表現をひととおり自在に使えるほうが、最初のうちは役立つ場面が多いと思います。
Rubyとかも、最初は正規表現全開な感じでテキストフィルタを書いてみるのがいいと思います。
</p>
<h2>先生や友だちや同僚がよく知っている言語</h2>
<p>
というわけで、ぼくの近くにいる人はTeXから学ぶことになります。
</p>
k16http://www.blogger.com/profile/02349067627444091120[email protected]0tag:blogger.com,1999:blog-9197115.post-3808095995067135812016-06-20T10:21:00.000+09:002016-06-20T14:14:40.581+09:00特殊エンジニア向け数学ガイドツアー本『グッド・マス』の話<p>
6月25日、つまり今週末、『<a href="http://www.amazon.co.jp/gp/product/4274218961/ref=as_li_ss_tl?ie=UTF8&camp=247&creative=7399&creativeASIN=4274218961&linkCode=as2&tag=k16shikano-22">グッド・マス ギークのための数・論理・計算機科学</a>』という本が発売されます。
<a href="#postscript">話せば長い事情</a>があって、発売前だけど訳者の次くらいに書籍の内容を熟知しているので、私的な紹介を書いてみました。
</p>
<iframe src="http://rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=ss_til&asins=4274218961" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
<h2>計算機のプロが書いた現代数学ガイドツアー</h2>
<p>
世に数学系の読み物はたくさん出版されています。純粋数学のプロが書いたものもあれば、そうでない人が書いたものもあります。
『グッド・マス』は、後者です。著者のマークさんは計算機科学のプロであり、数学のプロではありません。そのため、本書でいう「数学」も、コンピュータエンジニア的な目線で描かれます。
たとえば、連分数の話をするときはScalaで実装し始めるし、論理学の話をすれば「Prologはいいぞ」って始まるし、計算といったらチューリングマシンとBrainfuckでありλ計算です。
本書を一言で表すと、「コンピュータエンジニア、とくにプログラミング言語とか大好きっ子にとって興味深いであろう観光名所をめぐる現代数学ガイドツアー」です。
日常の言葉で抽象数学を分かりやすく伝える系の読み物を期待して読み始めると、肩透かしを食うと思います。
</p>
<p>
ちなみにですが、そういう方向で数学ネタを気軽に味わいたいとしたら、いまなら"Cakes, Custard and Category Theory"という本が面白いと思います。
『ケーキ、カスタード、それに圏論』というタイトルどおり、後半はまるまる圏論の何がおいしいのかを説明するのに割かれています。こないだ翻訳も出たようです(邦題には「圏論」ってないけど)。
</p>
<iframe src="http://rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-https://images-fe.ssl-imagesamazon.com/images/G/09/associates/build-links/highlight_html._V192555901_.gif22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=ss_til&asins=1781252874" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
<iframe src="http://rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=ss_til&asins=4562052856" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
<p>
この"Cakes, Custard and Category Theory"という本の著者であるEugenia Chengは、生粋のプロ数学者ですが、ユーチューバ―として有名だったりもします。
</p>
<iframe width="400" height="225" src="https://www.youtube.com/embed/k844OY_P0Ck" frameborder="0" allowfullscreen></iframe>
<p>
ナイフを振り回しながら教壇に立つチェン先生かわゆす。
</p>
<h2>『グッド・マス』の話だった</h2>
<p>
閑話休題。『グッド・マス』のゴールは、日常の言葉で抽象数学を語ることではなく、コンピュータ好きなら知っていて損のない数学ネタを一通りさらうことです。
とくに重視されてるのは、公理的に、論理を使って、構成的に数学という体系を捉える方法を伝えることです。
著者のマークさんは、冒頭の第1章から、数学の対象を日常的な感覚だけで語らないよう読者に促します。
エンジニアになじみのある日常的な感覚にも頼りつつ、数とか集合、証明といった対象を、現代数学というルールで捉えるやり方を正面から見せてくれる感じです。
数学の教科書とは違う方法で、コンピュータ好きな人が「生の数学」を味見する本だといえるでしょう。
これが本書の貴重なところだと思います。
</p>
<p>
もともと単発の記事をまとめた本ということもあって、あからさまなストーリーもなく、面白そうな部分だけをつまみ読みできます。「数って何?」みたいな前半の軽めの話題だけ読んでもいいし、Prologを使って一階の述語論理を学ぶ第4部だけ眺めてもいいし、公理的な集合論のノリをさらってみるだけでもいいでしょう。
特に最後の第6部は、正規表現とか再帰、λ計算、型といったプログラミング言語好き向けの話題で占められているので、この辺だけ読むのもお勧めです。
とはいえ後半は「数学をやってる現代人が暗に共有している意識を部外者が垣間見る」ことができるような構成になっているので、論理を扱っている第4部くらいからは順番に読むことをお勧めします。
自分は、はじめて原書を通しで読んだとき、第1章の自然数の説明でのっけからペアノの公理を持ち出してきたのも後半のためのネタ振りだったのかーと納得しました。
</p>
<p>
一方、『グッド・マス』にはあまり登場しない数学の話もたくさんあります。
解析とか位相に関するネタは本書にはまったく出てきません(ε-δのわかりやすい解説はないし、ドーナツとマグカップがどうこうみたいな話もない)。圏論もないです(Haskellのコードは出てきますが、正規表現の微分を実装するのに使われます)。
このへんの話題については期待しないでください。
</p>
<p>
あと、いわゆる一般人向け数学の本で必ず引き合いに出される黄金比については完全にコケにされているので、そういうのが好きな人は注意してください。
目次を見ると黄金比を扱っている章がありますが、これはマークさんが「おれは黄金比をもてはやす連中が嫌いだ」ということを表明するためにある章です。黄金比ネタが好きな人にはこの本はお勧めできません。
</p>
<p>
もうひとつ触れておきたいのは、なるべく読み手が飽きないようにしたいと思うあまりにマークさんの筆がちょくちょく滑るという点です。
ところどころ自由すぎる解釈で書き進めてしまった内容を、コンピュータ系技術書版元であるPragProgsには編集しきることができなかったのか、原書には突っ込みどころのある箇所や単純なミスがけっこう残っています。
ただし、そんな暴走気味の部分はcocoatomoが訳注などでしっかり引き締めてくれているし、
翻訳版のレビューをしてくれた方々(計算機と数学の両方に足をかけてるプロばかり)にも細かい部分まで目を通してもらえてるので、
原文の微妙な勘違いはかなり補正されていました。
翻訳版は、私が企画時にぼんやり思い描いていた以上に、かなり安心して楽しめる内容に仕上がっていると思います。
</p>
<p>
というわけで6月25日発売の『<a href="http://www.amazon.co.jp/gp/product/4274218961/ref=as_li_ss_tl?ie=UTF8&camp=247&creative=7399&creativeASIN=4274218961&linkCode=as2&tag=k16shikano-22">グッド・マス ギークのための数・論理・計算機科学</a>』、コンピュータをふだんから使っていて、もうちょっと数学的な考え方を知りたいよという人には、とっかかりとしてお勧めです。
</p>
<iframe src="http://rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=ss_til&asins=4274218961" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
<h2><a name="postscript">個人的なあとがき</a></h2>
<p>
本書のもとになっているのは、主に「数学」に関連したネタを扱う英語圏では有名な古参のブログ "Good Math / Bad Math" です。
"Good Math / Bad Math"は、いまほどインターネット上に一般向け数学ネタが溢れていなかったころから勢いのある筆致で数学系の記事を量産してきたブログで、
幾度かの移転を経て現在でもわりと活発に更新が続いています。
</p>
<a href="http://www.goodmath.org">
<blockquote>
"Good Math / Bad Math"<br/>
http://www.goodmath.org
</blockquote>
</a>
<p>
過去には『マンガでわかる統計学』の英語版に対する肯定的なレビューがアップされたことなんかもありました。
『マンガでわかる統計学』は英語版もかなりよく売れたんですが、その認知度はこのブログにおける紹介記事で一気にあがった感があります。
(ただしシリーズ全体の認知度として見ると、<a href="http://boingboing.net/2008/10/09/manga-guide-to-datab.html">Boing Boingで『マンガでわかるデータベース』がネタ的に扱われた</a>ことのほうが大きい)
</p>
<a href="http://www.goodmath.org/blog/2008/12/13/book-review-the-manga-guide-to-statistics/">
<blockquote>
"BOOK REVIEW: THE MANGA GUIDE TO STATISTICS"<br/>
http://www.goodmath.org/blog/2008/12/13/book-review-the-manga-guide-to-statistics/
</blockquote>
</a>
<p>
自分はたまたま『マンガでわかる統計学』の英語版に少し関与していたこともあって、
それからしばらく"Good Math / Bad Math"の記事をちょくちょくチェックしていました。
そんなある日、「<a href="http://www.goodmath.org/blog/2009/03/16/the-blog-and-the-book/">このブログをもとにして本を出すよ</a>」という記事が掲載されます。
しかも出版社はPragmatic Bookshelf社とのこと。
Pragmatic Bookshelf社といえば、『RailsによるアジャイルWebプログラミング』とか『プログラミングErlang』とか『情熱プログラマー』といったIT系書籍で有名な版元です。
これは面白い本になるに違いないと思いながら、続報を待つこと4年、ようやく2013年にベータ版の書籍が発売開始になったのでした。
</p>
<p>
さっそくβ版を自分で買ってKindleに突っ込み、一通り目を通してみて、「間違いなくそのうちどこかで日本語版が出るだろうな」と確信しました。
と同時に、あちこちマークアップの変換結果がコケていたりして、商品としての出来には微妙なところも感じていました。Pragmatic Bookshelf社では独自形式のXML原稿から紙の書籍と電子書籍を生成しているんですが、
それなりに数式が多く含まれる本書の原稿に対し、その変換処理の調整がいまいちうまくいっていないのは明白でした。
</p>
<p>
「どうせ日本語版が出るなら訳本には自分自身が関与したい、いやむしろ、自分が関与せずに日本語版が作られたら書籍として残念な出来になってしまいかねないぞ」
というわけのわからない使命感に駆られ、当時所属していた出版社で版権を抑えたうえで翻訳に興味がある有識者がいないかなーと思ってこんなツイートをしてみたのでした。
</p>
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">というわけで、あの伝説の数学ブロガーMARKCCによるプログラマ向け数学入門の "Good Math" を翻訳したいわけですが</p>— keiichiro shikano λ♪ (@golden_lucky) <a href="https://twitter.com/golden_lucky/status/458792252530106368">2014年4月23日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>
このツイートに見事に引っかかってくれたのが、そのちょっと前に「<a href="http://blog.elliptium.net/2011/09/1">スタート代数</a>」という勉強会を主催していた<a href="https://twitter.com/cocoatomo?lang=ja">cocoatomoさん</a>でした。
自分もスタート代数に何回か参加していたことから、お互いに何となく面識があったこともあって、企画を通して翻訳を進めてもらうまでは実に順調に話が進みました。
原著の原稿データから日本語版のPDFを自動生成する環境はこちらで用意し、cocoatomoさんにも翻訳をこまめにgit pushしてもらっていたので、
あとは日本語版が少しずつ形になっていくのを時々眺めていればいいという、(個人的には)きわめて理想的な感じで制作が進んでいきました。
</p>
<p>
ところが、翻訳がずいぶん進んで編集もぼちぼち開始し、これからいよいよ制作も本格化しようという段階になって、自分自身が会社を辞めるしかないという不測の事態になってしまいました。
発行までの実務は会社に残った同僚に引き継げることになったし、cocoatomoさんの好意でその後も翻訳制作の作業にリモートで口を出し続けることはできたのですが、直接の担当者として最後まで携われないまま辞めるというのは正直つらい選択でした(念のため補足しておくと、もっとつらいことがあったので辞めた)。
</p>
<p>
その翻訳版が、ついに6月25日に発行されることになりました。感無量です。
数式を含むマークアップの変換についても、仕込んでおいたCI上での作業プロセスを外注で回してもらえたので、書籍として申し分ない感じに仕上がっていると思います。いまの僕には、この本がものすごく売れても特に利益的なものはないのだけど(アマゾンアソシエイトについてはよろしくお願いします)、手に取ってもらう人が増えればとてもうれしいです。
</p>
k16http://www.blogger.com/profile/02349067627444091120[email protected]0tag:blogger.com,1999:blog-9197115.post-50394847319293707672016-06-08T16:49:00.001+09:002016-06-08T22:28:08.705+09:00Markdown原稿をGitHubで管理して本にする仕組みが出版社で導入されないわけ
<p>
これ、FAQっぽいんで、ちょっと私見を書いておこうと思います。
</p>
<p>
とくに技術書に関しては、<b>Markdownで原稿を書きたい</b>とか、<b>修正はPull Requestでもらえると楽</b>とか、そういう便利な世界を知っている人たちが執筆者なので、
「MS Wordで書いてもらった原稿を、こちらでDTPの担当者に組版してもらいます。修正は紙に赤字か、PDFをメールで送るので、そこにコメントを入れてください」という古き良き時代の出版社のやり方を目にすると、
「出版社って遅れてるよなー」という感想を抱かれることが多いのだと思います。
その結果、「<b>自分たちはITのプロとして出版のためのプラットフォームを作れるだろうから、それを使ってもらえないものか</b>」という方向の考え方に至るのはよくわかります。
</p>
<p>
しかし、これには、二つの面から「<b>ちょっと認識が違うから待って</b>」と言いたい。
</p>
<p>
まず「認識が違う」と思うのは、プレインオールドでない方法も部分的にはすでにけっこう導入されているという事実です。
とくに自分は、全面的に「<b>マークアップ原稿を最後の最後までGitHubで管理する</b>」ための仕組みを<a href="http://note.golden-lucky.net/2015/09/blog-post.html">もう何年も実際に運用して売り物の本を作ってきました</a>。
なので、「出版の中の人は現代的なプラットフォームを使えない」と言われると、どうしても「ぼくはちがうもん」と言いたくなるんですが、なんで自分はできてるのか、という点についてはあとで改めて書きます。
</p>
<p>
もう一つ、「出版のための現代的なプラットフォームが必要」という話に対して「うーん」って感じてしまうのは、
<b>ルールが決まってる組版で自由な表現をするための仕組みはどうするの?</b>という点に対する回答がないことです。
これは、原稿の形式と版管理ではどうにもならない問題です。
</p>
<p>
実際にそういうプラットフォームで売り物の本を制作してきた経験からすると、毎回いちばん頭を悩ませるのは、
プラットフォームをチューニングして、「<b>今回のプロジェクトで作りたい形の本を作れるようにする</b>」部分です。
毎回同じ体裁で似たような本を作るなら、yamlなどの設定を書き換えることによるシステム的なチューニングだけで済むかもしれません。というか、実際に済んでいます。
それでも、そのチューニングができる人が出版社の中に必要になるんですが、その程度なら、まあ、システムのお守りをする人がプロジェクトごとに担当者に要件を聞いて調整すればいいでしょう。
頭が痛いのは、「この本では見出しでこんな表現をしたい」とか、「強調をいくつか使い分けたい」とか、「標準的ではない構成にしたい」とか、そういう<b>個別の本の中身に対する要求に合わせたチューニング</b>です。
</p>
<p>
そういう要求を吸収できるようにシステムを作りたいということであれば、Markdownの原稿では絶対に無理(無理)なので、素直にLaTeXでもなんでも既存のプラットフォームを使おうよ。。(本音)
</p>
<h2>勝手が許されない「組版」と、自由な「レイアウト」と、それを吸収するプラットフォーム</h2>
<p>
出版物は、特に紙の本は、歴史がそれなりにあるので細部のルール(いわゆる組版)がわりときっちりしてます。
そのルールを逸脱していると、単純に読みにくい本になります。
このへん、ブラウザのレンダリングに任せればいいという発想でWebページを作るのとは違っているので、
たとえソースがXMLベースの原稿でも、本気のページ組版のためには、通常のブラウザエンジンではなく<a href="http://www.antenna.co.jp/AHF/">専用の</a><a href="http://www.princexml.com/">フォーマッター</a>が使われています。
もしブラウザのレンダリングエンジンでJavaScriptとCSSを使ってきちんと組版しようと思ったら、<a href="http://vivliostyle.com/ja/">専門の会社を一つ作らないといけないレベル</a>で大仕事です。
</p>
<p>
そんなわけで、出版物というのは、<b>組版というミクロな部分の見た目についてはあまり融通が利きません</b>。
誰でも使えるInDesignというアプリケーションがあるのにDTPがプロの仕事として成立してるのは、
一昔前の業種がいつまでも生き残ってるのでも、デザインセンスが必要だからだけでもなく、組版という仕事が本質的に専門知識を要求されるものだからです。
</p>
<p>
そうはいっても自動組版したい人、軽量マークアップの原稿を機械的に組版したい人にとっての選択肢は、いまは主にバックグラウンドでLaTeXを使うプラットフォームになると思います。
で、そのLaTeXですが、ご存じのとおり鬼門ですよね。
もっとも、Markdown+PandocやSphinx、Re:VIEWでとりあえずページ組版されたものを出すなら既成のスタイルを使うだけなので、とくに苦労はいりません。
</p>
<p>
問題は、ちょっと違った見た目にしたり、新しいレイアウト要素を追加したかったりする場合です。
これにはLaTeXのコマンドを使って自分でスタイルを書くしかありません。
しかも、新しいレイアウト要素を追加するにはそれだけでは済まず、ソースにおける構造とレイアウトとのマッピングを定義する必要があります。
自分は、このような<b>拡張が簡単にできないと死ぬ</b>と思ったので、かなり早い段階で<a href="https://github.com/k16shikano/xml2tex">そのためのDSLを開発してました</a>。
これまで十年くらい、「マークアップしたテキスト原稿を版管理」しながら「本として最後まで作り込む」という環境を実現できてたのは、こういう仕組みを作ったからです。
</p>
<p>
なお、これは自分だけでなく、「マークアップしたテキスト原稿を版管理」しながら「成果物として最後まで作り込む」を実現している人は、だいたいこのような構造とレイアウトのマッピングをする仕組みを自分たちで作り上げてるようです、というのを昔開催した「<a href="http://connpass.com/event/6724/">版管理+自動組版</a>」という勉強会で知りました。
</p>
<p>
厄介なのは、そういう仕組みを「誰もが使える」ようにする点です。
GitHubのようなベースとなるプラットフォームを使い始めてもらうためのハードルが高い<b>わけではありません</b>。
自分の経験だと、毎回の書籍原稿における<b>文書の構造とレイアウトを実現するメカニズムの両方をそれなりに理解しないといけない</b>のが唯一の障壁です。
そういうことを考えたい人が中に常駐していないと、プラットフォームがあったところで、多様な個々の本に対してそれを適用し続けることができないのです。
</p>
<h2>むしろ問われてるのは出版ビジネスの考え方かも</h2>
<p>
というわけで自分は、軽量マークアップのテキスト原稿をGitで管理して本にするという簡単な仕組みが出版社の中に普及しないのは、
そういうプラットフォームを使って勝手が許されない組版かつ自由なレイアウトを実現しながら本を作り込もうとする人が足りてないことが大きな理由だと思っています。
</p>
<p>
もっとも、これは「出版する本は作りこむべきだ」という個人的な思いによる分析なので、
単純なプラットフォームで実現できる形の本だけで出版というビジネスを回してやろう、という大胆な発想もありえると思います。
そういう発想を追求したい場合は、米O'reillyのAtlas+Safariのような仕組みや、Pragmatic Bookshelf社の取り組みについて調べてみるとよいと思います。
</p>
k16http://www.blogger.com/profile/02349067627444091120[email protected]2tag:blogger.com,1999:blog-9197115.post-11986988139431749362016-05-14T11:46:00.000+09:002016-05-14T12:34:53.757+09:00TeXと10年戦ってわかったこと<p>
世間では「TeX」と一口に言われているけど、実際には3つの異なる側面があります。10年以上TeXで何かやってきたわけだけど、「TeXはアレ」の本質はこの3つがごちゃごちゃになってるとこかなと思ったりしているので、書いてみました。
</p>
<ul>
<li>マークアップ形式としてのTeX</li>
<li>組版エンジンとしてのTeX</li>
<li>プログラミング言語としてのTeX</li>
</ul>
<p>
TeXの話をするときって、これら3つが案外と区別されていないなあと感じることがあります。具体的には、組版エンジンとしての機能について言及している場面でマークアップ形式の話を持ち出されたり、マークアップの話をしているときに名前空間がないからダメといった感じでプログラミング言語として批判されたり、ようするに、あまり建設的ではない。
</p>
<p>
もちろん、TeXというエコシステムについて何か言うときにはこの3つが不可分で、それぞれを切り出して論じてもしょうがないんだけど、まあポエムなので気にしないことにします。
</p>
<h2>マークアップ形式としてのTeX</h2>
<p>
TeXのマークアップというと<code>\</code>と<code>{}</code>がやたらに出てくるアレを思い浮かべると思いますが、「いわゆるTeXのマークアップ」と見なされているものに厳格な文法とかルールはありません。
よく、「XML自体はマークアップではなくマークアップを作る仕組みを提供するものだ」と言いますが、TeXはさらにひどくて、シンタックスさえもが自分の知っているTeXでない可能性があるのです。
</p>
<p>
現状のTeXは、いろいろな人や団体が過去に考案してきた「マークアップ」を、使う人が自分のユーザ文書の用途に応じて混ぜて使っている状態だといえます。
なので、たとえば「TeXのマークアップのパーザがほしい」といった要件を満たすものがあるとしたら、それはTeXそのものになります。
この、ユーザが目的に応じていくらでも変更できる余地がある、というのが、マークアップとしてのTeXの革新的かつ悲劇的な点なのかなと思っています。
</p>
<p>
とはいえ、だいたい用途ごとに「デファクト」のマークアップはあって、たとえば文章そのものに対する基本的なマークアップの文法でいま主に実用されているのはLamportさんが拡張したLaTeXです。
この、LaTeXで導入され、現在に至るまで主に使われている「いわゆるTeXのマークアップ」は、なかなかよく考えられているなあと思います(もとをただせばScribeのアイデアだし)。
数式に対するマークアップも、Knuthが考えたオリジナルTeXにおける数式の書き方を延々と使っているわけではなく、現在ではアメリカ数学会AMSが拡張したやつが広く使われています。
TeXの中で図を使うためのマークアップは、文章や数式とは別体系で、これはいまはTikZが主流になっています。
</p>
<p>
拡張したマークアップをパーズするための仕掛けはプログラミング言語としてのTeXで作ります。
また、その出力であるレイアウトは組版エンジンとしてのTeXで実現します。
</p>
<p>
というわけで、TeXのマークアップはひどい、ふつうの人には無理、という意見は、種々のマークアップが混在していることからくる感想なのかもしれないと思います。
<code>\</code>や<code>{}</code>や<code>$</code>はオリジナルのTeXに沿って使われることが大半なので、どれも構文は緩く似た感じになり、「えー、なんでこんな一貫性がないのー」って感じますよね。
できることに制約がないので、たとえば「○○用のマークアップとかないし、別の表現にするか」という発想にならず、「○○したいだけなのにこんな複雑なことをしなければならないのかくそが」という感想になりやすいという面もあると思います。
</p>
<p>
文章に対するマークアップとして見た場合、LaTeXのマークアップは別に筋は悪くはないんじゃないですかねえ。
現代的な構造化もできるし、もちろん必要に応じて拡張もできる(←そこがアレ)。
「マークアップ形式拡張のためのAPIを設計するセンス」を養う本とかどこかにないかなあ。
</p>
<h2>組版エンジンとしてのTeX</h2>
<p>
一部のアレな人以外、TeXを使う目的は組版でしょう。これについては、あまり批判的な人はいない気がします。
TeXは当初から組版のための要件がかなり高く、しかもそれが一通り実現されています。
さらに、それなりに長い歴史のなかで、本職の組版技術を知る人たちが自分たちの必要とする付加的な要件を本気で実現してきました。
そのため、ほとんどの人にとっては、世界中の多くの言語で実用的なブラックボックスとして機能できていると思います
(ふだん使っているTeXが組版についてブラックボックスに見えない人は、マークアップとしての側面と混同しているか、ただの組版のプロでしょう)。
</p>
<h2>プログラミング言語としてのTeX</h2>
<p>
なんというか、KnuthはもともとTeXをプログラミング言語として設計するつもりはさらさらなかったんじゃないかなあと思います。
自分の秘書でも使えるようなマークアップを自分で後から定義できるだけの機能を詰め込んだら、必然的にチューリング完全になってしまったというか。
あるいは、組版エンジンとして必要だろうなーと思う機能を作りこんでいて、その機能を外部からつつけるようにしたら、必然的にチューリング完全になってしまったというか。
とにかく、プログラミング言語としてのTeXにまともな設計思想はない気がするし、プログラミング言語として使いやすくする開発とかもされてこなかった。
なので使いづらいのは当然だし、使いづらさを楽しむのもまた一興かもしれません。
そもそもこれだけの機能がなかったら、後に続く人たちが「自分たちも仕事で使える」ものに魔改造できなかっただろうし(←その結果がアレ)。
</p>
<p>
とはいえ、そうも言ってられないという人たちは一定数いて、その先鋒がLaTeX3プロジェクトです。
それこそもう10年以上の歴史があるけど、過去のTeX資産を壊さないように慎重に開発が進められているので、いつになってもLaTeX3は完成しません(←だからアレ)。
</p>
<p>
とはいえ、LaTeX3のうちプログラミング言語として利用できる部分については現在のLaTeX2eでも使える状態にあります(expl3という)。
使いやすいかどうかはともかく、名前空間が実現できたり、関数っぽいものが定義できたり、プログラミング言語としてはふつうになってると思います。
次の10年に期待ですね(それまで選択肢がTeXしかないのも微妙だけど)。
</p>
k16http://www.blogger.com/profile/02349067627444091120[email protected]0tag:blogger.com,1999:blog-9197115.post-88565973411168187422016-05-02T10:07:00.001+09:002016-05-02T10:13:12.924+09:00執筆・編集のためのGit(GitHub)ワークフローを考えてみた
<p>
まとまった量の文章を執筆・編集するのにバージョン管理システムを使うことは、少なくとも技術文書においては特別なことではなくなりました。
原稿が汎用のテキストファイルの場合には、バージョン管理システムとして、GitやMercurialなどのソフトウェア開発用のツールを使いたいことが多いと思います。
実際、GitHubやGitBucketを利用して技術書やドキュメントの原稿を共同執筆するという話はとてもよく聞きます(知っている世間が狭いだけかもしれないけど)。
</p>
<p>
とはいえ文章の執筆・編集という作業には、プログラムのソースコードを開発する作業とは違う側面もいっぱいあります。
そのため、ツールとしてはソフトウェア開発用のバージョン管理システムを利用する場合であっても、そのワークフローについては、執筆・編集ならではの工夫が多少は必要なのかなと考えています。
</p>
<p>
もちろん、同じソフトウェア開発でもプロジェクトの種類や参加者の考え方によって最適なワークフローは異なるだろうし、
ソフトウェア開発で成功するワークフローが執筆・編集には適用できないなんていうことでもありませんが、
こうやったら技術書を作る時にうまくいった、あるいはうまくいかなかったという経験に基づく考察をここらでいったん公開しておくのは悪くないかなと思ったので、まとめてみました。
</p>
<p>
なお、あくまでも経験に基づいた独断を書きなぐったものなので、これが正解と主張するものではないし参考文献とかもありません。
また、バージョン管理システムとしてGit(GitHub)が前提の書きっぷりになると思いますが、これも自分の経験に基づく話だからというだけです。
が、だいたいどのバージョン管理システムでも通用する話であろうな、とは想像しています。
</p>
<p>目次</p>
<blockquote>
<ol>
<li><a href="#onehistory">正史モデル:伝統的な文章のバージョン管理ワークフロー</a></li>
<li><a href="#documentationnature">執筆・編集というプロジェクトの実態</a>
<ul>
<li><a href="#twophases">執筆・編集には2つのフェーズがある</a></li>
</ul></li>
<li><a href="#versioning">「じっくり読まなければ何となくいい感じ」が分水嶺</a>
<ul>
<li><a href="#reason">表面的な問題:統一感と文の品質</a></li>
<li><a href="#birdsview">根本的な対策:段落や節にまたがる俯瞰的な修正</a></li>
</ul></li>
<li><a href="#bestpractice">執筆・編集にとって最適(いまのところ)だと思っているGitワークフロー</a></li>
<li><a href="#howtoknow">余談:「じっくり読まなければ何となくいい感じ」に到達したことを知るには</a></li>
</ol>
</blockquote>
<hr/>
<h2><a name="onehistory">正史モデル:伝統的な文章のバージョン管理ワークフロー</a></h2>
<p>
旧来、印刷して出版される文書は、初校、再校、念校、下版といった形式でバージョン管理されていました。
複数の関係者がいる場合には著者の代表や編集者が全員の意見(赤字)をマージして一つの修正指示を練り上げ、それが次の校正に反映されるというワークフローです。
つまり、正史が一つだけ存在するモデルです。
</p>
<div class="separator" style="clear: both; text-align: center; margin-top: 2em; margin-bottom: 2em; "><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIbiGmdhXWLX7J3u63XP49S_jdVKDoQFkUqlx4qg5PuA_a2ap5NaJ2hQDYJhlByzw5CCcIrRyvTCSYyLXF5FR_GqEKUGzaC3rCeHnekSmy0sxw34a7JBB5mBHW_kS9nmpViHQm/s1600/one-history.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIbiGmdhXWLX7J3u63XP49S_jdVKDoQFkUqlx4qg5PuA_a2ap5NaJ2hQDYJhlByzw5CCcIrRyvTCSYyLXF5FR_GqEKUGzaC3rCeHnekSmy0sxw34a7JBB5mBHW_kS9nmpViHQm/s600/one-history.jpg" /></a></div>
<p>
この伝統的な正史モデルのワークフローに、バージョン管理システムを適用したいとして、いちばん分かりやすいのは次のようなマイルストーンの細分化でしょう。
</p>
<div class="separator" style="clear: both; text-align: center; margin-top: 2em; margin-bottom: 2em; "><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbibJtPEmJ9450aKwfrH0uVPCtIqh8n5r_mH2i4VSAQKb4Z4y6xmT_CrO5-zCzScbHzc_fgI7XjKcaFgY1E1MKkYvWNklJJu_EqdNs8DFg9hRg0aUYmKCg4GRf8ufSwl9cgxEw/s1600/vcs.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbibJtPEmJ9450aKwfrH0uVPCtIqh8n5r_mH2i4VSAQKb4Z4y6xmT_CrO5-zCzScbHzc_fgI7XjKcaFgY1E1MKkYvWNklJJu_EqdNs8DFg9hRg0aUYmKCg4GRf8ufSwl9cgxEw/s600/vcs.jpg" /></a></div>
<p>
従来であれば数日から数カ月おきに確定するバージョン(初校とか再校とか)の間に、バージョン管理システムを使って細かくコミットを重ねていくイメージです。
さらにこのワークフローを突き詰めれば、初校や再校といった従来のマイルストーンの役割も消えて、全期間にわたってコミット履歴だけが並ぶことになるでしょう。
もちろん何らかのマイルストーンは設定することになるでしょうが、いずれにせよワークフローとしてはあくまでも一直線です。
</p>
<p>
このワークフローでは、みんなが同一のmasterに対してコミットを重ねていくため、誰かの作業内容が妥当であるかどうかを意識的に確認する役割の人がいるのがベターです。
ただし経験では、そのような役割を特定に人に押し付けるのではなく、関係者全員が「あれっ」と思った時点で履歴を検索して適宜blameや再修正をかけられるような空気があるほうが、うまく回ることが多かったと思います。
そのような空気は、関係者どうしの広帯域なコミュニケーションを通じて醸成されますが、
メール(メーリングリスト)、バグトラッキングシステム(TracやGitHub issue)、会議システム(SlackやSkype)を複数併用していた場合にわりとうまくいっていた印象があります。
</p>
<h2><a name="documentationnature">執筆・編集というプロジェクトの実態</a></h2>
<p>
正史モデルのワークフローには、従来型の延長なので比較的導入しやすいというメリットがありますが、制限もあります。
このワークフローでは、どのコミットも、それまでの作業を塗りつぶして上書きする作業として扱います。
あとからコミット単位でrevertしたりrebaseしたりすることをあまり考慮していないワークフローだということです。
</p>
<p>
せっかくバージョン管理システムを使うのだから、作業の内容を明確化してブランチを切ったり、
それをあとからチェリーピックしたりマージしたり、逆に過去に加えた変更をなかったことにしたり、
そういうことができるほうがうれしいですよね。
正史モデルに拘泥してアドホックな上書き修正を積み重ねるのではなく、修正の意図や作業内容に応じてコミットをきっちり切り分けることで、原稿の変更による手戻を防いだり差分を見やすくしたりできるはずです。
</p>
<p>
ところが、経験上、文章の執筆・編集では作業内容ごとにコミットを整理したりブランチを切ったりするのが難しいなあと感じる場面がとてもよくあります。
文章の修正を局所的で互いに独立したコミットに収めることができず、コミットどうしが密に結合したり、一見すると巨大すぎるような修正コミットが発生したり、他の人の作業と競合したりしがちなのです。
</p>
<p>
もちろん、だからといって文章の執筆・編集では正史モデルで徹頭徹尾やるべきという話ではありません。
これまでの経験で感じるのは、うまくコミットとして切り分けられる問題もあれば、コミットとして切り分けるのが徒労でしかないような問題もある、という単純な事実です。
この二種類の問題を整理したところ、執筆・編集という作業には2つのフェーズがあり、この両フェーズを意識するとそこそこ最適なワークフローが説明できそうだなと気がつきました。
</p>
<h3><a name="twophases">執筆・編集には2つのフェーズがある</a></h3>
<p>
正史モデルの説明では、「脱稿」以降のワークフローについてバージョン管理システムを使うかのように説明しましたが、あれは嘘です。
バージョン管理システムを使って、共著者、編集者、外部のレビュアーによる共同作業を始めるのは、脱稿よりも前の段階、具体的には「内容をすべて書き出した」時点であるべきです。
</p>
<p>
ここが重要なんですが、「内容をすべて書き出した」時点は脱稿とは異なります。
「内容をすべて書き出した」時点は、ソフトウェア開発でいうと、まだ最低限の機能がコンパイルすら通っていない状態です。
ここから待っているのは下記のような作業です。
</p>
<ul>
<li>段落や節の見直し、統廃合、順序の入れ替え</li>
<li>それにともなう文章の書き直し、表現や語調の調性</li>
<li>全体にわたる用字用語(漢字の使い方とか)の統一、誤用や誤植の修正</li>
<li>タグやメタ情報(ルビとか索引とか)の修正、追加</li>
</ul>
<p>
各作業について具体的な内容には踏み込みませんが、ようするに、全体にわたる読み直しとリライトを何度か繰り返すことで、これらの問題をひとつずつ潰していく必要があります。
そうやって確認と修正を繰り返していると、あるときふいに原稿が「じっくり読まなければ何となくいい感じ」になっていることに気づきます。
このへんでようやく、ソフトウェアでいえば警告を無視すればコンパイルが通った状態、つまり本当の意味での「脱稿」の一歩手前です。
</p>
<div class="separator" style="clear: both; text-align: center; margin-top: 2em; margin-bottom: 2em; "><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhKfYbvvOz5fEiv3sXsc92nGRDC-Tahyb3hIiijG83e45SRPgYFY9guIYoLc02TioeJqZxLzb0uN3Z3RCdquOEotoR8BPWd4A4cg1Z4-yOAzvhHZPjgJ6jFhsRcoP1g1xUt2uI/s1600/two-phases.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhKfYbvvOz5fEiv3sXsc92nGRDC-Tahyb3hIiijG83e45SRPgYFY9guIYoLc02TioeJqZxLzb0uN3Z3RCdquOEotoR8BPWd4A4cg1Z4-yOAzvhHZPjgJ6jFhsRcoP1g1xUt2uI/s600/two-phases.jpg" /></a></div>
<h2><a name="versioning">「じっくり読まなければ何となくいい感じ」が分水嶺</a></h2>
<p>
「じっくり読まなければ何となくいい感じ」ゾーンまでくると、文書の骨組みや各文に対する大幅な修正は起こりにくくなります。
したがって、「どこそこのタイポ修正」とか「この文を修辞的に書き換える」とか「この段落は内容が疑わしい」といった具合に、文書に存在する問題を局所化できる場合が多くなります。
「どの箇所にどんな修正がなぜ必要か」をかなり具体的に切り出せるようになるということです。
</p>
<p>
修正が必要な箇所と、その意図をはっきり区分できるのだから、修正の妥当性や方針をissueで議論したり、必要だと判断できた修正を切り分けたり、そういった作業が現実的になります。
「じっくり読まなければ何となくいい感じ」にまで到達した原稿に対しては、issueやブランチを切ったうえで、それに従ってコミットを細かく管理したりPull Requestを発行したりするワークフローが可能だともいえます。
</p>
<p>
問題なのは、まだ「じっくり読まなければ何となくいい感じ」に到達していない原稿です。
この段階になっていない文章を読むと、「どの箇所にどんな修正がなぜ必要か」をはっきりとは明言しにくいけれど、とにかく何かしら修正が必要であると感じます。
経験上、この段階の原稿が抱えている問題の多くは、切り分けが困難な問題です。
そのため、バージョン管理という視点で考えると、作業を分担したり作業内容に応じたコミットやブランチを駆使しようという努力があまり実を結ばない気がしています。
</p>
<h3><a name="reason">表面的な問題:統一感と文の品質</a></h3>
<p>
「内容をすべて書き出した」時点での原稿は、ソースのバージョン管理という観点で見ると、下記のような問題を抱えている状態です。
</p>
<ul>
<li>統一感がない</li>
<li>読みにくい文がある「ように感じる」</li>
</ul>
<h4>統一感がない</h4>
<p>
「内容をすべて書き出した」時点の原稿で用字用語がきれいに整っているケースはまずありません。
言葉遣いや文体、文章の温度もまちまちです。
なんとなく統一感がない状態です。
</p>
<p>
用字用語が揺れているだけなら機械的に対処できる面はかなりあるし、そのためのツールもいくつかあります。
とはいえ、「いう」と「言う」の使い分けみたいな、書き手がふだんあまり意識せずに書いている表現ほど、自動的な統一だと不自然な結果になったり、そもそも自動化しにくいように思います。
結局、けっこうなボリュームの本を編集するときは、頭から読みながら気になった時点でgrepして全体に修正をかける、といった作業をある時点で誰かがやっています。
そして、この作業は、たとえば用語ごとに独立したコミットとして切り分けるのが案外と困難なのです。
しかも、経験上は切り分ける意味もほとんどありません。
</p>
<p>
文章の統一感を上げる作業を、独立した細かいコミットとして切り分けにくい(切り分ける意味があまりない)理由としていちばん大きいのは、単一の行に複数の用語揺れが混在するケースが珍しくないからです。
「行う」と「行なう」の揺れを正す作業と、「無い」を「ない」に開く作業を別々の人がやれば、「行なわ無い」という非標準的な表記を「行わない」に直すだけであっさり衝突します。
</p>
<p>
それでもコミットを細かく分割すべきという考え方もあると思いますが、個人的な意見としては、
これはソフトウェア開発で「関数の仕様を変更したので関数名と引数リストを同時に修正しなければならないが、コミットとしては関数名に対する修正と引数リストに対する修正とで区分する」みたいな話に近いと思っています。
つまり実質的には分割の意味がほとんどない。
</p>
<p>
もう一つの理由は、他の修正作業との関係です。
ソフトウェア開発でも、バグ修正とコーディング規約に合わせる作業を同時にやれば、同一の行に対して何度も修正、加筆、削除、入れ替えが発生し、そのため競合が発生しやすくなるでしょう。
文章でも、統一感を上げる作業を文章・段落・節全体などの見直し作業と同時にやれば、解消に手間がかかる競合が多発します。
そのため、たとえば「用字用語の統一」のためのブランチを切って作業し、後でPull Requestとして一発でマージ、といった理想的に見えるワークフローは、他の作業をまじめにやっているケースほど非現実的だと考えています。
この作業は、ブルトーザーで荒地を耕すようなものだと割り切って、見つけた誰かがmasterに対して随時pushしていくほうが経験上はうまくいきます。
</p>
<h4>読みにくい文がある「ように感じる」</h4>
<p>
プログラムなら、コンパイルして型エラーが出たりテストに通らなかったりすれば問題の位置がかなり絞り込めます。
文章でも、文法上のミスや文章の品質については、指摘して問題箇所を特定してくれるツールがいくつかあります(textlintとかRedPenとかJustRight!とかMS Wordの校正ツールとか)。
とはいえ、人間が読むために書いているものをチェックしようとしている以上、結局は誰かが読んで初めて見えてくる問題がかなりあるわけです。
文意に曖昧さがないかとか、語調が不自然でないかとか、そういう問題は実際に読んでみなければ見えてきません。
</p>
<p>
こういった問題を修正しようとして、「この文を読みやすくした」とか「文意をはっきりさせた」といった名目で局所的なコミットをたくさん作ってしまうと、あとで面倒なことになります。
というのも、文章を読むことで初めて見つかるような問題というのは、実際には文章レベルより上位の段落や節が抱える問題の一部であることが多いからです。
このような問題に対する局所的な修正コミットや、それを意図したPull Requestは、後述する「段落や節に対する俯瞰的な修正」のための作業と競合してしまいます。
</p>
<p>
このような競合では、「段落や節に対する俯瞰的な修正」のほうが修正として適切なことが多いので、「局所的な修正」の作業は単純に水泡に帰すことになります。
「じっくり読まなければ何となくいい感じ」未満の原稿では、「局所的な修正」は「段落や節に対する俯瞰的な修正」と競合するものだと考えたほうがいいでしょう。
この段階の原稿に対しては、コミットを小さくすることが正義とは限らないともいえます。
「段落や節に対する俯瞰的な修正」を先にやることにして、気が付いた局所的な問題はissueなどの形でコメントを残すのみにしておくのが無難かもしれません。
</p>
<h3><a name="birdsview">根本的な対策:段落や節にまたがる俯瞰的な修正</a></h3>
<p>
コードが適切にモジュール化されているソフトウェア開発であれば、それほど変更が衝突することなく、個々のモジュールに対する作業を別々の人が同時にできるでしょう。
文章でモジュールに相当するのは段落ですが、段落は互いに密に結合しているし、抽象的なインタフェースもないので、互いの順序や文章表現について同時に配慮が必要です。
そのため、段落ごとに執筆や編集を分担するという方法は、あまりいい結果になりません。
とりあえずまとまった量を読んでみないと問題を切り分けられないし、切り分けている途中で問題が直せてしまったりするので、
判断を下しながらある程度の範囲を集中して読み進める、という工程が必要になります。
</p>
<p>
で、そういう不備を直していると、結果としてまったく別の問題が解消されたりすることがよくあります。
段落がまるまる修正されたので誤植が消滅したとか、段落を直した結果としていまいち曖昧だった文意がはっきりしたとか、
リライトが必要と思われた節とほぼ同じ内容の説明が他の場所にあったので節ごと不要になったとか。
しかし、誰かが該当する文章を局所的に修正していたり用字用語の統一を全体にわたってかけたりしていると、当然、その部分で競合が発生します。
</p>
<p>
俯瞰的な修正の作業は、かなり大きな範囲全体でコミットとして意味を持つので、他でコミットされたりPull Requestされた局所的な文章の修正をこのコミットの内容と調整するのはけっこう厄介です。
経験上うまくいくのは、たとえば「1章の見直し」といった作業内容ベースでブランチを切り、別のブランチでの1章に対する修正は用字用語の統一くらいに留めておく(この程度なら手動でマージできる)というワークフローです。
修正する内容に対するブランチを作るのではなく、修正する範囲を区切るためにブランチを作るイメージです。
このブランチでは、最終的にmasterへと自動マージできるような状態を維持しながら(masterの内容をときどきmergeしながら)、修正作業を続けるようにします。
</p>
<h2><a name="bestpractice">執筆・編集にとって最適(いまのところ)だと思っているGitワークフロー</a></h2>
<p>
以上、だらだらと背景を書いてきましたが、結論です。
</p>
<p>
「内容をすべて書き出した」状態から「じっくり読まなければ何となくいい感じ」ゾーンにもっていくまでの間は、各コミットに必要以上に意味を持たせることはあきらめましょう。
完全に正史モデルを採用する必要はありませんが、この段階は開墾地をブルトーザーで整地するようなものです。
「木を抜く」作業と「穴を埋める」作業は並行してできるわけではないし、あとから一方の作業だけをやり直したいことも通常はありません
(将来もし穴が必要になるとしたら、それは別の作業として考えるべきでしょう)。
それなりの規模の区画ごとに、全体の出来を眺めつつ、もくもくと均していくのが現実的なはずです。
</p>
<p>
一方、「じっくり読まなければ何となくいい感じ」ゾーンまで到達した原稿は、問題とその対処がコミットとして明確に切り分けられるので、修正の意図をはっきりさせた最低限のコミットを作り、それをmasterにマージするようにしましょう。
</p>
<p>
まとめると、次のようなポリシーで執筆・編集をするのがよさそうだというのが現時点での結論です。
</p>
<ul>
<li>「じっくり読まなければ何となくいい感じ」まで達している原稿は、これから入れる修正の意図を明らかにしたいので、issueで議論してからコミットしたり、ブランチを切ってPull Requestにしたりする</li>
<li>それ以前の段階では、用字用語統一、誤記修正、タグ追加などの作業はブルドーザーによる整形作業だと割り切り、細かく管理するのはあきらめる。経験上、どのみちrevertやrebaseが不可能な作業なので徒労に終わる。信頼できる担当者どうしで作業をしているなら、見つけた人がmasterに随時pushするのが、他の作業との競合を回避するためにも効率的</li>
<li>それ以前の段階における局所的な文章の修正は、「じっくり読まなければ何となくいい感じ」ゾーンまではissueやコメントに留める。それ以降はPull Requestにする</li>
<li>それ以前の段階における節以上の範囲におよぶ内容上の修正は、作業範囲を隔離するためのブランチを切って作業する(このブランチではmasterにおける用字用語統一などの修正を適宜取り込みながら作業をする。Pull Requestにしてからマージしてもよいし、手動でマージしてもよい)</li>
</ul>
<div class="separator" style="clear: both; text-align: center; margin-top: 2em; margin-bottom: 2em; "><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7c53GnJdIHd24QEvjZPIjEj8UvhyphenhyphenrwoTUTWIGtkLcGdavKSbHkRZ6A7KV4c8FvXKwq8gedILPXBc_dOXWqqB77xP7ldGWuh8awP1_tysnkeIYYMzID7CaBGEntZBG-2hkJnlf/s1600/workflow.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7c53GnJdIHd24QEvjZPIjEj8UvhyphenhyphenrwoTUTWIGtkLcGdavKSbHkRZ6A7KV4c8FvXKwq8gedILPXBc_dOXWqqB77xP7ldGWuh8awP1_tysnkeIYYMzID7CaBGEntZBG-2hkJnlf/s600/workflow.jpg" /></a></div>
<p>
このほか、本文では言及しませんでしたが、下記のようなポリシーも経験上は有効であると考えています。
</p>
<ul>
<li>脚注追加のように独立性が高いコミットとして修正を加えられる場合には、どの段階でもPull Requestにしてよい</li>
<li>メタ情報を、永遠にマージしないブランチで管理することもできる。索引タグなどは本文にマージする必要がないかもしれない</li>
</ul>
<h2><a name="howtoknow">余談:「じっくり読まなければ何となくいい感じ」に到達したことを知るには</a></h2>
<p>
というわけで、文章のバージョン管理では「じっくり読まなければ何となくいい感じ」に至る前後のフェーズでコミットに対する考え方を変えよう、というのが現時点での自分の結論なのですが、
そもそも原稿の状態がこのティッピングポイントを越えたことはどうやって知ればいいのでしょうか?
</p>
<p>
残念ながら分かりやすい指標はまだ手にしていません。
しかし、循環論法めいていますが、ほぼすべてのコミットの意図を明確にできるようになった原稿は「じっくり読まなければ何となくいい感じ」になっているといえそうです。
その瞬間に気づくためには、いま施している修正が他の修正に依存していないかどうかを常に意識しながらコミットを刻む必要があるのかもしれません。
</p>k16http://www.blogger.com/profile/02349067627444091120[email protected]0tag:blogger.com,1999:blog-9197115.post-82600221757226429782016-02-29T09:00:00.000+09:002016-02-29T09:58:11.263+09:00バイナリ化したデータ構造を外部のファイルに保存して、コンパイル時にHaskellソースに埋め込む<p>
Haskellには連想配列のように使えるMapというデータ構造(<code>Data.Map</code>)があります。
実行中にキーと値を更新するつもりがなく、コンパイル時に生成される固定的なMapを実行時に毎回使うという場合には、
リテラルのリストをソースコードに書いてMapに変換して使うのですが、
リストのサイズが1万要素とかになるとソース全体が肥大化してコンパイルに無駄な時間がかかるようになります。
生のリストをコンパイルのたびになめる必要はないのだから、Mapに変換したデータを辞書のように外部に持っておいて、
それをソースから読み込んで使う方法があるに違いありません。(ようするに、RubyでいうMarshal、PythonでいうPickleがしたい、ということです。)
</p>
<p>
他のファイルの内容をHaskellソースに埋め込むには、一般に<a href="https://wiki.haskell.org/Template_Haskell">Template Haskell</a>が必要です。
ありがたいことに、外部のファイルの内容をソースコードに埋め込む機能に特化した<a href="https://hackage.haskell.org/package/file-embed"><code>file-embed</code></a>という便利なパッケージが用意されているので、これをTemplate Haskellと一緒に利用してこの問題を解決してみました。
</p>
<h2>バイナリの辞書を作る</h2>
<p>
まず、外部に保持するバイナリ辞書を下記の手順で用意します。
</p>
<ol>
<li>リストからMapを作る</li>
<li>そのMapをバイナリ化する</li>
<li>さらにGzipで圧縮</li>
<li>結果を別ファイルに書き出す</li>
</ol>
<p>
コードにするとこんな感じ。このコードはバイナリの辞書(Map)を生成するだけなので、コンパイルと実行はきっかり一回だけです。
</p>
<p style="indent:0; font-size:90%">▼ <code>mkdict.hs</code></p>
<pre>
<font color="#ff99ff">{-# LANGUAGE OverloadedStrings #-}</font>
<font color="#0099ff">import qualified</font> <font color="#669900">Data.ByteString.Lazy</font> <font color="#0099ff">as</font> <font color="#669900">BSL</font>
<font color="#0099ff">import qualified</font> <font color="#669900">Data.ByteString.Lazy.UTF8</font> <font color="#0099ff">as</font> <font color="#669900">BSLU</font>
<font color="#0099ff">import qualified</font> <font color="#669900">Data.Map</font> <font color="#0099ff">as</font> <font color="#669900">Map</font>
<font color="#0099ff">import</font> <font color="#669900">Codec.Compression.GZip</font> (compress)
<font color="#0099ff">import</font> <font color="#669900">Data.Binary</font> (encode)
<font color="#ff9933">dictList ::</font> [(<font color="#669900">Int</font>, <font color="#669900">BSLU.ByteString</font>)]
<font color="#ff9933">dictList =</font>
zip [1..] <font color="#ff9933">$</font>
(map <font color="#669900">BSLU</font>.fromString [<font color="#ff99ff">"西住"</font>, <font color="#ff99ff">"武部"</font>, <font color="#ff99ff">"秋山"</font>, <font color="#ff99ff">"五十鈴"</font>, <font color="#ff99ff">"冷泉"</font>, ...その他大勢 ]
<font color="#ff9933">main</font> = <font color="#0099ff">do</font>
<font color="#669900">BSL</font>.putStr <font color="#ff9933">$</font> compress . encode . <font color="#669900">Map</font>.fromList <font color="#ff9933">$</font> dictList
return ()
</pre>
<p>
ここでのポイントは、Mapのもとになる連想リストに日本語などの多バイト文字列がある場合、<code>Data.Text</code>ではなく<code>Data.ByteString.Lazy.UTF8</code>を使うことです。
なぜ<code>Data.Text</code>が使えないかというと、バイナリ化に使う<code>Data.Binary</code>が<code>Data.Text</code>に対応していないためです。
また、<code>Data.ByteString.Lazy.Char8</code>ではバイト列がぶった切られて日本語の文字が壊れてしまうので、結果的に<code>Data.ByteString.Lazy.UTF8</code>を使うしかありません。(ほかによい方法があったら教えてください)
</p>
<h2>バイナリ辞書をソースに埋め込んで使う</h2>
<p>
上記で生成したバイナリ辞書を<code>dict.dat</code>のような名前でどこかに保存したら、
下記のようにしてHaskellソースに埋め込んで使います。
</p>
<ol>
<li><code>embedFile</code>関数にファイルを指定すると、Template HaskellのQモナドにくるまれたデータが返ってくるので、これを<code>$(...)</code>で取り出す(というかソースファイル中に接ぎ木する)</li>
<li>接ぎ木されるデータは正格なByteStringなので、<code>fromChunks</code>で遅延ByteStringに変換する(<code>fromChunks</code>はByteStringのリストをとるので、リストの文脈に入れるために<code>return</code>している)</li>
<li>圧縮された状態を解凍</li>
<li>バイナリをほどく</li>
</ol>
<p style="indent:0; font-size:90%">▼ <code>getmessage.hs</code></p>
<pre>
<font color="#ff99ff">{-# LANGUAGE TemplateHaskell #-}</font>
<font color="#0099ff">import qualified</font> <font color="#669900">Data.ByteString.Lazy</font> <font color="#0099ff">as</font> <font color="#669900">BSL</font>
<font color="#0099ff">import qualified</font> <font color="#669900">Data.ByteString.Lazy.UTF8</font> <font color="#0099ff">as</font> <font color="#669900">BSLU</font>
<font color="#0099ff">import qualified</font> <font color="#669900">Data.Map</font> <font color="#0099ff">as</font> <font color="#669900">Map</font>
<font color="#0099ff">import</font> <font color="#669900">Data.FileEmbed</font> (embedFile)
<font color="#0099ff">import</font> <font color="#669900">Codec.Compression.GZip</font> (decompress)
<font color="#0099ff">import</font> <font color="#669900">Data.Binary</font> (decode)
<font color="#ff9933">dictMap ::</font> <font color="#669900">Map.Map Int BSLU.ByteString</font>
<font color="#ff9933">dictMap =</font> decode . decompress <font color="#ff9933">$</font> <font color="#669900">BSL</font>.fromChunks . return <font color="#ff9933">$</font> $(embedFile <font color="#ff99ff">"data.dat"</font>)
<font color="#ff9933">getMember</font> id = putStrLn <font color="#ff9933">$</font> <font color="#0099ff">case</font> <font color="#0099ff">Map</font>.lookup id dictMap <font color="#0099ff">of</font>
<font color="#669900">Just</font> x <font color="#ff9933">-></font> <font color="#669900">BSL</font>.toString x
<font color="#669900">Nothing</font> <font color="#ff9933">-></font> error <font color="#ff9933">$</font> <font color="#ff99ff">"No entry for "</font> <font color="#ff9933">++</font> id
</pre>
<p>
実行結果
</p>
<pre>
<font color="#0099ff">$</font> <b>ghc mkdict.hs -o mkdict</b>
<font color="#808080">[1 of 1] Compiling Main ( mkdict.hs, mkdict.o )</font>
<font color="#808080">Linking mkdict ...</font>
<font color="#0099ff">$</font> <b>./mkdict > data.dat</b>
<font color="#0099ff">$</font> <b>ghci</b>
<font color="#808080">GHCi, version 7.10.3: http://www.haskell.org/ghc/ :? for help</font>
<font color="#0099ff">Prelude></font> <b> :l getmember.hs</b>
<font color="#808080">[1 of 1] Compiling Main ( getmember.hs, interpreted )</font>
<font color="#808080">Ok, modules loaded: Main.</font>
<font color="#0099ff">*Main></font> <b>getMember 3</b>
秋山
<font color="#0099ff">*Main></font> <b>getMember 5</b>
冷泉
<font color="#0099ff">*Main></font>
</pre>
<h3>参考資料</h3>
<dl>
<dt><a href="https://wiki.haskell.org/Compiling_in_constants">Compiling in constants(Haskell Wiki)</a><dt>
<dd>
Gzipしたバイナリデータのリテラル表現をソースに埋め込んでいる事例(そんな人間が見ても意味がないデータをソースに貼り付けるのはいやだ)。
バイナリ辞書をCに変換して利用する例も紹介されているけど。
</dd>
<dt><a href="https://gist.github.com/yuga/8255552">Haskellでバイナリデータ(yuga/gist:8255552)</a></dt>
<dd><code>Data.Text</code>に対応したバイナリライブラリがなさそうなんだなということが分かりました。</dd>
<dt><a href="http://stackoverflow.com/questions/6402158/how-to-compile-a-resource-into-a-binary-in-haskell">How to compile a resource into a binary in Haskell?(Stack Overflow)</a></dt>
<dd><code>file-embed</code>パッケージの存在を知りました。</dd>
</dl>k16http://www.blogger.com/profile/02349067627444091120[email protected]0tag:blogger.com,1999:blog-9197115.post-27972464376870143032016-02-21T20:14:00.000+09:002016-02-21T20:14:55.095+09:00ターミナルモードのEmacsでHaskellを書いているときに補完候補をポップアップしてくれるcompany-ghc<p>
Haskellのコードを書くときは、Windows 10からTeratermでDebianサーバにSSH接続し、そこでEmacsを<code>-nw</code>で起動して使っています。
標準の<code>haskell-mode</code>でとくに不満はないのですが、いちおう<code>ghc-mod</code>も入れていて、単純なエラーの確認にはとても重宝しています。
でも、<code>ghc-mod</code>の補完機能はほとんど使っていませんでした。補完のためのコマンドが手になじまず、調べている間に手打ちしてしてしまうので、ちっとも身に付かなかったからです。
</p>
<p>
とはいっても、ある程度の量を書いていると、やはり手で打っているのではしんどくなってきます。何とかならないかなーと思っていたところ、<code>company-ghc</code>というものを発見しました。
</p>
<a href="https://github.com/iquiw/company-ghc">
<blockquote style="background-color:white;">
Company GHC<br/>
https://github.com/iquiw/company-ghc
</blockquote>
</a>
<p>
ターミナルで開いているEmacsでも、統合開発環境のような補完メニューを実現する<a href="https://company-mode.github.io/"><code>company-mode</code></a>というツールがあって、そのHaskell版を<code>ghc-mod</code>を介して実現するためのパッケージらしい。試しにインストールしてみたところ、こんなふうに、まるで統合開発環境のようになりました。これならぼくにも使えそう。
</p>
<p>
<div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikptgeAfBdqE6UFH0yVdlLSX-yU9YS39wwUo2g3Los8E1SdAo1Q_eOhIkDFXCuER937Ptyv2-UpYshPB668OmluVKx6CVemGd6uAuOGWHbRw75rmBVyBaBbOUTtXjoHkEZTYet/s1600/datalist.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikptgeAfBdqE6UFH0yVdlLSX-yU9YS39wwUo2g3Los8E1SdAo1Q_eOhIkDFXCuER937Ptyv2-UpYshPB668OmluVKx6CVemGd6uAuOGWHbRw75rmBVyBaBbOUTtXjoHkEZTYet/s480/datalist.png" /></a></div>
</p>
<h2>インストールと設定の概略</h2>
<p>
すでに<code>ghc-mod</code>を入れているなら、そのインストール時にEmacsのパッケージを<a href="https://melpa.org/">MELPA</a>から取得できる状態にしていると思います。その場合は、<code>M-x package-install</code>で<code>company-ghc</code>を指定するだけで、必要なパッケージを含めてインストールしてくれます(したがって事前に<code>company-mode</code>を個別にインストールする必要もありません)。MELPAからパッケージを取得する設定にしていない場合は、<code>init.el</code>かどこかに以下を設定します。
</p>
<pre>
(require 'package)
(add-to-list 'package-archives
'(<font color="green">"melpa-stable"</font> . <font color="green">"http://stable.melpa.org/packages/"</font>) <font color="blue">t</font>)
(package-initialize)
</pre>
<p>
無事にインストールできたら、まずは<code>company-mode</code>を有効にします。<code>haskell-mode</code>利用時のみ有効にすることも可能ですが、せっかくなのでグローバルに有効にしておきます。そのほうが<code>Ctrl-c Ctrl-l</code>でGHCiを起動したときにも補完が効くようになるし、いろいろ便利なはず。
</p>
<pre>
(require 'company)
(global-company-mode)
</pre>
あとは下記のように<code>company-ghc</code>を設定すれば完了です。
<pre>
(add-to-list 'company-backends 'company-ghc)
(custom-set-variables '(company-ghc-show-info <font color="blue">t</font>))
</pre>
<p>
これだけでもとりあえず動くはずですが、<code>company-mode</code>のパラメータを少しいじったほうが使いやすそう。
</p>
<pre style="overflow-x:auto; white-space:pre; word-wrap: normal;">
(setq company-idle-delay 0.5) <font color="green">; 補完候補を表示するまでの待ち時間</font>
(setq company-minimum-prefix-length 2) <font color="green">; 補完候補の表示を開始する入力文字数</font>
(setq company-selection-wrap-around <font color="blue">t</font>) <font color="green">; 補完候補のスクロールが末尾に到達したら先頭に戻る</font>
</pre>
<p>
さらに、補完候補がポップアップ表示される際の背景色などを好みで設定します。下記の設定に加えて、Teratermの[ウィンドウの設定]で「256色モード(xterm形式)」にチェックが入っていて、かつサーバ側の環境変数<code>TERM</code>が<code>xterm-256color</code>に設定されていないと、とても日常の使用には耐えない悲惨なユーザインタフェースになってしまいます。
</p>
<pre style="overflow-x:auto; white-space:pre; word-wrap: normal;">
(set-face-attribute 'company-tooltip <font color="blue">nil</font> <font color="green">; ポップアップ全体</font>
<font color="brown">:foreground</font> <font color="green">"black"</font> <font color="brown">:background</font> <font color="green">"ivory1"</font>)
(set-face-attribute 'company-tooltip-common <font color="blue">nil</font> <font color="green">; 入力中の文字列と一致する部分</font>
<font color="brown">:foreground</font> <font color="green">"black"</font> <font color="brown">:background</font> <font color="green">"ivory1"</font>)
(set-face-attribute 'company-tooltip-selection <font color="blue">nil</font> <font color="green">; 選択項目の全体</font>
<font color="brown">:foreground</font> <font color="green">"ivory1"</font> <font color="brown">:background</font> <font color="green">"DodgerBlue4"</font>)
(set-face-attribute 'company-tooltip-common-selection <font color="blue">nil</font> <font color="green">; 選択項目のうち入力中の文字列と一致する部分</font>
<font color="brown">:foreground</font> <font color="green">"ivory1"</font> <font color="brown">:background</font> <font color="green">"DodgerBlue4"</font>)
(set-face-attribute 'company-preview-common <font color="blue">nil</font> <font color="green">; 候補が1つしかなくて自動で入力される場合</font>
<font color="brown">:background</font> <font color="green">"black"</font> <font color="brown">:foreground</font> <font color="green">"yellow"</font> <font color="brown">:underline</font> <font color="blue">t</font>)
(set-face-attribute 'company-scrollbar-fg <font color="blue">nil</font> <font color="green">; ポップアップのスクロールバー</font>
<font color="brown">:background</font> <font color="green">"Midnight Blue"</font>)
(set-face-attribute 'company-scrollbar-bg <font color="blue">nil</font> <font color="green">; ポップアップのスクロールバー</font>
<font color="brown">:background</font> <font color="green">"ivory1"</font>)
</pre>
<p>
これで、最初の例のように、いい感じに補完候補が表示されるようになりました。
</p>
<p>
ちなみに、上記の色の設定例で「候補が1つしかなくて自動で入力される場合」とあるのは、下記のように候補が決定的になった状況のことです。
</p>
<p>
<div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDAF_5px54z6idqX9qQZiSy8noJJPuXRLvTAnCnR0kLBKKt57gaRunoKmYMHvBie-PzpQ2tE7oFJ2t9BRvlwnOKojtuh42N12EKpwm8HcFwm5c1coDeNDzogd47B4g36Jufg-4/s1600/import.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDAF_5px54z6idqX9qQZiSy8noJJPuXRLvTAnCnR0kLBKKt57gaRunoKmYMHvBie-PzpQ2tE7oFJ2t9BRvlwnOKojtuh42N12EKpwm8HcFwm5c1coDeNDzogd47B4g36Jufg-4/s480/import.png" /></a></div>
</p>
<p>
項目を選択した状態で[F1]を押すと、その項目のヘルプも見られます。
</p>
<p>
<div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgefbzO6DQqhekxWuWXi0-CYQWVxWW-Lq_nRh3eOQJCQ3dxecWRvkPJzlrCDclQp-rtjocrAt1yOyqm0_ACAB0zZYMO7yic6zVg1XGvS3epSzCy6q19x98NFjRbj4GDrg-Xsaww/s1600/intercalate.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgefbzO6DQqhekxWuWXi0-CYQWVxWW-Lq_nRh3eOQJCQ3dxecWRvkPJzlrCDclQp-rtjocrAt1yOyqm0_ACAB0zZYMO7yic6zVg1XGvS3epSzCy6q19x98NFjRbj4GDrg-Xsaww/s480/intercalate.png" /></a></div>
</p>
<p>
関係ないけど、TeXも捗る。
</p>
<p>
<div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg-9VP_9-3jeM1BW9pxpWEAnImoYudWDdSW5wK6Som8C-HVqVFDusJrQHkIOf9YLOCixMODKVTTRR5v10xkASuHIR1ljLnVcNbmA07jO7Sjau_SuuYZel3yXSN8PP-eV2BMj6b/s1600/expandafter.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg-9VP_9-3jeM1BW9pxpWEAnImoYudWDdSW5wK6Som8C-HVqVFDusJrQHkIOf9YLOCixMODKVTTRR5v10xkASuHIR1ljLnVcNbmA07jO7Sjau_SuuYZel3yXSN8PP-eV2BMj6b/s480/expandafter.png" /></a></div>
</p>k16http://www.blogger.com/profile/02349067627444091120[email protected]0tag:blogger.com,1999:blog-9197115.post-85398274882455071982016-02-09T19:28:00.000+09:002016-02-09T19:43:17.285+09:00LaTeXで連番リストに丸数字(\ajMaru)を使えたはずだけどhyperrefで困る話<h2>LaTeXで丸数字の連番リスト環境の基本</h2>
<p>
そもそもLaTeXで丸数字を使いたいときは、<a href="http://psitau.kitunebi.com/otf.html">otfパッケージ</a>の<code>ajmacros.sty</cpde>の機能を使うのが一番お手軽です。
このスタイルでは、数値を指定してさまざまな囲み数字のグリフ(あれば)を呼び出すという便利な機能が提供されています。
たとえば、ふつうの丸数字であれば、<code>\ajMaru{数値}</code>として出力できます。
</p>
<pre>
\ajMaru{1}、\ajMaru{100}、\ajMaru{101}
</pre>
<div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWvbCmFi7i8xPd6DbLXOqYzqpLbml2P-ihmy7P_u-sa-WXbAXXAFeBnjNeLvIwJhGwyli3d-MBOgtHp1C7V58gesmVJ-dxV8P0ZBXLoTbhDrFyaYJBlBa0NA_JE5f4bItSbzzf/s1600/ajmaru.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWvbCmFi7i8xPd6DbLXOqYzqpLbml2P-ihmy7P_u-sa-WXbAXXAFeBnjNeLvIwJhGwyli3d-MBOgtHp1C7V58gesmVJ-dxV8P0ZBXLoTbhDrFyaYJBlBa0NA_JE5f4bItSbzzf/s320/ajmaru.png" /></a></div>
<p>
一方、enumerate環境でラベルのスタイルを変えたいときは、<code>\theenumi</code>とか<code>\theenumii</code>といったコマンドを再定義します。
<code>\theenumi</code>と<code>\theenumii</code>は、それぞれ「enumi」や「enumii」という名前のカウンタに対応した「アラビア数字」に展開されるコマンドです。
その結果がenumerate環境でラベルを表示するのに使われているので、これらのコマンドの挙動を変えることで別の種類の数字を出力できるというわけです。
たとえばこんなふうにすれば、ラベルが大文字のローマ数字であるような連番環境が作れます。
</p>
<pre>
<font color="blue">\renewcommand</font>{<font color="purple">\theenumi</font>}{<font color="blue">\Roman</font>{enumi}}
<font color="blue">\begin</font>{enumerate}
<font color="blue">\item</font> 最初<font color="blue">\label</font>{A}
<font color="blue">\item</font> 次<font color="blue">\label</font>{B}
<font color="blue">\end</font>{enumerate}
最初は<font color="blue">\ref</font>{A}、次は<font color="blue">\ref</font>{B}。
</pre>
<div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-50WgxzAQeWfto7sxI7GUNN7jxU6tb4ZjlVCYFCNwLHCc35mdx7yC-FpitKJ2fazzybmIu0VQJ8RALDoAlzER83k3FeUo2CE8PxxreH2PkN_Ec3kIxVJKIURXsTbA6HEGbpPZ/s1600/roman.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-50WgxzAQeWfto7sxI7GUNN7jxU6tb4ZjlVCYFCNwLHCc35mdx7yC-FpitKJ2fazzybmIu0VQJ8RALDoAlzER83k3FeUo2CE8PxxreH2PkN_Ec3kIxVJKIURXsTbA6HEGbpPZ/s320/roman.png" /></a></div>
<p>
以上の知見を組み合わせれば、こんなふうにして丸数字の連番環境が作れそうです。
</p>
<pre>
<font color="blue">\renewcommand</font>{<font color="purple">\theenumi</font>}{\ajMaru{enumi}}
</pre>
<p>
しかしこれはうまくいきません。<code>\ajMaru</code>の引数は数値でなければならず、<code>enumi</code>はあくまでもカウンタの名前だからです。
</p>
<p>
ではどうすればいいかというと、<code>ajmacros.sty</cpde>に用意されている<code>\ajLabel</code>というコマンドを使います。
このコマンドは、後続の<code>\ajMaru{enumi}</code>の中身を実際のカウンタ値として取り出してくれるように定義されています。
</p>
<pre>
<font color="blue">\renewcommand</font>{<font color="purple">\theenumi</font>}{\ajLabel\ajMaru{enumi}}
<font color="blue">\begin</font>{enumerate}
<font color="blue">\item</font> 最初<font color="blue">\label</font>{A}
<font color="blue">\item</font> 次<font color="blue">\label</font>{B}
<font color="blue">\end</font>{enumerate}
最初は<font color="blue">\ref</font>{A}、次は<font color="blue">\ref</font>{B}。
</pre>
<div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGwhZnI8EUuKMOkpaQcC0Esyndor8E4P5mUi0xzo6DHewaUVsImYkUL1Xy0Vl45Is43XlIRIDE6vk5Is1gQ1Jo51cRVD0YrgNsEJiT3PTqYHhYN6q9QjnKYFrbru4jGeez2eWR/s1600/ajmaruenum.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGwhZnI8EUuKMOkpaQcC0Esyndor8E4P5mUi0xzo6DHewaUVsImYkUL1Xy0Vl45Is43XlIRIDE6vk5Is1gQ1Jo51cRVD0YrgNsEJiT3PTqYHhYN6q9QjnKYFrbru4jGeez2eWR/s320/ajmaruenum.png" /></a></div>
<h2>hyperrefと一緒に使えなくなっているっぽい(2016年2月現在)</h2>
<p>
本当ならこれで話は終わりのはずなんですが、相互参照をクリッカブルにしてくれる<a href="https://www.ctan.org/tex-archive/macros/latex/contrib/hyperref/">hyperrefパッケージ</a>を同時に使うと話がややこしくなります。
hyperrefは、相互参照をクリッカブルにするためにカウンタ関連の機能をいろいろ勝手にオーバーライドするという鬼仕様なのですが、
<code>ajmacros.sty</code>ではそれに振り回されないように、
hyperrefを読み込んだ場合には<code>\begin{document}</code>の時点で<code>\ajLabel</code>などをhyperref用にカスタマイズし直してくれます。
</p>
<p>
しかし、さらに厄介なことに、hyperrefはときどき内部の振る舞いをドラスティックに変更します。
そのため、せっかく再定義されている<code>\ajLabel</code>がまた使えなくなるという事態が2016年2月現在では発生しているようです。
具体的には、以下のような例で、上記のような事情を理解していないとちょっと追跡しにくいエラーが起きます。
</p>
<pre>
<font color="blue">\documentclass</font>[dvipdfmx]{jsarticle}
<font color="blue">\usepackage</font>{otf}
<font color="blue">\renewcommand</font>{<font color="purple">\theenumi</font>}{\ajLabel\ajMaru{enumi}}
<font color="blue">\usepackage</font>{hyperref} <font color="green">% hyperrefを使う</font>
<font color="blue">\begin</font>{document}
<font color="blue">\begin</font>{enumerate}
<font color="blue">\item</font> 最初<font color="blue">\label</font>{A}
<font color="blue">\item</font> 次<font color="blue">\label</font>{B}
<font color="blue">\end</font>{enumerate}
最初は<font color="blue">\ref</font>{A}、次は<font color="blue">\ref</font>{B}。
<font color="blue">\end</font>{document}
</pre>
<p>
実行例
</p>
<pre style="background-color:#333;color:#fff;">
...
! Undefined control sequence.
\ajLabel ...abel \@arabic \else \Hy@ReturnAfterFi
\hyperref@ajLabel #1\fi {
l.17 \item 最
初\label{A}
?
</pre>
<p>
エラーが起きている<code>\Hy@ReturnAfterFi</code>は、かつては<code>hyperref.sty</code>内で定義されて使われていたようですが、現在のhyperrefでは使われていないため、このような事態になってしまうようです。hyperrefパッケージのSVNのログを見ると、どうやら2011年4月に消えたようですね。
</p>
<blockquote style="background-color:white;">
[hyperref-svn] oberdiek: r1291 - trunk<br/>
<a href="http://mail.gnu.org.ua/mailman/listarchive/hyperref-svn/2011-04/msg00002.html">
http://mail.gnu.org.ua/mailman/listarchive/hyperref-svn/2011-04/msg00002.html
</a>
</blockquote>
<p>
上記のログを見る限り、<a href="https://www.ctan.org/pkg/ltxcmds">oberdiekバンドルのltxcmdsパッケージ</a>で定義されている<code>\ltx@ReturnAfterFi</code>を使うようにしたので、<code>\Hy@ReturnAfterFi</code>をディスコンにしたようです。
<code>\ajLabel</code>の再定義では、この<code>\Hy@ReturnAfterFi</code>を利用しているので、上記の例がうまく処理できない結果になっているようです。
</p>
<p>
そこで、<code>\Hy@ReturnAfterFi</code>を<code>\ltx@ReturnAfterFi</code>に変更するだけの以下のパッチを<a href="https://www.ctan.org/pkg/japanese-otf"><code>ajmacros.sty</code>(1.7b6)</a>に当てて試したところ、意図した挙動に戻りました。
(<code>\Hy@ReturnAfterFi</code>と<code>\ltx@ReturnAfterFi</code>の定義は同一なので当然といえば当然なのですが。。)
</p>
<pre style="overflow-x:auto; white-space:pre; word-wrap: normal;">
--- ajmacros.sty.org 2016-02-09 16:16:17.700785982 +0900
+++ ajmacros.sty 2016-02-09 16:15:57.548561902 +0900
@@ -685,7 +685,7 @@
% \def\check@UTF##1##2##3{\ifx\UTF##1\0x##2\else##3\fi}}{}}
\gdef\ajRedefine@ajCommands{\@ifpackageloaded{hyperref}{%
\let\hyperref@ajLabel\ajLabel
- \def\ajLabel##1##{\ifHy@pdfstring\Hy@ReturnAfterElseFi\hyperref@ajLabel\@arabic\else\Hy@ReturnAfterFi\hyperref@ajLabel##1\fi}%
+ \def\ajLabel##1##{\ifHy@pdfstring\Hy@ReturnAfterElseFi\hyperref@ajLabel\@arabic\else\ltx@ReturnAfterFi\hyperref@ajLabel##1\fi}%
\ajRedefine@ajCommand\"${Lig"$}\"&{Lig"&}\!*{Lig>.}\ajLig{Lig}\ajPICT{PICT}\"({PICT}\ajVar{Var}\@nil\@nil
\aj@Redefine@ajCommand!{{Maru}!|{KuroMaru}""{Kaku}"#{KuroKaku}!~{MaruKaku}"!{KuroMaruKaku}\@nil\@nil
\def\!J##1!K{\ifHy@pdfstring(##1)\else\expandafter\ifx\csname ajLig(##1)\endcsname\relax\@ajnumber{##1}{Kakko}%
</pre>
<div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBAtw0au5J7vvTfCa6nSUrkYQCYUGy97sV4B4gAgL1gsyEBTxKsSPQWJd2vXBlxzpi-qB1Vhi_2NsCFN9oNx-hj51SgunMmsUkaBluFVztQtOOaMZ0UxVg9JmnuWh6kvlG6KCv/s1600/ajmaruenumhyperref.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBAtw0au5J7vvTfCa6nSUrkYQCYUGy97sV4B4gAgL1gsyEBTxKsSPQWJd2vXBlxzpi-qB1Vhi_2NsCFN9oNx-hj51SgunMmsUkaBluFVztQtOOaMZ0UxVg9JmnuWh6kvlG6KCv/s320/ajmaruenumhyperref.png" /></a></div>
<p>
hyperrefは、電子書籍をLaTeXで制作するうえでは唯一無二のパッケージなのですが、ときどきこういう面倒が起きるのがつらい。。
</p>
<h2>まとめ</h2>
<p>
またhyperrefか。
</p>k16http://www.blogger.com/profile/02349067627444091120[email protected]0tag:blogger.com,1999:blog-9197115.post-62975915324416091342016-01-27T11:41:00.001+09:002016-01-27T11:41:10.935+09:00技術書編集者として「これはやられた!」2015年の本
<p>
技術書の年間ランキング的なものについて、編集者たちに「これはやられた!」と思う他社の本を候補として出させたら面白いのでは、という会話を小耳にはさみました。これはまたとないアマゾンアソシエイトの機会!ということで、勝手に自分の候補を上げてみます。
</p>
<p>
と思ったものの、新刊の技術書をそんなにたくさん読んでいないうえに、去年「これはやられた!」と思った本はいずれも技術書ではなく、どちらかというと数学書っぽい本ばかりでした。それでも、ジュンク堂池袋本店の「新春座談会 このコンピュータ書がすごい! 2015年版」で取り上げられた本ばかりだし、たぶん技術者が読む(べき)本としても妥当なはずです。</p>
<h2>『<a rel="nofollow" href="http://www.amazon.co.jp/gp/product/4791768515/ref=as_li_ss_tl?ie=UTF8&camp=247&creative=7399&creativeASIN=4791768515&linkCode=as2&tag=k16shikano-22">コンピュータは数学者になれるのか? -数学基礎論から証明とプログラムの理論へ-</a>』</h2>
<iframe src="http://rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=ss_til&asins=4791768515" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
<p>
いま自分の本棚を見返したら、この本の隣にたまたま『<a rel="nofollow" href="http://www.amazon.co.jp/gp/product/4409240927/ref=as_li_ss_tl?ie=UTF8&camp=247&creative=7399&creativeASIN=4409240927&linkCode=as2&tag=k16shikano-22">日本の著作権はなぜこんなに厳しいのか</a>』が並んでいて、一瞬だけ姉妹書に見えました。疑問形タイトル、文芸系とかビジネス系の出版社だと割と普通に見かけるけど、自分で本を企画するときには扱い方がわからず避けてしまうので、そういう書名を使いこなせる編集者になりたいです。というか、たぶん疑問形タイトルって、「これは既成の考え方をなぞった本ではなく、なおかつ人類は読むべきである」ことについて相当な自信がないと付けられない書名な気がします。
</p>
<p>
この本の場合、コンピュータと数学者のことを「算術計算に秀でたモノ」と考えている人にとっては、確かに「既成の考え方をなぞった本」ではないのでしょう。しかし、コンピュータとは自分が考えたプログラムが本当に動くことを確かめるためのものであるという人や、数学者はコーヒーから証明を生成する仕事であると気づいている人にとっては、どこかで見聞きして知っていたり知らなかったりする話にぐさっと明快な筋道を通してくれる本でした。一般向けの数学の読み物で見かける話も含まれてますが、call/ccは背理法ありの古典論理で純粋関数型言語は直感主義論理に対応しているんだという第5章のクライマックスに至る話を素で楽しめるのは、実際にプログラムを書いている技術者の特権だろうと思います。
</p>
<p>
出版社は青土社です。選択公理の読み物として一部で有名な‟<em><a rel="nofollow" href="http://www.amazon.co.jp/gp/product/1568813279/ref=as_li_ss_tl?ie=UTF8&camp=247&creative=7399&creativeASIN=1568813279&linkCode=as2&tag=k16shikano-22">The Pea and the Sun: A Mathematical Paradox</a></em>”(Leonard M. Wapner)の翻訳である『<a rel="nofollow" href="http://www.amazon.co.jp/gp/product/479176515X/ref=as_li_ss_tl?ie=UTF8&camp=247&creative=7399&creativeASIN=479176515X&linkCode=as2&tag=k16shikano-22">バナッハ=タルスキの逆説 豆と太陽は同じ大きさ?</a>』をはじめ(原書しか読んでないので翻訳の出来は知らない)、意外に「え?」っていう理学系の本も出してくるし、割と好きです。「現代思想」とか「ユリイカ」でも思想的な文脈で現代数学の記事をたまに掲載しているし、そのうち計算機科学や機械学習の特集もあるに違ない。
</p>
<h2>『<a rel="nofollow" href="http://www.amazon.co.jp/gp/product/4535787204/ref=as_li_ss_tl?ie=UTF8&camp=247&creative=7399&creativeASIN=4535787204&linkCode=as2&tag=k16shikano-22">圏論の歩き方</a>』</h2>
<iframe src="http://rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=ss_til&asins=4535787204" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
<p>
Haskellを使うのに圏論はいらないって言うけど、みんな圏論圏論って言ってるので、どうしたって圏論が気になりますよね。そんな人間を狙いうちする本が日本評論社から発売されました。タイトルどおり、圏論の名所をめぐるツアーガイドのような本です。いつか自分の足で行ってみたいけど余裕がなくて行けない場所へ行った気になれる本です。去年の夏に読んで、いまこうやって記事を書くつもりで内容を要約しようとしても、さっぱり具体的な言葉にできないんですが、そのへんもツアーガイドに似ています(実際、「地球の歩き方」なんかにしても、行く場所を決めるときに読んだ内容をあらためて説明しろと言われても言葉に詰まりそう)。
</p>
<p>
正直、この本のうち計算機に関する部分については、まさに自分でこんな本を作りたかったという気にさせてくれる本でした。この本が企画として面白いと思うのは、コンピュータ書でいえばフレームワークに対する「クックブック」のような本を、数学の一分野で形にしてしまった点です。数学書、コンピュータ書でいえば「コードの動作について説明しただけ」だったり「コード読めばわかるよね」だったり、そんな立ち位置の教科書が少なくない気がします。コンピュータ書の場合には、実行例を見せることで「どんな場面でどんなコードが必要なのか」を説明できたりしますが、それを数学書でやったのがこの本なのかなあと思いました。いわば「圏論の実行例」。あるいは「圏論のクックブック」。もし何らかの事情で圏論について本当に「わかる」必要があるなら、体系的に書かれた教科書を読みながら紙と鉛筆で勉強するのが近道なんですが、そうやって教科書の証明を読み進めるときの「実行例」だけが本として、しかも圏論みたいな分野で出たということで、自分のなかでは「これはやられた!」一冊でした。
</p>
<h2>『<a rel="nofollow" href="http://www.amazon.co.jp/gp/product/B015R0GNXK/ref=as_li_ss_tl?ie=UTF8&camp=247&creative=7399&creativeASIN=B015R0GNXK&linkCode=as2&tag=k16shikano-22">あなたの知らない超絶技巧プログラミングの世界</a>』</h2>
<iframe src="http://rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=k16shikano-22&o=9&p=8&l=as4&m=amazon&f=ifr&ref=ss_til&asins=B015R0GNXK" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
<p>
自分が過去に企画にできなかった本が企画化され、しかも想像以上に出来がいいのだから、「これはやられた!」一冊として選ばざるをえない。発売当時、くやしさをばねに<a href="http://note.golden-lucky.net/2015/09/blog-post_24.html">紹介記事を書いた</a>ので、そちらを読んでください。
</p>
k16http://www.blogger.com/profile/02349067627444091120[email protected]0