2018/07/07

技術書をクラウドファンディングで出版してみた

あきみちさんから、「IPv6本を出すということで、クラウドファンディングで協賛を呼びかけよう」(原文ママ)というアイデアを聞いたのは、TwitterのDMのやり取りを読み返すと2016年11月23日のことだったらしい。 DMには時刻が表示されないので正確な時間はわからないけど、その後のやり取りがいつの間にか11月24日になっているので、たぶんそういう時間帯だ。

それに対するぼくの最初の返答は、「それは既存の出版社だと面倒そうだ」(原文ママ)だ。 言外に「うち(ラムダノート)ならできるよ」が含意されていることは、起業前からいろいろ相談にのってくれていたあきみちさんには間違いなく伝わる。 とはいえ、そのころはまだ『プロフェッショナルSSL/TLS』も制作中だったし、直販ストアもなかったし、ラムダノートは胸を張って「出版社」と言える状態ではなかった。

そもそも、あきみちさんやぼくは技術自体というより技術解説でご飯を食べている人間であり、必要としている人がいる内容だからといって、採算度外視では動けない。 当時はまだクラウドファンディングで技術書を作るという先行事例もなく、どれくらい集めればいいのか、どれくらい集まればいいのか、どういうふうに具体化すればいいのか、まったく見当もつかなかった。 にもかかわらずぼくは、あきみちさんにいくつか質問したあとで、「だれにでも通用するやり方じゃないですが、あきみちさんでIPv6の本なら確度高い。」(原文ママ)と応じていた。 はっきりいって軽率である。 まあでも、考えていてもわからないことは、やってみるしかないので、当時のぼくはやってみることにしたのだろう。

それから急いで企画書っぽいものを作り、直接支援をお願いできそうな会社にあきみちさんから打診し、ぼくのほうでもMakuakeに問い合わせを入れた完成品をCC BY-NC-SAで公開することをふくめて、翌月にはだいたいプロジェクトの形が決まった。 当時の企画書の1枚めはこんな感じ。

このときの企画書をいま見返すと、本の構成も、収益化のモデルも、基本的なコンセプトはこの時点からほとんどずれていない。 本の構成については実際に本を読んでもらうとして、ここでは収益化のモデルという視点で現時点で個人的に感じていることをメモしておこうと思う。

「こういう本が最小限の負担で読める世界」に出資してもらう

『プロフェッショナルIPv6』の商売モデルは、たぶんこんな感じになっている。

つまり、この本の著者と出版社には、本という商品だけでなく、「こういう本が最小限の負担で読める世界」を実現することへの対価として出資してもらえたし、応援してもらえた(本当にありがとうございます)。 そうした出資を広く集めるうえでクラウドファンディングという方法は相性がよかったし、任意の金額を著者に直接渡せるという電子版の提供方法を手軽に導入できたのは大きかった(BOOTH、まじ便利)。

一方、多くの本の企画は、基本的にはこんな商売モデルでやっている。

この方法だと、動物の絵がカバーにあるわけでも全国の書店にフリー入帳で配本できるわけでもない新興の出版社から発行される「IPv6の解説書」は、完全に「知る人ぞ知る」ものになっていただろう。 あきみちさんとぼくの実情からすると、最悪、陽の目をみなかった可能性もある。 こうやって多くの人に届けることはできなかったかもしれないし、著者に利益を還元できなかったかもしれないし、うちも資金繰りに困っていたかもしれない。

教訓と抱負

『プロフェッショナルIPv6』は、たぶん、「こういう本が最小限の負担で読める世界が欲しい」という人を巻き込めた。つまり、「読ませたい人」の支援で成立した。 そして、この事実からは、技術書の出版に従事している自分たちにとっての教訓めいたものが導き出せる気がしている。

実のところ、技術書の多くは、これまでだって「読ませたい人」からリソースを分けてもらうことで「商売」をしている。 その最たる相手は、印税収入を期待せずに採算度外視で執筆してくれる著者。 それから、謝辞と献本程度の対価で内容のレビューをしてくれる有識者や、やはり献本程度の対価で宣伝をしてくれるインフルエンサー。 みんな、「読ませたい人」として、自分が持っているリソースを本という商品に投下してくれている。 出版社は、そうした人たちの善意に頼ることで、対価を払ってまで読みたいことを自覚している人の総数だけでは成立しないかもしれない本を作って売るという商売をかろうじて維持している。

ぼくら版元の編集者の人間は、そのことに意識的でなければならないと思う。 版元の編集者も「読ませたい人」ではあるだろうけど、その実現のために持ち出しで出資をしているわけではないので(むしろ多くの場合は十分な対価を得ている)、気を抜くとこの事実を忘れがちになるので本当に注意しなければならない。 ページあたり数百円とかで編集制作をやってくれる編集プロダクションが版元編集者のコストを肩代わりしている可能性にも意識的であるべき。閑話休題。

教訓は、なにも警鐘を鳴らす方向だけではない。 『プロフェッショナルIPv6』では、「こういう本が最小限の負担で読める世界が欲しい」という人から直接出資をしてもらったことで、商売として出版できるチャンスが広がった。 あきみちさんという著者が十数年かけてインターネット上で築き上げた人徳があってはじめて実現するクラウドファンディングではあったけれど、とにもかくにもこういう形で出版ができたということは、「読みたいことを自覚していてお金を出してくれる人」の絶対数が多くないことが多い技術書みたいなジャンルの出版にとっては、わりと未来がある話なんじゃないだろうか、とも思う。

そんなわけで、『プロフェッショナルIPv6』をひとまず公開にまでこぎつけた現時点で個人的に感慨深いのは、クラウドファンディングという手段の面よりも、「こういう本が最小限の負担で読める世界」に出資したいと感じる人にうまく届けられたかな、という点にあったりする。 締め切りに追われるのが精神的につらいのもあって、正直なところ、これからクラウドファンディングで本をばんばん企画していく予定はない。 でも、「こういう本が最小限の負担で読める世界が欲しい」、もうちょっと厳密に言うと、「こういう技術情報がある世界が欲しい」という人や組織に出資してもらえるような企画、あるいは仕掛けを考えて、そのうえでコンテンツの制作をこれからもがんばっていければ嬉しいなという気持ちでいる。

宣伝

というわけで、ラムダノートの本をよろしくお願いします。

https://www.lambdanote.com/

プロフェッショナルIPv6

2018/04/30

コマンド定義の中で\catcodeを変える

LaTeXではシングルクォート記号がデフォルトで「」になる。Unicodeでいえば、RIGHT SINGLE QUOTATION MARK(U+2019)。この挙動は、本文ならよいのだけど、等幅フォントにするような場面では都合が悪い。等幅フォントのときにみんなが期待するシングルクォートは「'」である。

みんなが期待する挙動なので、当然、そのためのパッケージがすでにある。upquoteパッケージである。しかし、このupquoteパッケージは、\verbコマンドおよびverbatim環境向けに作られている。fancyverb環境やalltt環境でも使えるが、\textttコマンド内の挙動には影響しない。つまり、upquoteパッケージを使っても、\texttt内のシングルクォート記号は「」になる。

\texttt{...}の中でシングルクォート記号を直立タイプ「'」にするにはどうするか。すぐに思いつくのは、「'」をアクティブ文字にして、OT1/cmttの\char13にするという方法。あるいは、textcompパッケージで提供されている\textquotesingleにするという方法。実際、upquoteパッケージの実装もそのようになっている。その方針をそのまま実装するとこうなる。

\let\orgtexttt\texttt
\def\texttt#1{%
  \catcode`'=\active
  \def'{\textquotesingle}
  \orgtexttt{#1}}

もちろん、これは動かない。この\defの中身はすでにTeXの入力ルーチンで読み込まれているので、\def'{\textquotesingle}の時点では「'」がアクティブ文字になっていない。そのため、ふつうの文字である「'」に対して\defすることになってしまうからだ。結果として、「コントロールシーケンスやアクティブ文字であるべき場所にふつうの文字がある」というエラーになる。

! Missing control sequence inserted.

                \inaccessible

こういう場合の常套手段として、「\lowercaseトリック」と呼ばれるものが知られている。このトリックのポイントは、\lowercaseというコマンドの引数が、「すべての文字を小文字として解釈してくれて、しかもカテゴリーコードに関しては無視してくれるような世界」になることにある。そういう世界で、「'」のことを、なにか「\defの1つめの引数に置いても怒られない都合がいいアクティブ文字」の小文字にしておく。幸い、TeXには、そのような都合がいい文字がある。「~」だ。\def~{...}であれば、\def\texttt#1{...}の定義部の中にいきなり書いても怒られない。そこで、「~'の小文字」ということにしておいて、\def~{...}と書けば、この\defにより実際には「'」に対する定義が書けることになる。

あるアルファベットに対する「小文字」を定義するためのプリミティブは\lccodeだ。これを使い、「'」のことを「~の小文字である」ということにして、その文脈で\lowercase{...}内で\def~{\textquotesingle}すればよい。

\def\texttt#1{%
  \catcode`'=\active
  \begingroup
    \lccode`~=`' %
    \lowercase{\endgroup
      \def~}{\textquotesingle}
  \orgtexttt{#1}}

\lccode`~=`'のスコープを定めている\begingroup\endgroupの組に対し、\lowercase{...}のカッコがきちんと入れ子になっていない。あまつさえ\def~{\textquotesingle}にも「}」がまたがってしまっている。気持ち悪いかもしれないけど、これで問題はない。少なくとも、\def~\begingroup\endgroupの中に入れてしまうと、この\defがローカルになってしまうので、「'」がアクティブになるだけなって定義がないままとなりエラーになってしまう。

! Use of ' doesn't match its definition.

まあ、\gdefにすればいいだけだけど。

\def\texttt#1{%
  \catcode`'=\active
  \begingroup
    \lccode`~=`' %
    \lowercase{%
      \gdef~}{\textquotesingle}\endgroup
  \orgtexttt{#1}}

(ところで、\endgroup\lowercase{の直後で問題ないことの根拠は、正直なところよく理解していない。\lowercaseが大文字小文字の対応表をメモリに展開するのが引数を読む前、だからなんだろうなあ。)

さて、\lowercaseトリックのおかげで「'」がアクティブ化される前に「\def'」と書くことを回避できたので、こでれエラーにならずに動く。しかし、挙動は依然としておかしい。ブロック要素で最初に登場する\textttの中では「'」の定義が効いておらず、その後ろに出てくる「'」が、\textttの中だろうが外だろうが\textquotesingleになってしまうのである。

*\texttt{\show'}
> the character '. % \textttの中だけど、文字
...
*\show'
> '=macro:
->\textquotesingle . % \textttの外だけど、アクティブになってる
...
*\texttt{\show'}
> '=macro:
->\textquotesingle . % 2つめの\textttの中ではアクティブに
...

最初に登場する\textttの中で「'」の定義が効かない原因は、すぐにわかった。\textttの引数はすでに読み込まれているから、「'」に対する\catcodeは効いてないのである。\defに対しては\lowercaseトリックのおかげでごまかせたが、この状態では\textttの引数に対して「'」が\textquotesingleとして扱われることはない。

この欠陥に対処するには、\textttの引数が読み込まれるのを遅らせればいい。そういう場合の常套手段は、マクロの展開を二段階にしてサブのほうで引数を読み込ませる、というもの。つまりこんなふうにする。

\let\orgtexttt\texttt
\def\texttt{%
  \begingroup
    \catcode`'=\active
    \x@texttt}
\def\x@texttt#1{%
  \begingroup
    \lccode`~=`' %
    \lowercase{\endgroup
      \def~}{\textquotesingle}
  \orgtexttt{#1}
  \endgroup}

これで、目的のマクロそのものは完成した。

これにて本件は落着といたす、でもいいんだけど、1つ前の定義が「最初に登場する\textttより後ろで、\textttの中だろうが外だろうがシングルクォートが\textquotesingleになってしまう」という挙動だったのが謎い。まったく\textquotesingleにならない、というなら納得できるんだけど、なぜ\textttの引数内で閉じているはずの\catcode`'=\activeが外に漏れてしまっているのか。

どう考えても、オリジナルの\textttの定義に何かある。 しょうがないのでlatex.ltxを覗くと、\textttの定義は事実上こうなっていた。

\DeclareRobustCommand\texttt[1]{%
    \ifmmode
      \nfss@text{\ttfamily #1}%
    \else
      \hmode@bgroup
       \text@command{#1}%
       \ttfamily\check@icl #1\check@icr
       \expandafter
      \egroup
    \fi}

なんなんだよ、この下から3行めの\expandafter。。これのおかげで、\texttt(を再定義したものの中にある\orgtexttt)の引数が読まれるとき、もりもり後ろのほうまで読まれてしまって、\catcode`'=\activeがしばらく先まで有効になってしまっていたっぽい。

この\expandafterは、\textttに限らず、NFSSが提供するフォント変更コマンドすべてに登場する(ようなマクロになっている)。これ、なんのために必要なの?

なにも謎くなかった。先の動作しない\textttの定義で\catcode`'=\activeは閉じてない。ZRさんありがとうございます。

2018/03/05

技術書のレビューの経験則

出版される前の本の内容は、通常は著者や編集者に代表される「制作サイド」の人間にしか読まれない。 専門性の高い本であれば査読とか監修といったプロセスを有識者にお願いすることはあるけど、そうしたお願いをするときには有償だったりカバーや袖に名前を出したりすることが多いので、これも「制作サイド」の一部とみなしていいだろう。

一方、基本的に無償で、完成した書籍の献本と謝辞への掲載くらいを前提に、あくまでもベストエフォートで発行前の本の内容を見てくださいというお願いを第三者にすることもある。 この場合の第三者というのは、制作中の書籍の想定読者だったり、出版後の書籍を対象読者へ紹介してくれそうな立場の人だったりする。 このようなプロセスを制作に取り入れる習慣は、とくにここ数年のIT系の出版社ではめずらしくなくて、界隈では「レビュー」などと呼ばれている。

というわけで、技術書の制作における「レビュー」について、自分の経験をもとに知見を整理しておきたい。 自分の経験をもとにはしているけど、たぶん日本で技術書のレビューをまわしてきた経験数では上位にいるはずなので、独りよがりではあるかもだけど意味がなくはないはず。

余談だけど、たぶんこういう出版前の状態を有志にボランティアでレビューしてもらうという文化を技術書界隈で積極的に始めたのはアスキーなんじゃないかなと思う。 少なくともぼくが最初にこういうプロセスの存在を知ったのは、アスキーの256本とかで執筆兼レビューのためにメーリングリストを使っているのを見たときだった。 彼らがどこまで意識的にこれをプロセス化していたのかは知らないけれど、この記事は、彼らがやっていたプロセスをぼくの前職のチームの先輩だった森田さんが取り込み、いろいろな著者、訳者に協力してもらいながら発達させてきた手法がベースになっている。

技術書のレビューのパターン

まず、レビューと一口にいっても王道のプロセスがあるわけではなくて、依頼方法およびレビュアーどうしのインタラクションの有無によっていくつかの形に分類できる。

レビュー内容は制作サイドだけが見たいレビュー内容が他のレビュアーにも見えてよい
制作サイドで知己がある人に依頼
制作サイドで知己がない人に依頼
不特定多数

上記の表のいずれのパターンに該当するかによって、レビューの具体的な手法やツールがだいたい決まる。

技術書のレビューの手法

とはいえ、実際にはレビューの具体的な手法やツールがまずあり、その結果として上記の表のいずれかに当てはまるという状況が多いだろう。 いずれにしても、誰にどういう方法でレビューをしてもらうかは、レビューに使うツールやプロセスに依存する。 そこで、次はツールという観点から上記の表の各セルとの適正について整理してみよう。

バグトラッキングシステムを利用する方法

②と④の場合は、プライベートなバグトラッキングシステムを使うことが多い。自分がかかわるプロジェクトだと、一昔前はTracのチケット、いまではGitHubのissueとしてフィードバックをもらっている。 もちろん、TracやGitHubなどのシステム側で不特定多数の参加を許可するようにすれば、⑥の場合にも使える。

バグトラッキングシステムを使うメリットとしては、あるレビュアーが見つけた問題を制作サイドやレビュー陣営全体で共有しやすいことが挙げられる。原稿のバージョン管理をしている場合にはリポジトリに関連付けられたバグトラッキングシステムを使えるので、フィードバックへの対応履歴を管理しやすいというのも魅力。ひとことでいえば、レビュアーとレビューを受ける側のトータルでの負担が最小化される方法だといえる。

レビュアーどうしでチケットやissueで議論ができるので、著者や編集者だけ、つまり制作サイドだけでは思いつかないような解決策が出たり、特定のレビュアーの偏った意見なのかそうでないのかを客観的に判断する材料ができたりするというメリットもある。

デメリットは、レビュアーが見つけた問題をチケットやissueにするときに、指摘したい場所を一意に伝えにくいこと。ほとんどの場合、レビュアーが見る対象というのは、原稿ソースに技術的にアクセスができる場合でも、組版されたPDFである。そのため、一般には「mページのk行め」のような指示方法になるしかないのだけれど、これには次の難点がある。

  • レビューを受け取る側ではPDFでなく原稿ソースのほうを見ているので、「mページのk行め」という情報は使わず、指摘内容からキーワードをgrepして該当箇所を探している。つまり、「mページのk行め」まで粒度が細かい情報は無駄になってしまうことが多い。原稿ソースが頻繁に更新される環境だと、レビュー対象のPDFと制作進行中のPDFとで場所の乖離がさらに激しくなる
  • 「mページのk行め」のような指摘は、他のレビュアーにとっても優しくないので、指摘のダブりが意外と発生しやすい。ダブりを防ぐために修正ずみの問題をすぐにクローズしないといった運用をしても、なおダブる。そもそも修正ずみの問題をクローズできないのでは、バグトラッキングシステムを使う利点が半減してしまう

場所の指示がめんどうであることに加えて、バグトラッキングシステムを利用することには、レビュアーが他のレビュアーの意見を読めてしまうことによるデメリットもある。

  • うまく回ればレビュアーどうしの議論によって問題の文脈がはっきりするのだが、ときには議論の発散という形でデメリットになる場合もある
  • 声が大きい有名人がレビュアーにいることで他のレビュアーが委縮してしまい指摘しづらい雰囲気ができたり、そのようなレビュアーの意見に流される可能性がある

まとめると、バグトラッキングシステムを使った技術書のレビューには、手軽に問題を管理できる一方で、指摘箇所を一意に特定するのが困難であり、他のレビュアーとのインタラクションが不可避であるというデメリットがある。 そのため、冒頭の表における②のような著者や編集者が議論をコントロールしやすいレビュアーの集合である場合に向いた手法だといえる。 ④の場合には、レビューの要件を具体的に明文化しておく必要があるだろう(もちろん②のケースでも明文化したほうがいいんだろうけど)。 一方、レビュアーが他のレビュアーの意見によってバイアスを受けるのを避けたい場合(①、③、⑤)、自転車小屋の屋根の色をめぐる議論に巻き込まれたくないという場合(⑥)には、使えない。

問題点を個別に直接送ってもらう方法

複数のレビュアーがバグトラッキングシステムで相互に意見を交わしながら技術書のクオリティを上げていく作業は、うまく回ると本当に楽しい。それ自体がエンターテインメントだったと感じることも少なくない。 しかし、そういう場が醸成されるまでには時間がかかるし、そもそも成功するとは限らない。オープンソースプロジェクトに慣れている著者かどうかという文化的な違いによる困難もある。 前述したように、レビュアーが他のレビュアーの意見によってバイアスを受けることを避けたい場合もある。

そこで、著者 and/or 編集者が個別にレビューを依頼し、一対一でフィードバックを返してもらうというケースもかなり多い。 その場合には、メールで指摘をもらったり、PDFのコメント機能を使ってもらったり、最近だとDropboxのコメント機能を使うこともある(Google Driveにも同様の機能はあるので使えるかもしれない)。

この方法は、フィードバックをもらうという一点に特化すればもっとも優れている。 Acrobatのレビュー機能やDropboxのコメント機能を使えば、バグトラッキングシステムでは不可避だった指摘箇所を一意に特定する難しさがある程度は解消できるという利点もある。

難しいのは、なんといっても人選。 バグトラッキングシステムを利用すれば十数人規模になってもハンドリング可能だけど、個別にやり取りをする負荷を考えると、数人に抑えたいところ。となると、ピンポイントで適切な人に依頼するのが現実的だといえるだろう。 そういうわけで、冒頭の表における①や③に向いた方法だといえる。 ⑤でも使えなくはないけれど、というか⑤をやりたいときはこの方法しかないんだけど、制作サイドが個別のやり取りの負荷を覚悟する必要がある。

クラウド上で共有したPDFにコメントを付けてもらう方法

DropboxにPDFを置くと、閲覧できる人が誰でも文字列をハイライトしてコメントをつけられるようになる。 この機能は、個別に指摘をもらう場合だけでなく、複数のレビュアーから同時に指摘を受ける場合にも使える。 Dropboxによる方法のメリットは、実施前の手間が最小であること。なにしろ、Dropboxに置いてリンクを伝えるだけでいい。 モダンブラウザがあれば説明不要で直観的に指摘箇所を一意に特定できるのもお手軽さにつながる。

デメリットは、DropboxのPDFビューアーはPDFの仕様に準拠していない独自の拡張で、次のような不自由があること。

  • 書籍全体の検索ができない場合がある。検索対象になるのはブラウザが描画ツリーを構築した部分だけ
  • コメントのステータスが未解決と解決済みの2つしかないので、複数のレビュアーからの指摘がダブらないようにするにはすべて未解決にしておくしかない。そのため、レビューを締め切るまで取り込み作業がしにくい
  • 個々のコメントにURLが付かないので、議論が始まったコメントや見逃したコメントを通知をたどって追いかけるしかない
  • PDFデータにはコメントが埋め込まれないので、ダウンロードしてPDFリーダーでコメントを管理することも、PDFデータからコメントを抜き出すこともできない

このような制約があるので、DropboxでPDFにコメントをもらう方法をうまくまわすには、PDFのページ範囲を小さく章単位などに絞ったり、レビューの締め切りまではコメントを解決済みステータスにしないようにしたり、少し工夫がいる。 それでも、指摘箇所を一意に特定しやすいというメリットは大きいので、Slackなどの他メディアでレビュアーと制作サイドが気軽に議論ができる②のような状況であれば、かなり魅力的だと思う。

もうひとつ、Dropboxに代表される共有PDFへのコメント書き込みには、指摘がミクロに偏りがちになってしまうという見過ごせない欠点がある。 この欠点を補うにも、レビュアーと制作サイドとが雑談できる場の用意が重要な気がしている。

なお、この方法で技術書のレビューが可能なのはDropboxだけではない。 Google Docsにも指摘が行単位になるけど同様の機能はあるし、Adobe Readerにも共有レビューという機能がある。 PDFの仕様にそったアノテーション機能であるAdobe Readerの共有レビューが使えるのがベストなんだけど、Adobe ReaderがLinuxベースの環境で事実上使えなかったり、macOSでもインストールしてない人がいたりするから、つらい。

技術書のレビューをする側の心得

ここまでは、技術書のレビューを受ける側に向けた話だった。 ここでは、レビューをするときにどんなことを意識したらいいかについてざっくり書いてみる。 ただし、ぼく自身はレビューを受ける側の立場に立つことが多いので、主にレビューを受ける側の視点が多分に混ざります。

レビューでがんばって探しちゃだめな問題

レビューで何を見るべきかを要約するのは難しいけど、がんばって見てはいけない問題というのはある。 建前としては「気づいたことを何でも指摘してほしい」なんだけど、何に気付くかは「何に気付こうと思って読んでいるか」に多分に影響されるので、「この点については意識的に探す必要がない」を意識するのはけっこう重要。

  • 誤字脱字など、日本語上のミス
  • 漢字や送り仮名などの表記ゆれ
  • レイアウトの不備

これらは、「気づいたなら指摘しておく」という態度で読めば十分で、レビューというプロセスでがんばって探すべき問題ではない。 逆に言うと、制作サイドの心得として、これらの問題をなるべくつぶした状態でレビューを開始すべきともいえる。

なんだけど、時間的な制約もあるので、現実にはそうでない原稿をレビューすることになる機会もある。 そういう問題が多く残っている状態でレビューをすることになった場合には、上記のような問題を一生懸命に探してあげるのではなく、「この章は誤字脱字が目立つけどあとで修正されるのですよね?」といった大局的なコメントを残すのがよい。 技術書のレビューの主眼は、あくまでも第三者の目を取り入れることであり、校正作業のボランティアではないのだから。

レイアウトについても同様で、完成途中のPDFを見るとどうしてもアラが目立つけど、それはやはりレビュアーが気を配る部分ではない。 「レイアウトの不備で有意義なレビューが困難である」といった指摘に留めよう。

ミクロな指摘より、マクロな指摘を

誤字やレイアウトの不備にも関係するけれど、第三者であるレビュアーがミクロに指摘したくなるような原稿の問題は、もっと広いスコープでの問題という場合が少なくない。 なんか日本語がわかりにくいなあと思って、語の位置を変えたり読点を追加したりしたミクロな修正案を出すのは、実は解決になっていないことが多い。 レビュアーがミクロな指摘で解消を試みた問題の根本的な原因は、より広いスコープで原稿の問題を解消できる人、つまり制作サイドでないと対処できないことが多い。

レビュアーとしては、なんか日本語がわかりにくいなあと感じる箇所があったら、「〇〇ということが言いたいんだと思うんだけど、なんか日本語がわかりにくいなあ」と指摘するのがベター。 〇〇すらわからないなら、「文意が不明」といったコメントでも十分。

自分にとって理想的な本にする機会ではない

技術書のレビューは、校正作業のボランティア募集にならないためにも、制作プロセスではかなり後の工程になる。 つまり、レビュアーとしては、本のコンセプトや表現方法、近日中の出版については了解しているということが前提になる。 したがって、内容に間違いがあると考えられるなら指摘すべきだけど、本の表現に対して調整を要求する場ではないという自覚は必要である。

文章に対するレビューというのは、センシティブなプロセスだ。指摘者以外にとってどちらでもいい話であることも少なくない。 どちらでもいい話に「どちらでもいい」というのは精神力がいるものなので、はじめから不採用前提くらいの気持ちだとみんなが楽になる。 たとえば、同じ内容ならこっちを説明すべきとか、説明の日本語表現はこっちのほうがいいとか、そういう指摘についての最終的な決定権は制作サイドにゆだねる。 制作サイドもまじえて議論になり、最終的な文章表現をなにか決定しないといけなくなったところで、代替案の作文をするくらいが双方の負担にならず、ちょうどいい。

逆に、著者や編集者には、無慈悲な独裁者となる覚悟が必要だといえる。 そういう意味ではオープンソースのコミッターと同じなのかも。 報われないかもしれない指摘であるという点について双方が納得していないと、レビューは回らない。

実践例

いままさに進行中の本の大規模レビューは、冒頭の表だと④、もしくは⑥に近いプロジェクトである。 そこで、指摘箇所を一意に特定する部分の困難さを回避しつつ、指摘の重複回避や原稿(他のプライベートリポジトリ)への取り込み状況の管理を可能するために、次のようなレビュー方法を採用した。

  • フィードバックはPDFのページ単位で受ける。そのために、各ページ用のGitHub issueをあらかじめ全ページぶん用意しておく
  • 指摘をするときの負荷を下げるために、PDFの各ページに、各ページ用GitHub issueへのリンクを埋め込んでおく。そこをクリックすれば、そのページに対するコメントを書き込めるページがブラウザで開くしくみ
さらに、上で紹介した経験則を踏まえて、レビュアーには下記のようなお願いをしている。

PDFを読んでページごとのissueに指摘を追記していってください。代案は不要です。なお、マンパワーの都合でissue上では無反応の可能性が高いです。ごめんなさい。

  • 具体的に指摘をいただきたいポイント
    • 内容の間違い
    • 解説がほしいトピック
    • 意味が取れない段落
  • 下記の指摘も歓迎です(grepをかけるので存在の指摘だけで十分です)
    • 技術用語の不統一
    • スペルミス、誤字、脱字
  • 下記については、指摘は不要です(最終までには自然に直ります)
    • 日本語表記(漢字や送り仮名)の不統一
    • レイアウトの不備
    • その他、局所的な日本語の問題

前半で述べたように、そもそも適切なレビューの手法は要求事項によって変わってくるので、これがベストな技術書のレビュー手法というわけではない。 最大で十数人くらい、著者が中心になってSNSなどで直接連絡がつく範囲に依頼するなら、いまのところDropboxへのコメントはかなり手軽に思える。 ピンポイントでお願いする人がいる場合も、DropboxへのコメントやPDFへのアノテーションがベストだろう。 一方、ある程度の議論が予測されたり、原稿のバージョン管理との親和性が優先されるなら、これからもGitHubのissueを使うと思う。

そしていずれにせよ、レビュアーに何を見てもらいたいか(見る必要がないのか)、レビューにあたって最終決定権は制作サイドの独断的な判断になることについては、何らかの形でレビュアーと制作サイドとで意識共有ができているべき。

2018/01/12

RubyでつくるRuby発売中

カート埋め込みのテスト。デフォルトだと書籍ページへのリンクにはならないのかな。カートに入れてしまったときに画面に常駐するカートボタンは、数をゼロにすると消えるようです。

2017/12/31

2018年賀状

年賀状書いた。

%!
<< /PageSize [285 420] >> setpagedevice

% excerpt from Bill Casselman's 
% "Mathematical Illustrations - a manual of geometry and PostScript"
/ctransform { load
    1 dict begin
    /f exch def
    [{[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 exec} forall
    end
} def

/f {/y exch def
    /x exch def
    x y fsub 5 y mul cos mul
    y x fsub 3 y mul cos mul
} def

/fsub { % u = sin (a √(30 - (b^2 / 10))) * 460 
    /b exch def
    /a exch def
    a 30 b dup mul 10 div sub sqrt mul sin 460 mul
} def

/setrandcolor { % def
    /r1 {rand 5 mod 3 div} def
    /r2 {rand 7 mod 6 div} def
    /r3 {rand 5 mod 6 div} def
    r1 r2 r3 setrgbcolor
} def

1 1 20 { % for

    /n exch def

    newpath
    /ShowcardGothic-Reg findfont 4 scalefont setfont
    -0.4 9 moveto (2018) true charpath
    -0.1 6 moveto (1820) true charpath
     0   3 moveto (2018) true charpath
    -0.1 0 moveto (1820) true charpath
    /f ctransform
    gsave

    clip
    newpath
    /j {
        /x exch def
        rand x mod x div 30 mul
    } def

    0 5 400 {
        /i exch def
        10 j setlinewidth
         setrandcolor
         0 i moveto
         300 i lineto
         stroke
     } for
 
     grestore
     currentlinewidth 2 mul setlinewidth
     0.1 0 0 setrgbcolor 
     stroke
 
     3 410 moveto
     /Georgia-Bold findfont 5 scalefont setfont
     0.3 0.2 0.2 setrgbcolor
     n =string cvs show
     (/20) show
 
     showpage
 } for
 

2018 by Keiichiro Shikano on Scribd

今年は球体を作ってみたいなと思って、はじめはエッシャーふうの非ユークリッド空間の円盤への写像を「2018」のパターンで埋めようと思ったのだけど、ちょっと調べたら、それをやるには3つか5つの頂点を持つような「2018」をデザインしてそれを中心から外周へと再帰的に貼り付けていくことになりそうで、デザイン力が要求されるし、コードを書く時間もないから、やめ。 正方形を円へと等角写像で膨らませて輪郭を作りつつ、sinをとって膨らみ感を強調し、x軸で多少オフセットして、全体にそれっぽく見せることでごまかしています。

フォントはShowCard Gothicというボリューム感のあるフォントを選びました。

にしても、はじめてPostScript手書きで年賀状を作ってからもう10年になるのかあ。 ということで、これを機に過去のぶんもすべてGitHubにまとめておきました。

もともとPostScriptしばりというわけでもなく、なんとなく西暦の文字列を使って世界で1枚だけの年賀状をアルゴリズミックに生成するつもりしかなくて、2009年はPostScriptじゃないしコードも残っていなかった(Gaucheで書き捨てた)。 まあでも、よく10年続いたなと思う。

10年続きはしたけれど、年に一回しか書かないこともあり、PostScript力にはたいした進歩が感じられませんね。

2017/12/24

TeXでつくるMarkdownパーサ

この記事はTeX & LaTeX Advent Calendar 2017の24日めのために書きました。

TeXの中でMarkdownを書ける

先月のことなんですが、TeXの、TeXによる、TeXのためのMarkdownパーサをつくました。

TeXで実装されてるので、当然、TeXで書く文書のなかで、シームレスにMarkdownを使えます。 具体的には、こんな感じに、\begin{markdown}から\end{markdown}のなかにMarkdown記法が書けます。

\documentclass{article}
\usepackage{md}

\begin{document}
\begin{markdown}

# 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**!

\end{markdown}
\end{document}

これをふつうにTeXで処理すると、記法から期待されるようなPDFができるわけです。

とはいっても、先月の時点でサポートしていた記法はそんなに多くなくて、これくらい。

  • 行頭の「#」の個数に応じた見出し化
  • 行頭の「*」で箇条書き
  • 行頭の「<」でインデント
  • 行頭の数字で連番箇条書き
  • 行頭スペース4個でインデントするとコードブロック化
  • `..`で囲むとインライン等幅
  • *..*で囲むとインラインイタリック
  • **..**で囲むとインライン強調

これ以外の要素を書きたかったら、いったん\end{markdown}して、生のTeXを書いてください。TeXなので、組版に関することなら、なんでもできます。

Markdownの中でTeXを書ける

この記事を読んでいる人はみんなTeX Conf 2017に参加しているので既知だと思いますが、念のため補足すると、このMarkdownパーサはTeX Conf 2017で発表した「TeXは軽量マークアップ言語の夢を見るか」のために作ったものです。 この発表では、Markdownをはじめとするマークアップ記法と、TeX(LaTeX)によって得られる表現力との関係について考察しました。 「Markdownについて話すのにMarkdownパーサの実装経験がなければ刺されるかも」という強迫観念から取り組んだ、概念実証のための実装です。

で、TeXのなかでMarkdownを使えるからといってうれしいことはあまりないし、それで済ませるつもりだったですが、せっかくTeXなので、先日ちょっと手を入れて\TeXくらいは生で書けるようにしました。 その副作用で、コントロールシーケンスや数式も入れられるようになりました!

# markdown-tex

markdown processor in TeX. 
As inline styles, `tt`, *italic*, and **bold** are available. 
Inline equation in \TeX notation $\int_0^1\frac{1}{x}dx = \infty$.

\hfill December 24 2017

## subsection

Here is a enumerate list.

1. enumerate
1. in 
…

しかし、実はこれは誇大広告で、厳密にいうと2つの条件を満たすマクロやコマンドだけがMarkdown記法の中で使えます。

1つめの制約は、完全展開できる必要があるという点です。 たとえば、\sqrtは使えません。 これは、latex.ltxにおける\sqrtの定義では\@ifnextcharが利用されていて、そのなかでは展開されない\futureletが使われているからです。

なんで完全展開可能性が必要かというと、Markdown記法の構文解析を簡単にするために、対象となるトークンリストをいったん「完全展開された文字列」へと変換しているからです。 これにはexpl3の\tl_set_rescan:Nnxを使っています。 その際、TeXの入力を完全展開すると空白文字が集約されてしまってMarkdown記法として構文解析できなくなるので、これらは文字列とみなして完全展開しています。

\tl_set_rescan:Nnx \md_tokens
  {
    \char_set_catcode_letter:n {  32 }% SPACE
  } { \BODY }

これで\md_tokens変数に「完全展開された文字列」が入るので、それを構文解析し、それをTeXの胃袋に送ってPDFを作らせる、というのが先月までの実装でした。 そんなわけで、この状態でMarkdown記法の中に\TeXと書くと、このマクロが完全展開されたT\kern -..5ex\hbox E\kern -.\@mがそのままPDFに出てきてしまう状態でした。

では、Markdown記法の中に\TeXと書いて期待する出力結果を得るにはどうすればいいでしょうか? 完全展開をやめればよさそうですが、前述したようにスペースの扱いの都合があるので、文字列にしてからパースするという方針は変えがたい。 となると、完全展開された文字列をパースするときにTeXのプリミティブをパースしてコントロールシーケンスに変換し直し、それをTeXの胃袋に送ればいいのではないか?

というわけで、そんなようなコードを追加して、無事に\TeXのようなマクロがMarkdown記法のなかに埋め込めるようになりました。

\cs_new:Npn \inside_cs:Nnnn #1#2#3#4 {
  \tl_set:Nn \car_line { \tl_head:n { #4 } }
  \tl_set:Nn \cdr_line { \tl_tail:n { #4 } }
  
  \tl_if_head_eq_charcode:nNTF { #4 } { \sp_letter }
     {
       \tl_put_right:Nn #2 { 
         \cs:w #3 \cs_end:
       }
       \exp_args:NNnff \parse_to_end_line_with:Nnnn { #1 } { #2 } { } { \cdr_line }
     }
     {
       \tl_set:Nx \so_far { #3\car_line }
       \exp_args:NNnff \inside_cs:Nnnn { #1 } { #2 } { \so_far } { \cdr_line }
     }
}

ただし、実装をサボっているので、非標準的(?)な利用方法のコントロールシーケンスはパースできません。 たとえば、\hbot{foo}はいいけど、\hbox to 10pt{foo}とかはだめ。 これがもう1つの制約です。

今回のオチ

にしても、ここまでにやったことを振り返ると、事実上TeXでTeXをパースしているわけで、むだなことをした感が半端ない……。

  1. TeX記法の入力をTeXでパースし、トークンリストが作られた(TeXの仕事)
  2. トークンリストをMarkdown記法としてパースするために、完全展開して文字列化した(\tl_set_rescan:Nnx
  3. その文字列からコントロールシーケンスを取り出すのに、あらためてTeX記法のパーサを実装に追加した(\cs_new:Npn \inside_cs:Nnnn

2017/12/23

なぜ原稿をテキストで書かなければいけないのか

これは編集とライティングにまつわるアレコレ Advent Calendar 2017の23日めの記事です。

原稿をどういう形式・記法で書くべきなのか、という質問をときどき受けます。 一瞬だけ悩むけど、だいたい答えはこうなります。

「記法はなんでもいいけど、できればテキスト形式で」

今日は、この答えの背景を話します。

まずは「なんでもいい」の部分から。

記法はなんでもいい

出版社や編集者によっては細かく原稿の記法を指定しているようですが、ぼくは特に原稿の記法を決めていません。 これは、そういう記法を決めることができずにここまできた、というのが正直な理由です。 つまり、ぼくの怠慢なんですが、なにも考えずに怠慢であったというよりは、積極的に怠慢になろうと考えた結果なので、そのへんを少し吐露してみます。

原稿の記法を決めるということは、執筆者の脳内にあるものを吐き出してもらうための形を決めるということです。 脳内にあるものを他者に見せるための形を決めるわけではありません。

しかし、書き手が脳内を吐き出すという行為には、「どう見せたいか」という書き手自身の気持ちがどうしても混ざります。 この、「どう見せたいか」っていうのは、書く内容に合わせて思いつくものだったり、文章化が難しいから逃げるという側面もあったりするので、書く前から全パターンを網羅しきれるものでもありません。

で、脳内にあるものを吐き出した原稿と呼ばれる何かを、読者向けの見せ方を意識しながら整理する、そんな専門職があります。 編集者っていうんですけど、編集者によっては「あるドメインの読者にとってうれしい見せ方」から「適切な吐き出し記法」を逆算し、それを自分のキャリアのどこかの時点できちんと整備して、知見として執筆者と共有できている人がいます。 ぼくはそれをサボってきたので、そういう知見をとくに提供できず、「なんでもいいです」という頼りない返事になってしまうというわけでした。

ただし、ここからが重要なんですが、考えなしに「なんでもいいです」といっているわけでもありません。 言い訳っぽいですが、吐き出し記法に付随する見え方のほうを意識して見え方に頼った書き方をしてしまったり、汎用のブロック要素を利用した見せ方に依存する書き方が生み出されたり、そういうのを繰り返した結果として、「原稿の記法はあらかじめ決定しないほうがうまくいく」となって現在に至っています。 適切な吐き出し記法をいろいろ考えた結果、適切な吐き出し記法を汎用化すると(少なくともぼくには)うまくいかない、というジレンマに陥ったわけです。 ポジティブにいうと、好きな記法で吐き出してもらうのが執筆者とぼくにとって楽なケースが多いと判断したということです。

できればテキスト形式で

すでに結論めいたものを書いてしまってますが、どう見せるかの検討に移ってよいのは、脳内にある概念をとりあえず文字列として吐き出し、それを文章にして、さらに段落としてしっかり構成したあとです。 もうちょっと正確にいうと、段落の構成を試行錯誤するのと並行して、ようやく見せ方を考えられるようになります。

こんなふうに言うと、「はじめに構成をかっちり固めてから書くんじゃ」という声が聞こえてきそうですが、怒られを恐れずにいえば、それは幻想です。 文章を書く前から段落の構成をかっちり固めるには、相当の訓練とあきらめが必要です。 むしろ、文字列をダンプしたものから段落を試行錯誤して練り上げることこそが、文章作成の王道だといえるでしょう。

原稿がテキストであることが重要なのは、これが主な理由です。 文字列、文章、段落を行ったり来たりするイテレーションを、コンピュータを使って回しまくるには、テキストデータがいちばん好都合なのです。 だから、テキストで書いてください。

さらに、テキストとして吐き出されていれば、編集者が文章や段落をつくる手伝いができます。 テキストであればどの環境でもエディタで編集できるから、という面もありますが、もっと大きいのは、テキストであれば差分をとったりバージョン管理システムを利用したりすることで、編集者の作業を執筆者から見て透明にできるからです。

脳内にある情報を原稿として吐き出すのは、たいへんです。それをさらに文章や段落にするのも、けっこうたいへんです。 だから、後者のほうを手伝う職業として、編集がいるわけです。 しかし、原稿から文章や段落にする過程で、原稿のポイントが失われたり、もともとの執筆者が意図していない情報が紛れ込んだりするのは問題です。 この過程では、「編集者がやったこと」がつまびらかになっている必要があります。 つまり、編集者の作業が執筆者にとって透明である必要があります。 それがコンピュータで不自由なくできるのも、いまのところテキスト形式だけなので、その点でも原稿はテキストにしたいという結論になります。

原稿はソースコード、組版結果はバイナリコード

前述したように、原稿をテキスト形式で書き出し、テキスト形式のまま編集することは、編集者の作業の透明性を高めます。 編集者の作業が透明であるということは、作業結果がすべて執筆者の手元で再現できるということでもあります。 しかも、バージョン管理システムを使えば、元の原稿に対する差分(の積み重ね)という形で再現できます。

これは、執筆者が自身の吐き出した原稿をソースコードとして保持し、そのゆくすえを終始自分の管理下におけるという意味でもあります。 わりと見逃されてる点だと感じてるんですが、「原稿を人に見せる形にまで加工するプロセスが、原稿に責任がある本人にとってアンタッチャブルな状態」って、書き手にとっても編集する側にとっても、けっこう怖くないですか? データとしてアクセスできなければ、どこがどう変わったかをgrepしたり、あとで気づいた用語の間違いを全体にわたって機械的に変換したり、そういう作業が死ぬほどめんどくさくなります。 気に喰わない文章や段落を試行錯誤して手直しすることも、気軽にできなくなってしまいます。 少なくとも、あとは版面に情報を適切に固定するだけという状態になるまでは、編集者はいうまでもなく執筆者自身も原稿にアクセスできるほうがいいはずです。

原稿に責任がある人が、原稿への計算機によるアクセスを奪われないためには、そもそも原稿がそれにかなった形式である必要があります。 その形式として妥当なのは、テキストでしょう。 執筆者にもDTPアプリケーションを執筆に使ってもらう、もしくは、執筆者が利用できるワープロソフトで組版もするという可能性もありえなくはないですが、こうした方法は先に言及した「適切な吐き出し形式」に似たジレンマに陥ります。 「こう見えてほしい」という気持ちを前提にして吐き出しをすると、しっかりした文章や段落を構成するのが困難になるのです。 書いている最中に見せ方を工夫したくなってしまうのは、早すぎる最適化の罠だといってもいいでしょう。 まして、WYSIWYG環境で書くのは、バイナリコードを直接いじっているようなものです。 (そもそも、見た目の先にある組版という専門性が要求されるプロセスに、非専門家が手軽に介入できる状態はどうなのかという問題もあります。 原稿がどう見えてほしいかと、その要求をどう実装するかには、さらに一段階ギャップがあるのです。)

なんだか、ドキュメントにおける構造とスタイルの分離という、よくある話に収斂しているような気もしますね。 実際、気のせいじゃありません。 この記事で言いたかったことを、構造とスタイルの分離という話に翻訳すると、次のように要約できます。

  • ドキュメントの構造となる部分の試行錯誤では、テキスト形式を使うのが作業面でもっとも理にかなっている
  • ドキュメントの構造となる部分は、原稿に責任がある人から最後までアクセスを取り上げるべきでない部分でもあり、それに都合がいいのはテキスト形式である

なお、この記事の趣旨は「執筆や編集にはテキストエディタが最高」ではないので、べつにWordとかGoogle Docs、あるいはIDEなどを執筆や編集に使ってもぜんぜん問題ないです。 ただし注意が必要なのは、それらツールにネイティブな形式(.docとか)をソースにしてしまうと、ここに挙げたようなテキストであることの利点が生かせないということです。 なので、どんなツールで書くにしろ、どこかの時点ではテキスト形式にして、それを最終的なソース原稿とするのが無難だとおもいます。

記法が決まらないと前に進めないならMarkdown的なやつで

というわけで、文章を書くときは、「とにかく脳内をダンプし、試行錯誤して段落を組み立てる」のが基本です。 繰り返しになりますが、脳内を吐き出すときの記法は、どう見えてほしいかという気持ちに無意識に依存してしまいます。 その依存を断ち切り、どう見えてほしいかはいったん忘れて文と段落の構成に集中するというのが、一次脱稿でいい状態にもっていくコツ(はやく脱稿するコツではない)です。 「段落だけを書く」という覚悟で望みましょう。 どんな本にも適用できる決定版の見せ方はないけど、万能の書き方というのは実はあるので、パラグラフライティングをしっかりやってください

とはいえ、そうはいっても脳内を吐き出すときの記法に何かしら制約があるほうがいいっていう人も少なくないと思います。 段落だけとかストイックすぎて無理、見出しの指定方法やインラインの強調方法とか決まってないと書けない、とくに技術書ではコードブロックや図も入れたい、という要求は当然ありますよね。

そんなときは、とりあえず、Markdownふうの記法を使っておきましょう。 ここで、CommonMarkか、それともGitHubFlavoredか、といったことを気にする必要はありません。 見ためを確認したり、そこからワンパスでHTMLやPDFを生成することが目的ではないからです。 ちょっとしたブログ記事ならともかく、どんなMarkdown方言であれ、どのみちMarkdownだけをソースにして本は作れません。 Markdownだけで本が作れたら、XMLとかLaTeXとかとっくに滅んでますね。

まとめ

この記事では、なぜ自由な記法のテキスト形式が原稿の執筆と編集で優位性があるかについて、下記の2点に注目して主張しました。

  • どう見せるかは考えず、段落の書き込みに集中するためには、見せ方と表裏一体な記法には惑わされないほうがよい
  • 内容に責任をもつ著者や編集者が、自分たちには手が出せない状態になる直前まで計算機を使って原稿を操作するには、データ形式としてテキストが好都合

そのうえで、これらの要求を満足するならツールはテキストエディタでなくてもよいこと、シンプルな段落以外の要素として脳内をダンプする手法としてのMarkdownふう記法の可能性について考えました。

Markdownについては、また明日なにか書くかもしれません。

2017/12/06

英語圏のIT系技術書ブランドについての雑感

この記事はpyspa Advent Calendar 2017の6日めのために書きましたが、アマゾンアソシエイト目的です。

『退屈なことはPythonにやらせよう』が出た

2017年にブレイクしたPythonの本といえば、オライリー・ジャパンから発行された『退屈なことはPythonにやらせよう』ですよね。

実はこの本、そのむかし、自分でも翻訳発行をひそかに検討していたのです。 当時の翻訳者候補の方とのDMをさかのぼってみたら、少なくとも2015年7月以前の話でした。 「非プログラマーでもプログラミングしようぜ」という趣旨で著された本書は、わたし自身の書籍企画の方向性によくマッチしていました。 それで本書に目を付けたのですが、いかんせん分量は多いし、Pythonは日本だと入門者向け言語としていまいち盛り上がらないし(当時の話です)、なにより例題があんまりぐっとこないねという話で、そのときは企画化をパスするという結論を出しました。 これは余談にして重要なポイントでもあるんですが、それから起きた出来事を思うと、このとき本書を自分が企画化しなかったのは別の意味でも正解でした。

それから数年たち、Pythonブームという絶好のタイミングで本書が日本語化され、たくさんの人に読まれるに至ったのは、掛け値なしにとてもうれしいことです(ほんとだよ)。 逃がした魚は大きい的な気持ちもないではないですが、ぶっちゃけると、オライリーという看板で出たことが本書の日本での普及にとってとても大きなことだったと思います。

さて、ここで「アレ?」と思う人がいるかもしれません。 「この本はオライリーなのに、オライリーの編集者じゃないおまえが企画を検討してたって、いったいどういうこと?」

オライリーの本はO'Reillyの本とは限らない

『退屈なことはPythonにやらせよう』の原書は、O'Reilly Mediaではなく、No Starch Pressという北米の出版社による発行です。

https://www.nostarch.com/

この出版社の名前を聞くのは初めてという人でも、コンピュータ書に関する情報を気にしている方なら、その発行タイトルのなかには知っているものが少なからずあるでしょう。 No Starch Press発行の本で翻訳されているものを、思いつく限りざっと並べてみます(もちろん全部ではありません(たぶん))。

そうそうたるラインナップですよね。 さらに面白いことに、No Starch Pressは『マンガでわかる統計学』などの英語版の出版社でもあります。

いまではこんなにすごいNo Starch Pressですが、もとはBill Pollockという人が立ち上げた小さな出版社でした。 2006年にBillさんに会ったころもまだまだ小さい出版社でしたが、この10年くらいで一気に魅力的なラインナップを増やし、いまではIT系技術書界隈でかなりの存在感を示しています。 ここでまた余談だけど重要なポイントとして、2006年にBillさんに『マンガでわかる統計学』の版権買ってよという話をするとき、「エディターです」と自己紹介したら、「おれはパブリッシャーだぜ」と冗談で返されたのが自分のなかではものすごい衝撃で、いつかおれもパブリッシャーって名乗るぞとぼんやり思ったのでした (もっともBillさんはぼくのことさえ覚えてない気がする)。

話をもどすと、上記のNo Starch Pressの翻訳書のなかには、『退屈なことはPythonにやらせよう』以外にも、いくつかオライリー・ジャパン発行のものが含まれています。 つまりオライリー・ジャパンから発行されている翻訳書は、必ずしも世界的な技術書ブランドであるO'Reilly Mediaのタイトルだけではないのです。 オライリー・ジャパンの中の人は、No Starch Pressをはじめ、さまざまな海外の出版社からこれはと思う良タイトルをO'Reilly Mediaに限らず探してきて翻訳発行しているわけです。 これぞO'Reillyというカバーだけど動物の版画でない本がけっこうあるのは(宇宙人までいる)、そういうわけなのです。

No Starch Press以外で、日本ではO'Reillyブランドの技術書として誤認されてるんじゃないかなと感じてる本としては、たとえばこんな例があります。

上記6点は、すべて原書出版社がちがいます。当ててみよう。Hayao(-ε-δ)‏ さんに教えていただいたのでアソシエイト効果がありそうなほうを追記しました。Hayao(-ε-δ)‏ さんありがとうございます!)

なお、逆のパターンである「O'Reillyの本がオライリーから出ているとは限らない」も真です。 ただし、最近はO'Reilly Mediaのラインナップの魅力が落ちてるのと、O'Reillyブランドで魅力的なのはオライリー・ジャパンがしっかり出してくるので、ほぼオライリー・ジャパンから出てきているように見えます。

動物だけではない英語圏の技術書ブランド

ここまで長々とアマゾンアソシエイトを張りまくってきましたが、ここからが本記事のタイトルでもある「雑感」です。

2017年現在の英語圏におけるIT系出版社のブランド地図は、たとえば2000年代前半のそれとはかなり変動しています。 2000年代前半は、その当時で創業20年くらいのイケイケO'Reilly Mediaに圧倒的なブランド力がありました。 しかし現在は、この記事でも一押しのNo Starch Pressはじめ、やはり中堅どころのManning Publicationsなど、現時点で創業20年前後を迎えている中小の出版社のほうがむしろ精力的に面白い書籍を生み出している印象があります。 彗星のごとく登場してあっというまに手堅い出版社となったPragmatic Bookshelfも、これから創業20年前後にかけて、もうひと化けするかもしれません。

そうした出版社に比べると、すでに40年近い歴史を持つO'Reilly Mediaは、経営規模で見ても大手出版社として網羅的なラインナップを擁し、中小出版社の書籍の発売元として流通を支える存在にまで成長していますが、発行書籍の面白さとかクオリティという点では最近ぱっとしないなというのが率直な感想です。 それに呼応するように、いま企画が好調なオライリー・ジャパンが、少なくとも翻訳書についてO'Reillyタイトル依存でなくなっているというのは感慨深いところです。 そういえばオライリー・ジャパンも、いまちょうど創業20年ちょっとですね。

一方、O'Reilly Mediaよりさらに老舗のPearsonや、そのハイエンドコンピュータ書籍のレーベルとしてのAddison-Wesleyは、タイトル数こそ多くないですが、IT系技術書出版社としての信頼感はいまなお顕在だなあと感じることがわりとあります。 タイトルに対する信頼感という意味では、The MIT PressやCambridge University Pressなどの大学出版系も依然として強くて、これからも日本語で読めるようにしていくべきだと思えるような本はこのへんの老舗出版社のものがますます多くなるのかも、と思っています。

精力的といえば、英国を拠点に爆発的にラインナップを増やして一気に存在感を増したPacktという出版社もあります。 Packtの特徴は、とにかく最速であらゆるIT系のトピックについて書籍の形をしたものをそろえるという戦略です。 そうしたラインナップ網羅主義は、ある意味ではO'Reilly Mediaが目指してきたところだとも思います。 ラインナップ網羅主義には、個別のタイトルの出来不出来をケアできないという面があるので、個人的には避けていきたい方向性ですが、いかんせん展開が速いので、Packtの傾向にも注目だけはしていこうと思っています。

今回のオチ

日本語圏におけるIT系技術書の状況については、あまり大きなことを言える立場にないですが、いろんな人たちの紆余曲折とか踏ん張りとか地道な出版活動とかあって、いろんなブランドが盛り上がったり、消えたり、地に落ちたり、新しく誕生したりしています。

そんななかで、この記事をここまで読んでアマゾンアソシエイトを踏まなかった方には、2017年に4つのタイトルを発売して始動したラムダノートというIT系技術書出版社の名前を覚えてもらえるとうれしいです。

2017/12/03

TeXでつくる『RubyでつくるRuby』

この記事はTeX & LaTeX Advent Calendar 2017の3日めのために書きましたが、宣伝目的です。

TeX & LaTeX Advent Calendar 2017の重点テーマは「TeXでつくるアレ」とのことですが、偶然にも2017年、よく似たタイトルの『RubyでつくるRuby』(遠藤侑介著)という本が出ました。 プログラミング言語を学ぶときの例題としてプログラミング言語をつくる以上に格好のネタはない、という趣旨の本です。

プログラミング言語をつくるというと、なにやら難しく聞こえるかもしれませんが、『RubyでつくるRuby』では、わずか150ページのなかにそのエッセンスを凝縮しています。 本文の理解を助けるかわいらしいイラストもフルカラーでふんだんに用意されているので、はじめてプログラムを書いてみようかなという人でも、おそらく(願わくば)読み通せる内容です。 電子書籍はなく、古き良き紙の本のみですが、電子版がいいという人はAscii.jpでもとになった連載が読めるので、そちらをどうぞ!

プログラミング言語の処理系が扱うデータは「木」

『RubyでつくるRuby』では、プログラミング言語Rubyで書かれたプログラムを処理して実行するプログラミング言語を、プログラミング言語Rubyでつくります。 つまり、本書の読者が書くことになるプログラムが処理するのは、Rubyのプログラムです。

Rubyに限りませんが、多くのプログラミング言語では、プログラマーが書いたプログラムを実行する前に、そのプログラムをまず「木」と呼ばれる種類のデータへと変換します。 この「木」は、その名のとおり樹木のような姿をしていて、「枝がのびる節」と「葉」があります。

このへんは、文章で説明するよりも、絵で見るほうがはやいでしょう。 たとえば、次のようなRubyのプログラム(四則演算だけですが)がどんな木になるかというと……

(1 + 2) / 3 * 4 * (56 / 7 + 8 + 9) 

こんな木になります。式で見るより、項どうしの演算の関係がわかりやすいですね。

本書の解説には「木」を扱う場面がたくさん出てくるので、説明文やコードに加えてこんな具合に木の絵をたくさん用意できれば、いま説明しているデータの姿がどんなようすなのか「ひとめ」でわかります。 なので、ぜひ木の絵はたくさん載せたい。

かといって、こういう木の絵をぜんぶイラストレーターさんに描いてもらうのもたいへんです。 描くほうだけでなく、間違ってないかチェックするほうもめんどくさい。 それなりの見た目で、なおかつ間違いなくプログラムの木を描くには、どうすればいいでしょうか?

そう、TeXを使えばいいのです。 実際、上に例として出した木もTeXで生成しています。

TeXで木を描く

というわけで、前置きが長くなりましたが、『RubyでつくるRuby』の木の絵をTeXでどう描いたかをちょっと紹介します。 書籍『RubyでつくるRuby』では、プログラムの木を、Rubyにおける配列表現からTeXで生成しました。 これなら手間もかからず、なにより作図にともなう間違いもありません。

tikz-qtreeパッケージの使い方

木は、プログラムに限らずいろいろな場面に出てくるデータ構造なので、関連するTeXパッケージがわりとたくさん出そろっています。 そのなかで『RubyでつくるRuby』の木を描くのに選んだのは、 tikz-qtree というTikZベースのパッケージです。

https://ctan.org/pkg/tikz-qtree

この tikz-qtree パッケージを選んだ理由のひとつは、上下逆向きの木構造を手軽に描けることです。 木構造を描くときは、根を上にする(つまり本物の樹木でいったら上下逆)ことが多いのですが、本書の場合にはイラストにある本物っぽい木の絵とシームレスに読み替えてもらいたいので、根を下にして木構造を描ける機能が重要だったのです。

tikz-qtree のミニマルな例を示します。これは 2 * 4 というRubyプログラムの「木」の例です。

\documentclass[tikz,convert={outext=.png}]{standalone} 
\usepackage{tikz-qtree}
\begin{document}

\begin{tikzpicture}
  \Tree [.*
          [2 
           \node[draw]{4};
          ]]
\end{tikzpicture}

\end{document} 

\Tree[ ] のなかに、木を描いてきます。 [ ] を入れ子にすると、その中に書いたものが子どもの要素になります。 要素としてスペース区切りで値を書き込めば、それが葉になります。 子を持つ要素には、値の前に「 . 」をつけます。 上の例では、根にあたる「 * 」に「 . 」が必要です。 さらに上の例では、TikZの \node 命令がそのまま使えることを示すために、「4」のほうだけ枠をつけてみました( \node 命令なので末尾に ; を忘れずに!)。

上記を tree.tex として保存し、以下のようにpdflatexで処理すれば……

$ pdflatex --shell-escape tree.tex 

こんな絵が得られます。

この木の上下をさかさまにするには、 tikzpicture 環境に [grow'=up] というオプションをつけるだけです。

\documentclass[tikz,convert={outext=.png}]{standalone} 
\usepackage{tikz-qtree}
\begin{document}

\begin{tikzpicture}[grow'=up]
  \Tree [.*
          [2 
           \node[draw]{4};
          ]]
\end{tikzpicture}

\end{document} 

このままだと絵として味気ないので、色をぬったり、枠の形を変えたり、線の幅を調整したりするわけですが、そのへんはTikZの \node をごにょごにょいじるというつまらない話なので割愛します。 TikZのマニュアル(むかしは400ページくらいでしたが、いまでは1000ページ超)を片手にがんばってみてください。

TikZソースを木のソースから生成する

木の見た目を整えたら、毎回TikZを手描きするのはばかばかしいので、プログラムで生成するようにします。 『RubyでつくるRuby』で描きたいのはプログラムを表す木で、その木はRubyコードとしてはこんなふうな姿をしています。

["*", 2, 4] 

本当は、 2 とか 4 が何ものであるかを表すために、もうちょっとメタ情報がついていますが、だいたいこんな感じです。 (そもそも、配列でプログラムの木を表すのはあくまでも『RubyでつくるRuby』の中に限定した話で、じっさいのRubyではまったくべつの表現方法です。)

これはどう見てもS式なので、カンマを削除してGaucheで直接読み込んで変換し、 tikz-qtree パッケージを使った木を描くTeXソースを吐くようにしましょう。

(use srfi-13)
(use text.tree)

(define (deco-b b)
  #"\\node[text=white,inner sep=4pt,drop shadow,fill={rgb:blue,5;white,1;green,1},draw,rounded corners]{\\small ~b};")
  
(define (deco-l l)
  #"\\node[text=white,inner sep=2pt,drop shadow,fill={rgb:green,6;white,1;black,4},draw,ellipse]{\\mystrut\\smash{~l}};")

(define *before-tikz* "\
\n\\begin{tikzpicture}[grow'=up] \
\n  \\tikzset{ \
\n    every tree node/.style={font=\\ttfamily\\large}, \
\n    edge from parent/.append style={very thick}} \
\n  \\Tree ")

(define *end-tikz* "\n\\end{tikzpicture}\n\\clearpage\n")

(define *before-doc* "\
\n\\documentclass[tikz,border=10pt,convert={outext=.png}]{standalone} \
\n\\def\\mystrut{\\rule{0pt}{1.3ex}} \
\n\\usepackage{tikz} \
\n\\usepackage{tikz-qtree} \
\n\\usetikzlibrary{shapes.geometric,shadows}% \
\n\\begin{document}\n")

(define *end-doc* "\n\\end{document}\n")

(define (tikzqtree ts)
  (list *before-tikz* (mkqtree ts) *end-tikz*))

(define (mkqtree ts)
  (cond ((null? ts) "")
        ((pair? ts) (mkbranch
                      (car ts)
                      (map mkqtree (cdr ts))))
        (else (mkleaf ts))))

(define (mkbranch b l)
  (list "[." (deco-b (x->string b)) "\n " l "]"))

(define (mkleaf l)
  (list (deco-l (x->string l)) " "))

(define (main args)
  (call-with-input-file (cadr args)
    (lambda (p)
      (print
       (tree->string
        (list
         *before-doc*
         (map tikzqtree (port->sexp-list p))
         *end-doc*)))))) 

カンマをプログラムで削除しないのは、カンマなしならS式としてそのままreadできるからです。この手のユーティリティはコーディングが簡単なほうに倒してガッっと書いてしまうのが肝要だと思います。

実行結果

最初に紹介した、わりと複雑なかっこうをしている次のようなRubyの計算式について、プログラムの木を描いてみましょう。

(1 + 2) / 3 * 4 * (56 / 7 + 8 + 9) 

この計算式は、『RubyでつくるRuby』ではこんな感じの木(配列の配列)として表されます。

["*", ["*", ["/", ["+", 1, 2], 3], 4], ["+", ["+", ["/", 56, 7], 8], 9]] 

この一行をファイルに保存して、カンマだけエディタで削除し、先ほどのGaucheスクリプトで読み込むと……

$ gosh mktree.scm temp.rb > temp.tex 

こんな気持ちの悪いLaTeXのソースができます。

\documentclass[tikz,border=10pt,convert={outext=.png}]{standalone}
\def\mystrut{\rule{0pt}{1.3ex}}
\usepackage{tikz}
\usepackage{tikz-qtree}
\usetikzlibrary{shapes.geometric,shadows}%
\begin{document}

\begin{tikzpicture}[grow'=up]
  \tikzset{
    every tree node/.style={font=\ttfamily\large},
    edge from parent/.append style={very thick}}
  \Tree [.\node[text=white,inner sep=4pt,drop shadow,fill={rgb:blue,5;white,1;green,1},draw,rounded corners]{\small *};
 [.\node[text=white,inner sep=4pt,drop shadow,fill={rgb:blue,5;white,1;green,1},draw,rounded corners]{\small *};
 [.\node[text=white,inner sep=4pt,drop shadow,fill={rgb:blue,5;white,1;green,1},draw,rounded corners]{\small /};
 [.\node[text=white,inner sep=4pt,drop shadow,fill={rgb:blue,5;white,1;green,1},draw,rounded corners]{\small +};
 \node[text=white,inner sep=2pt,drop shadow,fill={rgb:green,6;white,1;black,4},draw,ellipse]{\mystrut\smash{1}}; \node[text=white,inner sep=2pt,drop shadow,fill={rgb:green,6;white,1;black,4},draw,ellipse]{\mystrut\smash{2}}; ]\node[text=white,inner sep=2pt,drop shadow,fill={rgb:green,6;white,1;black,4},draw,ellipse]{\mystrut\smash{3}}; ]\node[text=white,inner sep=2pt,drop shadow,fill={rgb:green,6;white,1;black,4},draw,ellipse]{\mystrut\smash{4}}; ][.\node[text=white,inner sep=4pt,drop shadow,fill={rgb:blue,5;white,1;green,1},draw,rounded corners]{\small +};
 [.\node[text=white,inner sep=4pt,drop shadow,fill={rgb:blue,5;white,1;green,1},draw,rounded corners]{\small +};
 [.\node[text=white,inner sep=4pt,drop shadow,fill={rgb:blue,5;white,1;green,1},draw,rounded corners]{\small /};
 \node[text=white,inner sep=2pt,drop shadow,fill={rgb:green,6;white,1;black,4},draw,ellipse]{\mystrut\smash{56}}; \node[text=white,inner sep=2pt,drop shadow,fill={rgb:green,6;white,1;black,4},draw,ellipse]{\mystrut\smash{7}}; ]\node[text=white,inner sep=2pt,drop shadow,fill={rgb:green,6;white,1;black,4},draw,ellipse]{\mystrut\smash{8}}; ]\node[text=white,inner sep=2pt,drop shadow,fill={rgb:green,6;white,1;black,4},draw,ellipse]{\mystrut\smash{9}}; ]]
\end{tikzpicture}
\clearpage

\end{document} 

これをコンパイルすると……

$ pdflatex --shell-escape temp.tex 

冒頭に掲載したような、こんなきれいなpngファイルが得られるというわけでした。

まとめ

『RubyでつくるRuby』を読むと、このような「木」がプログラムそのものだということがわかります。 このように生成された図だけでなく、hirekoke画伯描きおろしカラーイラストも豊富に掲載された『RubyでつくるRuby』をいますぐ買おう!

繰り返しになりますが、電子版はラムダノートでは出版していないものの、Ascii.jpでもとになった連載が読めます。ぜんぶ無料!

2017/08/21

LLイベント2017の「第2プログラミング言語鑑定団」で鹿野が話したことまとめ

プログラミング好きにもいろいろあって、仕事で使ってる道具をもっと知りたいという人もいれば、自分が使ったことない道具の話を知りたいという人もいれば、道具はなんでもいいから面白い話がしたいという人もいます。 久しぶりに参加したLLイベントは、そんな多様なプログラミング好きが「全員がアウェーな立場」で交流するという、貴重で面白い機会でした。 実際、「LL」の1つめのLには去年までは「Lightweight」という意味があり、その単語が示す特徴をもった言語のイベントのようにどうしても見えてたんですが、今年からはそういう区切りも公けになくし、Lは「Learn」の意味になったとのことです。

そのLLイベント2017で、「第2プログラミング言語鑑定団」というセッションに出させてもらいました。 司会の小山さんが「Teratail, Yahoo知恵袋などから、それらしい質問をかき集めてマージ」した6パターンの「次に学ぶ言語は何がいい?」に対し、鑑定団の一人としてお勧め言語を紹介せよというのがミッションでした。 ぼく以外の鑑定団のメンバーは、ささけんさん高野さん高橋さん。一癖あるすごいITエンジニアばっかりだー。このメンバーが集まるというだけで、LLイベントすごいって気持ちになりました。

いっぽう、ぼく自身はただの書籍編集者です。 自分の仕事に必要な道具を作ったり環境を整えたりはするけどエンジニアというわけではないし、プログラミングは好きで勉強はするけど研究者ではないし、 本職ではない人間になんという無茶ぶりかと思って最初は躊躇したのですが、たぶん、この記事を書かせてもらったことをきっかけに声をかけてもらえたんだろうなあ。

employment.en-japan.com

なお、上記の記事は「ElixirとRustとHaskellにちょっと興味がある人向けの紹介記事を各界の第一人者に書いてもらおう」という企画の前フリなので、そういう目線でやさしい気持ちで読んでもらうと幸いです。 ElixirRustはすでに公開中。今月中にHaskellも公開される予定です(宣伝)。

ほかの鑑定団の回答

そもそもブログで自分の回答を書くつもりはなかったんですが、ささけんさんがさっくりと自分の回答をまとめて公開したので、まとめざるを得なくなった。

[高野さんと高橋さんが何か公開されたらリンクはる予定地]

鹿野はどんな言語を勧めたか

想定質問は事前に見せてもらってたのですが、じゃあその質問に対して何を答えることが求められてるんだろうというのは、正直なところ当日になってもわからなくて、会場に着くまでは「ちょっとまずいかもなあ」と暗い気持ちでいました。 で、それを一緒に来ていた同僚に愚痴ったところ、「お勧め本を紹介したらいいじゃん」という画期的な入れ知恵をしてもらい、その路線でいくことに決めたのでした。

質問1

文系の大学4年生のときにプログラミングが好きになり、独学で C と Java の初歩を学びました。卒業後Web 制作会社に入社し、HTML, CSS,JavaScript を習得しました。Web周辺だけでは将来が不安なので、次に何を学ぶべきか考えています。アドバイスをいただけないでしょうか。

この質問を最初にみたときは「知らんがな」という思いしか去来せず、サイコロでも投げて決めろと言いたかったのですが、言語じゃなくて書籍であれば紹介すべきものがすぐに思いつきました。 五十嵐先生の『プログラミング in OCaml』です。なので、回答は「OCaml」にしました。

あらかじめ断っておくと、ぼくはOCamlを実用してるわけではありません。 OCamlのコードをいじったのは、『型システム入門』を作ったとき、OCamlで書かれた原著者ビルド環境を日本語pLaTeX向けに改修したときくらいです。 ですが、この本は、OCamlを使うつもりがとくにない人でも、独力でプログラミングを学んできたような人であれば、読むといいことがたくさん書いてあると思っています。 具体的には、OCamlというプログラミング言語でのプログラムの書き方だけでなく、どうしてそういう機構になっているのかがいちいち詳しく解説されており、プログラミング言語の理論についても味見できるようになっています。 この質問者はWeb周辺の技術を追いかける以外の勉強をしたいようだし、そういう意味でもぴったりではないかと思いました。

質問2

文系大学に通う学生ですが、昔からゲームが好きで、将来はゲームクリエイターになりたいと考えています。そうはいってもプログラミングはまだできないし、特筆したスキルもありません。ゲームクリエイターに関する書籍を読んで、将来こんなゲームを作りたいと夢を膨らませています。私がゲーム開発者になるためにはどの言語から学ぶのがよいでしょうか?

ゲーム作りたいといってる時点で、プログラミング言語を選んでる場合じゃなく、むしろどのゲームエンジンを使ってみればいいかという話なんですよね。 なので、回答は「Unity」か「Unreal Engine」にしました。

書籍として紹介したのは、『Unreal Engine 4で極めるゲーム開発』です。無責任にも自分では読んでないんですが、渋川さんが激烈に勧めているので間違いないでしょう。

質問3

Web制作会社でサーバサイドを開発しているソフトウェアエンジニアです。現在使っているプログラミング言語はRubyでフレームワークはRailsです。最近世の中でAIや機械学習がブームになっていて、私もそちら方面のスキルを磨いてより高度な作業をできるようになりたいと考えています。AIや機械学習を使いこなすのに最適なプログラミング言語は何でしょうか?

機械学習で縛られてる設問なので、Pythonからは逃げられないような気がします。ということで、回答としては「Python」。

でも、たぶんPythonを学べばどうなるものでもなく、線形代数なんかを地道に復習したほうがいいような気もします。 そのへんからかみ砕いて解説されているという点で、書籍は『ゼロから作るDeep Learning』をお勧めにしました。

質問4

SIerとして大手案件の2次下請けを仕事にしています。主に使っている言語はJavaでフレームワークはStrutsです。噂ではStrutsにもSIerにも未来はもう無いそうで、転職して他の仕事もできるようになりたいのですが、これまでJavaしか使ったことがないのでどうしたら良いか分かりません。これから学ぶのならば、なるべく長く役に立つ技術が良いと思うのですが、何がよいでしょうか。

「長く役に立つ」といったら、これまで長く使われてきた実績があり、これからもそう簡単に消えることはないであろう言語しかないだろうということで、「Common Lisp」か「Haskell」と回答しました。

書籍はそれぞれ『実践Common Lisp』と『すごいHaskell』を紹介。このへんは我田引水させてもらいました。

質問5

プログラミング初心者です。Webサイト作成のためにPHPの学習中ですが、他の言語にも興味があります。しかしなかなか難しいのもあって効率的なプログラミング学習法はないかと頭を悩ませているところです。そこで、おもしろそうと興味を持てば学習がはかどるのではと考えました。面白いプログラミング言語とその理由を教えてください。

面白いプログラミング言語といったら、とりあえずこれを押さえておけということで、「Brainfuck」です。 とはいえ、Brainfuckでプログラムを書くんじゃなく、好きな言語でBrainfuckを作ってみたらという提案をしました。 やっぱり、プログラミング言語ってこういうことなんだという実感を得るには、なんでもいいから作ってみるのがいちばんで、そのためにもBrainfuckの実装には一度は挑戦してみると楽しいと思います。

というわけで、お勧めした書籍は『Rubyで作る奇妙なプログラミング言語』。

質問6

インフラ運用エンジニアをしています。使える言語はシェルです。仕事ではたくさんのOSSを使用していますが、これらは書かれている言語がC,PHP,Python,Ruby,Node.js,Javaなど多岐にわたります。最近は自動化がブームですが、OSSを使って自動化をやっていくために、どのような言語を学ぶのがよいでしょうか。

OSSのツールを利用していくのに知っておいたほうがいい言語で、質問に出ていないものといって思いつくものは、「Go」しかありませんでした。 というわけで書籍としては『プログラミング言語Go』です。

いま思い返すとPerlとかLuaという選択肢もありえましたが、やっぱりあの場でお勧めする言語としてはGoしかありませんでした。 なぜなら、Goはラムダノートから近日中に新刊が出る予定だからです。 アスキーjpで連載していた「Goならわかるシステムプログラミング」の書籍化です! 昨日のLLイベントでも「低レイヤをかじることの重要性」は何度か強調されていて、そのたびにCやアセンブラというキーワードが出ててましたが、いまならそれこそGoで楽に学べます。 そういう趣旨で好評の連載に、著者の渋川さんが少し話を追加して、10月くらいに出せるように頑張って制作中。お楽しみに(宣伝)。

質問7(会場からの飛び入り質問)

小学三年生の息子がプログラミングをはじめるのに、Scratchのほかにどんな選択肢がありますか?

小学生にプログラミングを教えるときって、ビジュアル言語じゃない形でコンピュータの開発環境に触れる機会も必要だと思ってるんですよね。 かといって、汎用言語はそこそこ覚えないといけないことが多くてつらい。 そこで、覚えることが最小限で、コンピュータの生っぽいところを意識できる言語があればいいんですが、その条件を満たす言語はSchemeくらいしかありませんよね(異論は認める)。 というわけで「Scheme」をお勧めしました。

参考書籍はもちろん『計算機システムの構造と解釈』です(いまおもうと『Scheme手習い』という手もあった)。

2017/06/21

編集というサービスの内容(技術書編)

技術書の編集者が原稿に対して何を提供するものなのか、整理してみた。順番には意味があります。

  1. 原稿をDTP担当者が作業できるデータにする
  2. 誤字脱字、非標準的な表記を直す
  3. 表記を統一する
  4. 文法の間違い、不適切な言い回しを直す
  5. 構成の不備、内容の間違いを指摘する
  6. 構成の不備、内容の間違いを直す
  7. 冗長な内容、文脈から外れる記述を欄外に追い出したり、段落構成を手直ししたりする
  8. 段落や文を、文脈に合わせた相に書き直す
  9. 行間をうめる
  10. 解説画像やイラスト、索引などのメタ情報を作る
  11. 原稿を書く
  12. 【番外】企画する

どこまでやってほしいか、できるか、追加料金がいくら必要なのかというのを、著者・版元編集者・下請け編集者の間ではっきりさせると、みんなが幸せになる気がする。(だいたい編集外注するときって「編集作業一式」の「ページあたりの単価」になりがちで、しかしその「一式」には上記のような幅があるわけだから、人によって高いとか安いとか感じ方がいろいろ変わってしまうよね……。)

本として書店に並ぶまでに必要な作業は上記のほかにもいっぱいあり(装幀の企画と手配、権利、印刷製本、流通に関連するいろいろな仕事などなど)、上記に挙げた編集業務を担当編集者がぜんぶやるべきという話ではないはず。

たとえば、上記のうち5までは担当編集者が直接やるけど、残りは外部の査読者だったり編集者だったりを雇うことにするとか、あるいは、そこは著者の仕事であると最初から割り切る(ということを著者との間で同意しておく)ほうが、結果的に読者が手にする本にとって最善というケースもあるかもしれない。

なお、弊社では上記のすべてに対応した編集業務の受注が可能です。お気軽にご相談ください。

2016/12/30

2017年賀状

年賀状書いた。

%!PS
<< /PageSize [285 420] >> setpagedevice

/setrandcolor {% def
    /r1 {rand 5 mod 3 div} def
    /r2 {rand 4 mod 4 div} def
    /r3 {rand 3 mod 4 div} def
    r1 r2 r3 setrgbcolor
} def

/f {% def
    dup dup dup
    4 mod 0 eq {(2) 4 1 roll -1 0 rmoveto} if 
    4 mod 1 eq {(0) 3 1 roll -3 0 rmoveto} if 
    4 mod 2 eq {(1) 2 1 roll -3 0 rmoveto} if 
    4 mod 3 eq {(7 ) -5 0 rmoveto} if
} def

/i 4 def

/lineto-chars { % def
  /ex x def /ey y def
  /y exch def /x exch def
  /d x ex sub dup mul y ey sub dup mul add sqrt def
  /R y ey sub x ex sub atan def
  R rotate
  { d 0 le % ifelse
    { exit }
    { setrandcolor 
      /ra rand 5 mod 3 div 10 mul 22 add def
      /Georgia-Bold findfont
      [25 0 0 ra 0 0] makefont setfont
      i f show
      /i i 1 add def
      /d d 7 sub def }
  ifelse
  } loop
  0 R sub rotate
} def

1 1 20 { % for
  /n exch def

  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
  {/y exch def /x exch def}{lineto-chars}{}{} pathforall
  gsave
  
  32 230 moveto
  0.9 0.1 0.2 setrgbcolor
  /Georgia-Bold findfont [90 0 0 100 0 0] makefont setfont
  (2017) show
  
  grestore
  showpage
} for

2017 by Keiichiro Shikano on Scribd

PSの解説でよく登場する、パスに沿った文字列描画の簡易版です。 まずflattenpathしてカレントパスをlinetoの配列に変換したあと、各linetoが描く直線がX軸になるまで回転→linetoの長さまで数字を順番に書く→回転を戻す、を繰り返しています。 どのへんが簡易版かというと、グリフを書き終わったポイントは当然ながらオリジナルのパスからはずれているのだけど、そこへ戻す処理をさぼっています。そのため、ベースになるパス(ハート型)よりも文字列の描く図形のほうが肥大していく、それもフォントや処理系によってずれ幅がけっこう違ってしまう、という緩い仕様です。 このコードはWindowsのDistillerに合わせてあります。 gsだと、なぜかずれがもう一回り大きい。

過去のやつ。