2016-05-11

BitKeeperがオープンソース化された付記DVCSの歴史

BitKeeper

BitKeeperは最初の分散ソース管理システムである。今後はオープンソースのApache 2.0ライセンスとして提供される。

BitKeeperは高速で、エンタープライズレディな、分散ソースコード管理であり、大きなプロジェクトから小さなプロジェクトまでスケールする。

「最初の」という主張には語弊があるが、DVCSの歴史を考えると、あながち間違いでもない。

DVCS(分散バージョン管理システム)を最初に実装したのは、Sun WorkShop TeamWareである。

Sun WorkShop TeamWare - Wikipedia, the free encyclopedia

これは名前通り、Sun Microsystemsによって開発されたDVCSで、その主要な開発者として、Larry McVoyがいる。

Larry McVoy - Wikipedia, the free encyclopedia

Larry McVoyはその後独立してBitMover社を立ち上げ、BitKeeperというDVCSを開発する。BitKeeperは2005年までLinuxカーネルの開発に使われていた。

BitKeeper - Wikipedia, the free encyclopedia

Larry McVoyは、1990年台前半に、Sun MicrosystemsはSunOSをオープンソース化すべきであると主張していた。

The Sourceware Operating System Proposal

もし実現していれば、Linuxは今日の興隆を見なかったかもしれず、我々はSunOSを使っていたかもしれない。

そもそも、Sunの生い立ちたるや、IBMのメインフレームのような巨大で高価なコンピューターに対して、より小型で安価なUnixワークステーションを販売して成功したというものだ。とすれば、次は個人でも所有できる、さらに小型で、さらに安価なPCが流行するというのは、自身の成功体験から予測できたはずである。PC用のハードウェアを売る商売でSunは儲けられたはずであり、OSは自由にできたはずだ。我々はIBM PC互換機ではなく、Sun PC互換機を使っていて、WindowsやGNU/LinuxのかわりにSunOSを実行していたかもしれない(Sunのユーザースペースツールは使いづらいのでGNUはまだ残っていたかもしれない)。

にもかかわらず、Sunは近視眼的な判断によってSunOSをオープンソースにはしなかった。

さて、1993年にSunOSのオープンソース化を主張したLarry McVoyは、残念ながらその主張を実践しなかった。BitMover社を立ち上げてBitKeeperを開発したが、BitKeeperはプロプライエタリであった。2005年まで、Linuxカーネルの開発に使われていたが、無償版で提供されていない機能を実装したLinuxカーネル開発者であるAndrew Tridgellの行為に激怒してコミュニティへのBitKeeperの提供を辞めた。

そして、gitが生まれることになった。gitは圧倒的な速度でDVCS市場を独占していき、BitKeeperなど誰も相手にしなくなった。そして今日に至る。

残念ながら、BitKeeperのオープンソース化は、10年遅かった。もう手遅れだ。

2016-05-08

xkcd 463: 投票機

xkcd: Voting Machines

Premier Election Solutions社(以前はDiebold社)は、自社で開発したオハイオ州の選挙用の投票機が、McAfee アンチウイルスソフトウェアの問題によって障害を起こし責任を追求されている

「ちょっとまて」
「投票機にアンチウイルスソフトウェアだと? 間違ってるだろ」

「なんで? セキュリティは重量だろ?」
「もちろんそうだが、なんと言うべきか」

「保護者の教師の説明会で、教師が授業中は常にコンドームをつけているので安全だと保護者の説明したとしよう」

「なるほど、厳密に考えると、付けていないよりは安全・・・」
「間違ったやり方のヤツがいかに多いことか」

titleテキスト:これで俺はまた暗号会議を追い出された。いいだろ。いい例えなんだからさ。

2016-05-05

MITがSICPを教えなくなった理由

Programming by poking: why MIT stopped teaching SICP | posterior science

このNYC Lisp meetupの動画で、Gerry Sussmanに対する質問として、SussmanとAbelsonの古典、The Structure and Interpretation of Computer Programs(SICP)に基づく、伝説的な6.001講義をなぜMITはやめたのかと聞かれている。

Sussmanの回答としては、SussmanとHal Abelsonは1980年代から延々と教え続けるに嫌気が差し、1997年に、学部長の事務所に行って、「俺らはやめる。後どうするからは勝手に考えろ」と宣言した。より重要なこととしては、SICPのカリキュラムは、今日のエンジニアリングに求められるエンジニアを育てることができないからである。1980年代と1990年代には、エンジニアは複雑なシステムを組むのに、単純で十分に理解されている部品を組み合わせた。SICPの目的は、そのようなシステムを理解するための抽象的な言語を提供することだ。

今日では、状況が変わっている。今のエンジニアは、自分が完全に理解していない複雑なハードウェアのためのコードを日常的に書いている(そして、大抵の場合、企業秘密により完全に理解するのは不可能である)。ソフトウェアでも状況は同じだ。プログラミング環境は、多大な機能を提供する巨大なライブラリ群の集合として存在している。Sussmanの今日の生徒は、その時間の大半を、ライブラリのマニュアルを読み、どのように組み合わせれば目的が達成できるのかを把握することに費やしている。Sussman曰く、今日のプログラミングは、「より科学に近い。ライブラリを持ち寄って、つっつき回すのだ。プログラムを書くには、突っつき回して、どのように動作するかを観察する。そして、「目的を達成するために改造できるか」と考えるのだ」。SICPの「合成による解析」という物の見方である、小さな、単純な部品を組み合わせて大きなシステムを作るということは、もはや今日の状況にそぐわなくなった。今や、我々のプログラミングはつっつき回すことで行われている。

なぜPythonを選んだかということについて、Sussmanは、"late binding"に決定したと冗談を飛ばした。Pythonには大量のライブラリがあり、教育者の様々な実習に使いやすい(たとえば、ロボットを制御するソフトウェアを書くなど)

Sussmanは、SICPカリキュラムは現在のカリキュラムより洗練されていると考えているものの、正しいカリキュラムのあり方についてはまだ答えが出ていないという。

たしかに、今のプログラマーは、ハードウェアの仕様書を元にを直接操作するコードは書かないし、OSを実装していないし、コンパイラーも実装していないし、古典的なアルゴリズムやデータ構造さえ自分の手で書く必要がなくなっている。ライブラリが発達してその必要がなくなったためでもあり、また個々の機能があまりにも高度になりすぎて、到底一個の人間の手に負える作業量ではなくなったということもある。

不自由なハードウェア、ソフトウェアが蔓延してその詳細がわからなくなり、また自由なソフトウェアであっても、その内容が複雑になりすぎ、一つ一つ完全に理解するには時間が足りなすぎる。

何にせよ、平均的なプログラマーが実現できる機能は昔よりはるかに複雑になっていることは確かだ。

2016-05-02

Craig WrightがSatoshi Nakamotoだとする証明はない

WiredとGizmodeにより、Craig Wrightなる人物がbitcoinのオリジナルの設計者にして最初の実装者、Satoshi Nakamotoであると報じている。

Bitcoin’s Creator Satoshi Nakamoto Is Probably This Unknown Australian Genius | WIRED

This Australian Says He and His Dead Friend Invented Bitcoin

bitcoinのオリジナルの設計者にして最初の実装者は、当時Satoshi Nakamotoと名乗っていた。一見、日本人のような名前であるが、彼は自らのことを多く語らず、またできるだけ身元の特定に繋がる痕跡は隠していた。当然、国籍はおろか、個人かどうかすらもわからない。彼の書いたコードのコメントはすべて英語で、非英語ネイティブにありがちな文法ミスはみあたらない。また、彼の当時のフォーラムへの500件ほどの投稿を調べると、GMTで5時から11時にかけてほとんど投稿がみられないので、Satoshi Nakamotoはこの間には睡眠をとっていたのではないかと推測されている。この時間帯はJSTに生きる人間の一般的な睡眠の時間帯とは異なっている。

Satoshi Nakamotoの正体には様々な憶測が飛び交い、日本人である京大の望月新一教授や、たまたまSatoshi Nakamotoという名前であるアメリカ人がメディアによって正体であると噂されたりもした。

さて、このCraig Wrightなる人物は、自ら作者であると名乗りでた人物であるが、発言がまるででたらめであると言われている。Bathurst大学で博士号を取ったと自称しているが、大学は否定した。また、彼のブログによる証明というのも、bitcoinの公になっているハッシュ値にすぎず、ブログで提示しているbase64っぽい文字列に至っては、デコードすると単なる平文のブログ本文にもある文字列になるというお粗末さである。

Jean-Paul Sartre, Signing and Significance - Dr. Craig Wright BlogDr. Craig Wright Blog

そもそも最も簡単な照明である、当時Satoshi Nakamotoが使っていた最初のPGP秘密鍵で署名した、「Craig WrightはSatoshi Nakamotoである」というメッセージを出して、少なくともSatoshi Nakamotoが当時使っていたPGP秘密鍵は所有しているという証明をしていない。

よくある詐欺師であり、目的はSatoshi Nakamotoを自称して出資を引き出すためではないかと言われている。

と、ここまでならよくある話だが、何故か今回の話にはおまけがある。bitcoin開発者であり、当時のSatoshi Nakamotoとも対話していて、暗号理論も理解していて証明の真贋も見分けることができるであろうGavinが、Craig Wrightは確かにSatoshi Nakamotoであるとコメントしているのだ。

このため、bitcoin開発者はGavinのコンピューターがハックされた可能性を考慮して、Gavinからコミット権限を取り消す措置をしている。まだGavinからハックされたというコメントはない。

Peter Todd on Twitter: "FYI, @gavinandresen's commit access just got removed - Core team members are concerned that he may have been hacked. https://t.co/7re7z16TeR"

ちなみに、Gavinがハックされたとか詐欺に加担しているのであれば、最も簡単に利益を上げる方法が取られていない。すなわち、「私はサトシだ。今から私の持っているbitcoinを全部売る」と宣言して、bitcoin取引市場に多大な売り注文がやってくると誤認させ、市場を混乱に陥れてbitcoinの価値を下げたところでbitcoinを買い占め、市場が落ち着いた後で売り払うという方法だ。

Satoshi Nakamotoが今更名乗りでても、それ自体は別に興味深くはない。本人の名声とか政治的迫害を別にすれば、Satoshi Nakamotoでなければできない設計や実装は今さら存在しない。ただし、Satoshi Nakamotoのウォレットに入っているbitcoinは莫大であり、市場に放出された場合、大混乱に陥るだろう。

こういった事情により、一概に詐欺とも言いがたい事態となっている。

コンピューター科学のアカデミック業界の残念な現状

mhoye on Twitter: "Extremely angry with the state of academic CS research right now. (1/n)"

MozillaでFirefoxのエンジニアリングコミュニティマネージャーであるMike Hoyeが、コンピューター科学におけるアカデミック研究の残念な現状に激怒している。

コンピューター科学のアカデミック研究の現状に激怒している。

MozillaがBugzillaを始めとした多数の情報を公開した結果として、多くの研究論文が書かれている。

我々はそのような研究には注目している。論文はじっくり読んでいるし、研究結果にしたがって今後の方向性も決めている。

しかし、我々は常に変化する世界に生きている。そのため、我々はデータをもとに結果を再検証して、仮定が正しいことを確認する。

ここで我々が行いたいことは、我々はある意思決定をある論文Xの結果をもとに行いたいのだが、その結果は最新のデータでも妥当であろうか? と言えることだ。

まともな世界では、そのような検証は以下の3ステップで行えるはずだ。

  • 論文著者のバージョン管理システムのレポジトリをクローン
  • 論文著者のプログラムを最新のデータに対して適用
  • 新しく生成されたグラフを見る

データはまだ仮説を支持するものであるか? 素晴らしい。この方向で進めよう。結果が変わった? 何故なのか考えてみよう。いずれにせよ。全員が満足する結果となる。

しかし、これは実現しない。なぜならば、コンピューター科学の研究者はコードもデータも公開しないからだ。奴らはLatexで整形したWordドキュメントをペイウォールに阻まれたPDFとして公開する。

奴らときたら、科学の原則である、「妥当性」とか「再現性」とか、中でも最も基本的な原則、「現実に即しているか」などは、クソ喰らえの姿勢だ。

人間が知識や学習結果を共有しないことの時代遅れがいかに時代遅れであるかを見てみようか。

ギリシア火薬の製法は失われた。ダマスカス鋼の製法は失われた。アンティキティラ島の機械は紀元前200年に失われ、同等の精度を持つ時計を再び作るには1500年代まで待たねばならなかった。

いいか。よく聞け。お前の未公開のコードと、お前の未検証のデータと、お前のペイウォールに阻まれた博士論文は、この輝かしい因習の一部であるのだぞ。

お前の目的とやらが、学士を得て卒業することなら、まあいいだろうよ。大抵の人間が望むことだ。だが、院にまで来てやることか?

お前の業績により世界をよりよい方向にインクリメントするためには、世界はお前の業績を読めなければならないのだぞ。

俺は結果の報告書など読みたくない。そんなのは、ワインを注文しているのに、赤っぽい色の液体について報じた新聞記事の切り抜きをFAXしてよこされるのと同じだ。

検証可能なデータと動くコードなしには、お前のコンピューター科学の博士論文の命題とやらは命題ではない。それは単に命題が存在するかもしれないという未検証の主張に過ぎない。

まとめると、俺は大変に失望している。もっと言うべきことはあるが、俺はこれから長年の研究とツールを再現するためのコードを書かねばならないのだ。

2016-05-01

超会議2016でドワンゴの運営スタッフとして焼きそばを焼いた感想

「江添さん、超会議で焼きそばを焼きませんか?」

恰幅のいい同僚が話しかけてきた。この男はドワンゴの料理研究部の部長である。

ドワンゴには福利厚生として同好会の設立を会社に申請でき、受理された同好会には部費も支給される。最も、会社が経費として出す金なので、いろいろと制約がある。例えば、飲食費用には使えない。料理研究部は調理器具や職場近くのキッチンのレンタルなどに部費を使っている。

「焼きそば? 少し前に話題になったアレをネタにするつもりですかな。しかし、もう旬は過ぎてしまったのではありませんかな」

「アレ」というのは他でもない。一時期、ドワンゴから退職が相次いだ時期があり、その時のある退職者に対して、退職理由がよくわからないとドワンゴの川上宣夫会長と伊藤直也氏がスシをつまみながらのインタビュー記事で書かれたことを受けて、元ドワンゴ社員のkuzuhaが、言及されている退職者というのは自分であろうと名乗りでて書いたブログ記事が発端で、一時期ドワンゴと焼きそばが炎上したアレだ。

僕は初回のニコニコ超会議が開催される前にこの話を聞いてさっさと退職したので実際には経験をしていませんが、ニコニコ超会議には社員が強制的に動員され、列の整理や焼きそば屋台などに従事させられました。正直に言ってソフトウェアエンジニアとして雇用した人間に焼きそばを焼かせるのは雇用契約違反なのではないかと思います。立て付けとしてはお客様の文化に触れる、本気で楽しんでくださっているお客様の姿をじかに見られる他にない機会であるという言い分です。

ドワンゴは大量退職に関する印象操作をやめろ - hiroki-uemuraのブログ

この炎上以降、Googleの検索欄に"ドワンゴ"と入力すると"焼きそば"がサジェストされ、"ドワンゴ 焼きそば"でググると、ドワンゴに対してネガティブな情報ばかりヒットするようになってしまった。

私がドワンゴに入社する以前の話であり、この当時の状況は人からの伝聞と風のうわさでしかわからないのだが、kuzuhaの記事には間違いがある。初代超会議のフードコートでドワンゴのエンジニアに課された料理は「焼きそば」ではなく「あんかけチャーハン」だったとのことだ。当時、ドワンゴの社内チャットでは、「会社は焼きそばではなくチャーハンですと訂正するIRを出すべきでは」などと無責任な冗談が飛んでいた。

ところでチャーハンといえば、ドワンゴには非公認のチャーハン部があり、名にし負うハンドルネームがチャーハンである部長の強力なリーダーシップのもと、毎週一度近所の中華料理屋に臨んで大盛りのチャーハンを食らうという活動をしているが、同部ではチャーハンの重量以外に、食べづらさ、胃もたれなどの完食への困難性への度合いを総合的に評価した、実質係数なる独自用語が飛び交っていて、1.2kgのチャーハンを完食した部員は尊敬され、中でも、1.2kg完食者の「来る者拒まず、去る者追う」という発言は名言としてSlack上で永久にPinされている。

それはさておき、同僚の話によれば、転んでも無料では起きない精神をもってこの炎上ネタを利用し、来る超会議2016ではエンジニアがフードコートで焼きそばを焼く企画があるという。そのために、フードコートに自らの意思でアサインされるエンジニアを募集しているという。

「いえね、やはりこういう企画は表に名前の出ている有名なエンジニアさんを採用したほうがいいと思いますし、焼きそばを焼くのも悪くありませんよ。なんでしたらフルタイムではなくパートタイムでも構いません。基本的には他のブースにアサインして途中2時間ほど抜けて焼きそばを焼くという形でのエンジニアの参加も予定しています。焼きそばを焼いていただけるのでしたら、特別に企画にかけあって希望のブースに優先的にアサインされるような配慮も致します。そしてですね。あまり言いふらしてほしくないのですが、休憩時間を通常1時間のところ、焼きそばブースは特別に2時間取ろうと予定しております」

「ほう、2時間?」

「はい、といいますのも。焼きそばを焼く鉄板はすごく熱くなるので、普段から仕事で焼きそばを焼く本職の人でも3,4時間ぐらいが限界だとか。我々素人に換算しますと、もっと短い時間で限界になるでしょうし、休憩時間も多めに必要なわけです」

巨体に似合わぬ高い声で、同僚は官僚的な勧誘文句を連発する。実際、この同僚はこの手の官僚的な細かい規則主義、手続き主義を極めて得意とする男であり、その才能は公私において遺憾なく発揮されている。今回のこの企画に割り当てられたのもその才能故だろう。この企画を遂行するにあたっては、外部のイベント設営会社、イベント運営会社、ましてや食品を扱うので消防、保健所などとの極めて役所的で煩雑なやり取りをしなければならないだろう。

そういえば、この同僚はドワンゴ社員の労働組合の代表でもあった。以前、ドワンゴとドワンゴ社員の労働組合との労使協定が危うく締結できなくなる危機があった。理由は会社と労働者との待遇の提示と要求の不一致という高尚なものではなく、単にドワンゴ社員がズボラで会社と労使協定を締結する際の労働組合の代表を選ぶ投票に参加しないというだけであった。

雇用者と被雇用者の労働組合との間で労使協定が締結できない場合、何が起こるのかというと、労働基準法の定める範囲外の労働が違法になる。読者の中には、労働基準法の範囲内の労働しか認められないのはとても良いことではないかと考える人もいるだろう。もしそう考えているとしたら、読者は労働基準法を読んだことがないだろうから、今すぐ読むべきである。

労使協定を結ばない労働基準法の定める範囲内の労働というのは、極めて制限が強い。一日の労働時間は最大8時間であり、1週に最大40時間である。残業や休日労働は認められない。緊急時のみ認められるが、事後に行政に残業や休日労働を行った旨を届け出なければならない。これは、夜中や休日にドワンゴの提供するサービスに障害が発生した場合でも、次の営業日の営業時間になるまで修正作業が行えないことを意味する。例えばニコニコ動画でそのような障害対応を行った場合、ユーザーが可及的速やかに離れてしまうだろう。Webサービスにおいては、障害はいつ何時でも即座に対応しなければ死活問題なのだ。また、定時が存在するようになり、全労働者は同じ時間に一斉に出社し、同じ時間帯に一斉に休憩を取り、同じ時間に一斉に退社することになる。

もちろん裁量労働制はなくなる。ドワンゴの特に極端な社員の一日では、早朝に就寝し、昼過ぎに起床して出社し、出社で疲れたので仕事など当然できるわけもなく、まず飯を食いに行き、16時から朝会と称する部署のメンバーが集まっての活動報告を行い、18時頃からそろそろ昼になってきたから本腰を入れて仕事するかなどとうそぶきながらようやく活動を始める。そんな裁量労働制もなくなってしまう。

事態は極めて逼迫しているというのにドワンゴの労働者はどこ吹く風といった時、この同僚は各個撃破の地道な根回しを行って何とか票を集めて従業員代表になり、労使協定を締結させ、ドワンゴの裁量労働制を維持し、ひいてはドワンゴの労働基準法違反を回避させた男である。

かかる経緯で、筆者は超会議2016で焼きそばを焼くことになった。

なお、フタを開けてみると、この同僚の根回しが強力すぎたためか、はた、祭り好きの人間が多かったのか、焼きそばブースへのアサインを希望するドワンゴのエンジニアが応募多数に付きお断りする事態が発生していたらしい。

そもそも元をたどればこの焼きそば企画の発端は、kuzuhaの上記のブログ記事なのだが、この企画を社内で提案した人間は、実は途中で退職しているそうだ。そのため、同僚は退職者の企画を引き継いだ形になる。この規格の経緯を考えるとなんとも形容しがたい何らかの違和感のある不思議な気分になる。

今回の焼きそば企画では、"ドワンゴ 焼きそば"でググった時の検索結果のネガティブな結果を変えようという意図もあるらしい。なんと、物理SEOというわけか。当日はよりシュールなネタとして、特別なスタッフカードを装着することとなった。そのスタッフカードには、顔写真と名前と「私は自らの希望で焼きそば担当になりました。」とそらぞらしく書いてある。

この同僚の苦労はともかく、焼きそばブースにアサインされただけのエンジニアは、前日のリハーサルと当日の本番に労働するだけであった。

リハーサルの日は雨が降っていた。焼きそばブースの現地でのリハーサル開始として指定された時刻は16時であった。これは朝が弱いエンジニアへの配慮である。というのは方便で、実際には、消防と保健所の検査が終わるまで鉄板に火を入れることができず、調理実習ができないためである。筆者は大幅に寝坊をして現地の到着が15時半になったが、ブースには誰もいなかった。しかたがないのでニコニコ頂神社の壁を登っていた。グレードは8級以下に感じた。今回のビレイは派遣されたプロが担当するそうだ。焼きそばもプロが派遣されているという。今回、ボードゲームがないのは残念だ。

16時になったのでフードコートに戻ってみるが、やはり誰もいない。まさかと思って控室に行くと、全員いた。エンジニア達は爪楊枝にN高のシールをはって食べ物に指す旗を作るという地味な単調作業をしていた。エンジニアの人件費を考えると、この旗は相当高いに違いない。しかし不思議だ。プログラマーにとって単調作業は忌避すべきものであるが、我々はたまに単調作業の魅力に惹かれてしまう。これは一体どういうわけだろう。

その後、待てども待てども検査はなかなか始まらず、とうとう前日は調理実習が何もできないまま解散した。筆者はその足で、海浜幕張にあるPEKIPEKIというクライミングジムに行った。去年登れなかった課題がまだ残っており、しかも登ることができた。また、クライミングマシーンのExtream設定をクリアした。一年たって上達を感じる。

さて、当日、ようやく鉄板に火を入れることができるようになったので、焼きそばのプロの実演を見た。出来上がったカレー焼きそばを食べたが・・・とても粉っぽくて食べられたものではない。どうやらレシピに記載されたカレー粉の分量が多すぎるようだ。調整してまともな味にした。

今回の焼きそばには、ドワンゴのニコニコ動画チームのK1の設計したカレー焼きそば、ニコニコ静画チームのまさらっきが設計したイカスミ焼きそば、ニコニコ生放送チームのK2が設計したピザ焼きそばの3種類の焼きそばが用意されている。カレー焼きそばには、カレー粉が入っている。イカスミ焼きそばにはイカスミが入っている。ピザ焼きそばは肉の代わりにシーフードミックスで、トマトピューレを入れた上で、上からパルメザンチーズをかける。

今回、焼きそばブースにアサインされたレシピの設計者はまさらっきだけだ。試食の結果、イカスミ焼きそばが一番美味しかった。まさらっきはグルメをわかっているものと見える。問題は、唇と歯が黒くなってしまうバグが発覚したことだ。

ピザ焼きそばは、極めて粘着質で、パック詰めが難しいという運用上の問題が発覚した。

今回は、オープンソース焼きそばということで、レシピがGitHubで公開されている。ライセンスは煮るなり焼くなり好きにしろライセンスだそうだ。

dwango/yakisoba-sauce: Open source recipe of yakisoba-sauces for chokaigi 2016

とはいえ、物理的存在に自由不自由の区別は存在しないのだが。

売上としては、カレー焼きそばが最も多く売れ、イカスミ焼きそばが最も売れないという結果になった。

価格は800円だそうだ。焼きそばにしてはやたらと高い。イベント価格とは言えあまりの高い値段に罪悪感がある。とはいえ、後述する焼きそばを焼く労働の辛さを考えると、妥当ではないかと思えるようになってしまった。

さて、肝心の焼きそばを焼く労働の苛酷さについて述べる前に、もうひとつ書いておくことがある。エンジニアとしての演出だ。

せっかくだから鉄板の温度を計測して表示してはどうか、また、焼きそばのそれぞれの売上もカウントして表示してはどうかと、アサインされたエンジニアの一人が主張し、実際にそのための装置を作った。その実装が笑えるほど面白かったので紹介する。

まず、鉄板の温度の計測方法であるが、接触するセンサーは衛生上問題があるので使えない。赤外線のセンサーを用いることにした。そのため、中国製の赤外線センサーを買った。さて、赤外線センサーを分解して、中身だけ取り出し、温度情報を取得すればいい。ドワンゴの電子工作部の部員に依頼したが、温度情報を取り出す方法がわからない。唯一測定できる信号線は、液晶ディスプレイにつながっているもので、0.1mm以下の線が何本もあり、これを手作業でハンダ付けして一本一本取り出すのは極めて困難なのでやりたくないとのことであった。したがって、計測装置は極めて笑える富豪的な実装になった。

すなわち、温度を表示する液晶ディスプレイをカメラで撮影し、画像認識して温度を得るというものである。このためにカメラとRaspberry Piが用いられた。

しかし、残念ながら、当日の表示に温度表示がつくことはなかった。理由はわからないが、鉄板の温度が60度ぐらいに表示されてしまうのだ。表面に塗った油が煙を出すような状態でその温度は明らかにおかしい。この赤外線温度計は確か500度まで対応していたはずだがなぜだろうか。あるエンジニアは、鉄板の温度が高すぎてオーバーフローしたのではないかという説を出した。温度が9bitで管理されていた場合、512度以上になるとオーバーフローする。しかし、9bitなどという中途半端なビット数で管理するだろうか。「いや、ビット数を増やすと信号線が増えて回路も増えて手間もコストもかかる。組み込みならよくあること」と言っていた。

しかし、冷静に考えると鉄が600度になると赤黒く発光するはずであり、そんなに高温になるだろうか。

「もう乱数でも表示しておけばいいんじゃないか。どうせ気づかないぜ」などという冗談まで飛び出した。

さて、焼きそばの種類ごとの売上をカウントするボタンはうまく機能した。ボタンは、100円ショップで売っていそうな透明なタッパーを容器として、ボタンを3つ取り付けてある。容器の中には基板が入っていた。

「それはArduinoかな」
「ラズパイですよ」
「ラズパイ? たかがボタン3つの制御のために?」
「何言ってるんですか。富豪的プログラミングって言葉知ってます?」
「たかがボタン3つの制御のために一昔前のスマフォに組み込まれていたARM CPUと100MB以上のメモリが必要なのか?」
「今はIoTの時代ですよ。ボタンもsshdぐらいお話できないと不便ですよ」
「ボタンの制御にH.264をデコードできるGPUを詰んだMinecraftもインストールされているコンピューターが必要なのか?」
「それは・・・うーむ」

3つボタンの容器は2つあったので、このシステムにはRaspberry Piが3つも使用されていることになる。なお、実際にはログの集計に使うソフトウェアにメモリが16GB以上必要でMacBookまで持ち出すはめになった。富豪的プログラミングにもほどがある。

さて、そろそろ肝心の焼きそばを焼く労働について述べねばなるまい。当日のフードコート奥には、3枚の鉄板が設置された。一枚の鉄板で一度に40人前(パック詰めのときには、目分量でかなり多めに詰めたので、実際にはもっと少ないだろうが)の焼きそばを焼くことができる。カレー焼きそばの材料は、豚こま切れ肉1.5kg、キャベツ1.5kg、カレー粉適量、もやし2kg、麺4kgである。

このスケールでは、焼きそばの調理は重労働である。まず鉄板が熱い。読者は何をいまさらと思われるかもしれないが、やはり鉄板は熱い。焼きそばをかき混ぜるには、ヘラを動かすために鉄板の上に手をかざさなければならず、極めてあつい。そして材料は重い。まさか焼きそばの麺があれほど重たいものだとは思わなかった。

そして、焼きそばは休みなしにひっきりなしに焼かねばならなかった。というのも、作ったそばから売れて在庫がなくなっていくからだ。会場には焼きそばの保温器が設営されていたが、果たして必要だったのだろうか。

フードコートのボトルネックは注文を聞いて現金をやり取りする部分で、そのためにスループットが上がらず行列ができてしまうのだが、たとえそのボトルネックが解消されたところで、焼きそばの生産速度はすでに追いつくのも難しいほど限界であった。

また、パック詰めも焼きそばの調理ほど肉体疲労はないが、地味に手間のかかる面倒な作業であった。トングで焼きそばを掴んで、パックにいれ、輪ゴムをかけなければならないのだ。カレー焼きそばとイカスミ焼きそばは普通の焼きそばなのだが、ピザ焼きそばはトマトピューレを入れるため、やたらと粘着質な出来上がりになってしまい、トングで掴んでパックに移す作業が極めて面倒であった。

興味深いのは、フードコートの売れ行きである。行列ができていると呼び込まずともどんどん人が来るのだが、行列ができていないとまるで人が来ない。これは一体どういう群集心理が働いているのだろうか。先の単調作業への魅力といい、なんだかやたらと心理学への興味が深まる。

こうして、過酷な2日間に渡る焼きそばブースでの業務が終わった。始まる前は、「ところで、ちゃんと焼きそばは食べられるんでしょうね? 目の前で焼いているのに食べられないとか拷問ですよ」などと言っていたエンジニアは、あまり焼きそばを食べていた気配がない。

超会議のフードコートで焼きそばを売って実感したこととしては、希望せずに強制的にフードコートに配属されたら、少なくとも転職を考えるぐらい疲労するということだ。

だいぶ披露したとはいえ、ボルダリングは別腹だ。超会議2日目の後は海浜幕張のクライミングジム、PEKIPKEIには行った。前日リハーサルで落とせなかった課題が落とせたので満足して帰った。来年もまたこよう。

写真

ドワンゴ広告

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2016-04-23

Ubuntu 16.04にアップグレードした

Ubuntu 16.04にアップグレードした。今回はかなり問題だらけだった。

まず、アップグレードが正常に終わらなかった。古いパッケージを削除する途中で、hicolor-icon-themeのインストールスクリプトが正常に終了しなかったとのメッセージが表示された。同じ問題が報告されているようだ。

Bug #1571139 “package hicolor-icon-theme 0.15-0ubuntu1 failed to...” : Bugs : hicolor-icon-theme package : Ubuntu

他にも、Localesのインストールスクリプトが正常に終了しなかったというメッセージも表示された。

そして、"E: mkinitramfs failure cpio 141 gzip 1"と表示されたまま画面が完全に固まってしまった。入力を一切受け付けず、端末に切り替えることもできなければ、SysRqもきかない。30分ほど待っても何も起こらないので、仕方なく電源を落とすことにした。

さて、ブートしてみるとGrub2のシェルが表示される。さて、ブートローダーの問題なのだろうか。

とりあえずUbuntu 16.04のISOを落としてブータブルUSBメモリを作成してブートしてみる。あっさりとブートできた。どうやらLive USBではなくて普通にUSBメモリのブートローダーだけを使ってラップトップにインストールしたUbuntuが起動したらしい。ログイン画面は16.04になっている。

それではgrubのインストールだけやり直せばいいのだろうか。とりあえず様子を見てみようとGUIのアップデートプログラムを起動してみたところ、何やら大量のパッケージを確認もなくアップデートして再起動を促された。はて、まだ終わっていなかったのだろうか。

再起動してみるとこれまた普通に使える。古いパッケージ、特に古いLinuxカーネルのパッケージが大量に残っているので、apt-get autoremoveで除去した。

さて、今回はGCCが5.3、Clangが3.8になっている。ただし、libc++とlibc++abiに問題があるようだ。まず、libc++abi-devは、/usr/include/libcxxabi/下にインストールされるのだが、このディレクトリへのパスが通っていない。しかし、なぜか/usr/include/c++/v1/cxxabi.hだけは存在するので/usr/include/libcxxabi/__cxxabi_config.hを#includeしようとして見つからないエラーが出る。

仕方がないので、Clangのオプションに-I/usr/include/libcxxabi/を渡してパスを追加した。

もうひとつ、どうもlibc++ 3.7のstd::stringの実装に問題があるようだ。/usr/include/c++/v1/stringの1326-1331行は以下のようになっているが、

    _LIBCPP_INLINE_VISIBILITY explicit basic_string(const allocator_type& __a)
#if _LIBCPP_STD_VER <= 14
        _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value);
#else
        _NOEXCEPT;
#endif

1936-1940行は以下のようになっており


template <class _CharT, class _Traits, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY
basic_string<_CharT, _Traits, _Allocator>::basic_string(const allocator_type& __a)
    : __r_(__a)
{

basic_stringのコンストラクターの宣言にあったnoexceptが定義には存在せず、宣言の不一致でエラーになる。

パッケージ管理されているファイルを弄りたくはないので、とりあえず別のディレクトリにコピーしてコードを修正し、そのディレクトリへのパスを追加することで修正した。次のUbuntuのアップグレードの時まで忘れずに覚えていなければならない。

変更自体は、noexceptを付けるだけだ。


~/Documents/src/cpp/include$ diff -u /usr/include/c++/v1/string ./string 
--- /usr/include/c++/v1/string 2015-09-06 19:01:16.000000000 +0900
+++ ./string 2016-04-23 18:59:51.848010811 +0900
@@ -1936,6 +1936,11 @@
 template <class _CharT, class _Traits, class _Allocator>
 inline _LIBCPP_INLINE_VISIBILITY
 basic_string<_CharT, _Traits, _Allocator>::basic_string(const allocator_type& __a)
+#if _LIBCPP_STD_VER <= 14
+        _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
+#else
+        _NOEXCEPT
+#endif
     : __r_(__a)
 {
 #if _LIBCPP_DEBUG_LEVEL >= 2

2016-04-20

江添ボドゲ会@5月

以下の通り5月7日に自宅でボドゲ会を開催するのでお集まりください。

江添ボドゲ会@5月 - connpass

今回もカレーでも作ろうと思う。

curl | bashをサーバーサイドで判定する方法

Detecting the use of "curl | bash" server side | Application Security

ソフトウェアをインストールするとき、シェルスクリプトを実行するのはよくあることだ。しかし、そのシェルスクリプトが他人のリモートサーバーでホストされていた場合、curl | bashするのは危険だ。まともなユーザーは、curl | bashする前に、まず中身を確認して、悪意がないことを確かめるものだ。

しかしもし、サーバー側がwgetやcurlといったツールとブラウザーを判定して、それぞれ別のコードを返した場合どうか。ユーザーが見るのは囮のシェルスクリプトだ。

しかし、それではcurlやwgetを利用してシェルスクリプトをダウンロードするユーザーは騙せない。しかしもし、curlとcurl | bashを判定することができたらどうか。実は、できるのだ。

curlとcurl | bashを判定する方法は、bashの処理にある。bashはコードを順次実行していく。コードの実行中はパイプからの読み出しが滞る。ネットワークとパイプのバッファーが全て埋まってしまえば、サーバーからのデータのダウンロードは中断する。したがって、コードの冒頭にsleepを置いて、バッファーを埋めるために無害で表示されないnull文字を送りつける。ダウンロードが途中で中断すれば、curlはパイプを経由してbashに出力しているのだと判断できる。

curl | bashを判定するサーバーを判定する方法

では、ユーザーはどうやってcurl | bashを判定するサーバーを判定すればいいのだろうか。判定が上に述べたような簡単なディレイで行われているならば、そういうディレイを発生させてやればよい。

curl https://example.com/setup.bash | (sleep 3; cat)

しかし、curl | bashを判定する方法はその他にもあるし、ディレイを複数使って判定することもできるので、確実に判定はできない。信頼できないデータはまずローカルのファイルに落として、中身を検証してから、ローカルのファイルをbashで実行すべきだ。

2016-04-12

Brian Kernighanがプログラミング言語Goの組版に使ったのはなんとtroff

Ramakrishnan Muthukrishnan - Brian Kernighan on the typesetting of "The Go Programming Language" book

L&RのKでありAWKのKでもあるBrian KernighanとAlan Donovanの執筆したThe Go Programming Language(邦訳は丸善からプログラミング言語Goとして6月15日に出版される予定)の組版には、Troff(具体的にはgroff)が使われたそうだ。同本の組版に感心した人間が、Brian Kernighanに組版について以下のようなメールを送った。

親愛なるKernighan教授へ

プログラミング言語Goの本のとても組版が美しい。個人的な感想では、LaTexでクマれたものより美しいように思われる。

同本の執筆手順と本の組版について詳しい説明を願いたい。著作権の項目に使ったツールについては書かれているが。

謝意

Ramakrishnanより

その結果、Kernighanから以下のような返事が返ってきたという。

Ramakrishnanへ

組版について褒めていただきありがたい。組版の大半は単にtroff(実際にはgroff)と-msマクロパッケージで行われた。Latexも少し試したが、私もAlanもその出力をさらに編集する気になれなかったし、Latexを使って組版するのは不可能だと思っている。Troffは私のよく知る昔ながらのツールで、汚く例外的な挙動も多いが、文字を組みたい場所に置いてくれることは確かだ。

入力はXMLで、見出し、パラグラフ、索引、プログラムコード辺、簡単な表などを25個ぐらいのタグで表現している。Goのプログラムでこれを変換した。素早く画面上で見るためと、もし機会があればe-book版のためにHTMLにするのと、印刷のためにtroffにする。XMLを使うのは執筆時にすこし面倒だったが、エラーチェックが便利だった。

細かい修正のために多数のgoプログラムとスクリプトを書いた。例えばすべてのページが同じ高さになるようにtroffの出力を書き換えるとか。生成されたpostscriptにも印刷所の印をいれるために手を入れている。

フォントはAlanの選択だ。適切なフォントを見つけて適切なサイズと見た目にするのにかなり労力を使った。いくつかのアジア圏の文字はうまく扱うのが難しかった。troffは全角Unicode文字を適切に扱えないので、テキストを書きかえてごまかした部分がいくつかある。

図はぜんぶAlanの仕事だった。Googleのドローイングプログラムを使った。pic[画像?、ソフトウェアの名称?]を少し試してみたが、便利ではなかったし、HTMLで扱うためには面倒だった。上付き文字以上の組版が必要な数式は使わなかったし、表は簡素なものだった。eqnとtblぐらいあれば足りるが、HTMLでは扱っていない。

もう少しドキュメントを整備してツールも公開すべきなのだろうが、ほとんどの読者は君のように過程に興味はない。もうひとつの問題として、始めた当初は綺麗で筋の通った設計だったのに、結果として過程は炎上したし、やたら複雑なmakefileを書く必要に迫られた。

メールをありがとう

Brian

ちなみに、GNUのtroff互換実装であるgroffは、ここ10年ほどメンテナーがいなくて保守されていない。

ドワンゴ広告

アスキードワンゴ編集部はlatexを使っているそうだ。ちなみに、日本の殆どの出版社はInDesignで組版をしている。それも、編集者はInDesignを直接触らない。InDesignを触るのは印刷所の人間だ。ある編集者などは、「自分はコンピューターを触らない」と誇らしげに言うそうだ。そういう人は、紙に直接赤鉛筆などで組版の指示をして印刷所に投げる。

私からすると、GUIの組版ツールを使うのは同じ作業を何度も繰り返さなければならず極めて効率が悪いと思うのだが、印刷業界は不思議なものだ。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2016-04-06

Vim風のテキストエディターvis

martanne/vis: a vim like text editor

1%のコードで80%のVimの機能を目標に開発されているVim風のテキストエディター。

GUIとマウスのサポートがない以外は興味深い。

2016-04-04

アメリカ合衆国政府が公金を投じて開発されたソフトウェアは自由ソフトウェアにする法案を公開

https://sourcecode.cio.gov/SourceCodePolicy.pdf

Matthias Kirschner's Web log • US government commits to publish publicly financed software under Free Software licenses

アメリカ合衆国政府が、公金を投じて開発したソフトウェアは公共の財産であるのでデフォルトで自由なソフトウェアにする法案を公開している。

これは当然の話で、日本でも速やかに行うべきである。日本国政府が公金を投じて開発させるソフトウェアは自由なソフトウェアとすべきであって、プロプライエタリなソフトウェアの納品は禁止されるべきである。当然、WindowsやMac OS XなどのOSは国家に納品するには適さないOSである。

物理法則が同じかつ1900年ぐらいの科学レベルの異世界にタイムリープした現代人は現代の進んだ科学知識を活用して異世界チート主人公系ラノベのごとくになれるか

いかのような問題提起を考察したい。

なるほど、とても興味深い設定である。これについてできる限り考察してみよう。

異世界チート主人公系ラノベというジャンルがある。一個の現代人の主人公が常識や物理法則の違う異世界に飛ばされて、世界の差異を利用して有意に立つという筋書きの物語である。主人公はどこにでもいる一般人、それも無職とか低賃金有期雇用者とか、社会的弱者であることも多い。

ここでは2016年の人間が1900年に飛ばされて、科学知識の差を利用して活躍する筋書きである。活躍する上で、理解がクソなために科学の発展を阻害するというオチまで付けなければならない。

しかし、実証主義として考えれば、実際に観測可能な現象と一致する結論は、たとえ仮説が間違っていたとしても、科学の発展にはもたらす害悪よりも利益のほうが大きいのではないか。たとえばニュートンは筋金入りの神秘主義者で、現代の常識から考えれば非科学と迷信に凝り固まった人間ではあるが、ニュートンは確実に科学の発展に寄与している。

さて、まず1900年の科学水準について確かめてみよう。ひとまず1900年の日本語版のWikipediaを確認してみる。

1900年 - Wikipedia

  • 1月2日 - 初の電気バスがニューヨーク市で開業
  • 4月11日 - 米海軍が初の潜水艦ホーランド (潜水艦) を取得(就役10月12日)
  • 5月1日 - 東京電気鉄道(後の都電)設立
  • 5月29日 - 米国オーチス・エレベーター社がエスカレーターを商標登録
  • 7月2日 - ツェッペリン(水素ガスによる飛行船)が初飛行(ボーデン湖)
  • 7月19日 - パリ万国博覧会会期中にパリの地下鉄が開通
  • 8月8日 - 国際数学者会議にて、ヒルベルトの23の問題のうちの10題が公開される
  • 9月11日 - 日本初の自動公衆電話が東京の新橋駅と上野駅、熊本市内に設置

後にガンマ線と名付けられる放射線をポール・ヴィラールが観測したのも1900年である。

元素の発見もかなり進んでいて、放射性の元素もかなり発見されていたし、非放射性の元素はほとんど発見されていたし、未発見のものも発見は時間の問題であった。

なるほど、1900年の科学水準というのは、すでに電気バス、潜水艦、電車、エスカレーター、飛行船、地下鉄、公衆電話が存在していたどころか実用化もされていて、かつ数学もだいぶ進んでいたし、放射線の理解も進んでいたし、元素も安定したものはほとんど発見されていた。

さて、困った。1900年は思ったよりも科学水準が高い。例えば筆者程度の人間が1900年に飛ばされても、現代の科学知識を用いてチート主人公になることはできない。

ひとつ考えられるのは、この頃の一般大衆の科学水準はまだ低く、宗教や迷信が強く信じられていて、現代の進んだ心理学を元に大胆に振る舞えば、新興宗教とかネットワークビジネスの開祖としてそれなりに活躍できるのかもしれないし、「まっとうな科学の発展を阻害」するというもうひとつの目的も達成できるのかもしれないが、そういうことができる人間は現代でも新興宗教とかネットワークビジネスの開祖になれるだろう。そして、後述する言語の違いにより、この方法によるチート主人公となるのも難しいのである。

2016年と1900年で大きく違うのは、言語と人権である。この差は、おそらく主人公にはチートどころかハンディキャップになるであろう。

1900年の日本語は、現代と発音が異なる。2016年の主人公が音声学と日本の方言の考古学を専攻していて、かつ発音の実践を積んでいない限り、話し言葉による日常会話は困難であろう。1900年の価値基準で判断すると、主人公は実質的に失語症になってしまう。

書き言葉の差はもっと難しい。主人公が古文漢文に加えて草書体を相当に深く学んでいない限り、1900年の日本社会では文盲の扱いを受ける。当時は、ラテン語の読み書きができないものは論文すら読めずに、科学の世界に足を踏み入れることさえできない。文章で科学知識を伝えられなければ、いかに2016年の第一線の科学知識を持っていいようと無力である。英語はまだ世界共通語の地位を確立しておらず、ドイツ語やフランス語も科学の世界ではまだ強い力を持っていた。

たとえ筆者が2016年の最新の科学技術の知識を持っていて1900年において文書で書き残したとしても、その内容の解読には長い年月がかかり、功績が理解されるのは主人公の死後50年以上かかるであろうし、その頃には主人公の書き残した科学技術は独立して発見されているであろうから、社会への影響は、一部の歴史学者の混乱を除いて、良くも悪くも与えないだろう。

1900年においては、人権はかなり軽視されていた。たとえば1900年の1月23日には、光明寺村女工焼死事件が起こっている。これは織物工場で働く労働者の寄宿所が火事になったのだが、当時の慣習として、労働者の逃亡を防止するために、寄宿所の窓は鉄格子の上、ドアが施錠されていたから、労働者は逃げられなかったのだ。

リンカーンによる奴隷解放宣言は1862年であったが、アメリカ合衆国において黒人が選挙権を実際に行使できるようになるのは1971年からであった。

これを考えると、1900年に飛ばされた主人公は意思疎通ができず知的障害とみなされ、日銭を稼ぐために奴隷のような劣悪な労働環境に身をやつすことになるだろうと予想できる。

考察結果として、1900年の科学水準はかなり高く、2016年の一般人程度があやふやな科学知識を振りかざした程度では、異世界召喚系ラノベのような活躍はできないことが判明した。

2016-04-01

C++標準化委員会の文書: P0200R0-P0209R0

P0200R0: A Proposal to Add Y Combinator to the Standard Library

lambda式で再帰できるようにするY Combinbatorライブラリの提案。

int main()
{
    auto gcd = std:y_combinator( []( auto gcd, int a, int b ) -> int
        {
            return b == 0 ? a : gcd( b, a % b ) ;
        } ) ;

    std::cout << gcd( 20, 30 ) << std::endl ;
}

実装例

template < typename Fun >
class y_combinator_result
{
    Fun f ;
public :
    template < typename T >
    explicit y_combinator_result( T && fun )
        : f( std::forward<T>(fun) )
    { }

    template < typename ... Args >
    decltype(auto)
    operator () ( Args && ... args )
    {
        return f( std::ref(*this), std::forward<Args>(args)... ) ;
    }
} ;

template < typename Fun >
y_combinator_result<std::decay_t<Fun>> y_combinator( Fun && fun )
{
    return y_combinator_result<std::decay_t<Fun>>(std::forward<Fun>(fun)) ;
}

[PDF] O0201R0: A cloning pointer-class for C++

コピー時にポインターの参照先をディープコピーするclone_ptrの提案。

int main()
{
    auto p1 = std::make_clone_ptr<int>(42) ;
    auto p2 = p1 ;
}

これは、以下のようなコードと同じ意味になる。

int * p1 = new int( 42 ) ;
int * p2 = new int( *p1 ) ;
delete p2 ;
delete p1 ;

また、clone_ptrは初期化時に渡されたmost derived typeによるポリモーフィックな型のディープコピーや破棄が正しく行える。


struct Base
{
    virtual void f() = 0 ;
    ~Base() { } // virtualデストラクターではない
} ;
struct Derived
{
    void f() override { }
    Derived() { }
} ;

// 実行時型
clone_ptr<Base> p1( new Derived() ) ;
auto p2 = p1 ;

// ディープコピーが行われる
assert( p1.get() != p2.get() ) ;
// Baseではなく実行時の型であるDerivedとしてコピーが行われる
assert( dynamic_cast< Derived * >(p2.get() != nullptr )

// p1, p2の破棄では、Derivedのデストラクターが呼ばれる

shared_ptrと同じだ。

コピー時にディープコピーを行うクラスのデータメンバーとして生のポインターの代わりに安全に使えるので入るべきだ。

A Proposal to Add Constexpr Modifiers to Functions in <algorithm> and <cstring> Headers

<algorithm>と<cstring>をconstexpr対応にする提案。イテレーターのconstexpr化は別の提案で行う。

<algorithm>をconstexpr化する提案。多くのアルゴリズムは<cstring>に依存しているので、<cstring>もconstexpr化する。

std::memcpyやstd::memmoveは、void *型の引数を取るので、本来constexpr化できないのだが、constexpr化しないとライブラリ実装はcompiler intrinsicsを使うだけなので、constexpr化する。

P0203R0: Considerations for the design of expressive portable SIMD vectors

SIMD型の提供に関する考察。

P0205R0: Allow Seeding Random Number Engines with std::random_device

乱数エンジンをrandom_deviceで初期化できるようにする提案。

現状では、random_deviceからビット列を手動で取り出して乱数エンジンに食わせてやらなければならないが、乱数エンジンの内部状態が何ビットなのか得る方法がないため、適切な初期化が移植性の高い方法で書けない。

これは当然入るべきだし、そもそも最初から入っているべき機能だ。

P0206R0: Discussion about std::thread and RAII

threadのデストラクターが実装された時に、threadがjoinableであると、terminateが呼ばれる。これは様々な問題を引き起こす。しかし一方で、この挙動のほうが好ましい場合もある。

この文書は、threadのデストラクターは自動的にjoinを呼ぶ変更か、自動的にjoinを呼ぶ別のthread型を追加する文面案を提示している。

既存のコードの挙動を変えないために別の型にすべきだろう。

P0207R0: Ruminations on lambda captures

lambada式で値によるデフォルトキャプチャー[=]が使われた場合、クラスのメンバーはthisポインター経由ではなく、値によるキャプチャーになるように挙動を変更するとどうなるかを考察。

この文書は、既存の挙動は変えないことを推奨している。

筆者は変えるべきだと思う。

[PDF] P0208R0: Copy-Swap Helper

強い例外安全を実現するために、まずオブジェクトをコピーして改変し、改変が例外を投げなければswapする。改変が例外を投げた場合元のオブジェクトは変更されないという処理を行うヘルパー関数の追加。

文面案のcopy_swap_helperの宣言が間違っている気がする。

[PDF] P0209R0: make_from_tuple: apply for construction

tupleの各要素をコンストラクターに渡してオブジェクトを構築してくれるmake_from_tupleの提案。

以下のように使う。

struct X
{
    X( int, double, std::string ) ;
} ;

auto t = std::make_tuple( 1, 2.0, std::string("3") ) ;

auto x = std::make_from_tuple<X>( t ) ;
// 以下と同じ
// auto x = X( get<0>(t), get<1>(t), get<2>(t) ) ;

すでにtupleの各要素を関数の引数に渡してくれるapplyがあるが、

void f( int, double, std::string ) ;

std::apply( t, f ) ;

make_from_tupleはそのオブジェクト構築版と言える。

同様にして、placement newしてくれるuninitialized_construct_from_tupleがある。

alignas(X) char buf[sizeof(X)] ;
X * ptr = std::uninitialized_construct_from_tuple<X>( buf, t ) ;

実装は以下のようになる。

template < typename T, typename Tuple, std::size_t ... I >
T make_from_tuple_impl( Tuple && tuple, std::index_sequence<I ... >  )
{
    return T( std::get<I>( std::forward<Tuple>(tuple) )... ) ;
} ;

template < typename T, typename Tuple >
T make_from_tuple( Tuple && tuple )
{
    return make_from_tuple_impl<T>(
        std::forward<Tuple>(tuple),
        std::make_index_sequence<
            std::tuple_size_v< std::decay_t<Tuple> >
            >()
        ) ;
}

ドワンゴ広告

Ubuntu On Windowsでドワンゴ社内の支給PCの勢力図が塗り替えられそうな気がするが、いい加減に支給PCのWindowsぐらい最新にするべきだと思うしGNU/LinuxをOSの候補に加えるべきだ。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

Linuxにleftpad()というシステムコールを入れる提案

LKML: Richard Weinberger: New syscall: leftpad()

Linuxカーネルに興味深い日付でleftpad()というシステムコールが提案されている。

最近のnode.js業界の事件を振り返るに、leftpadのような基本的なアルゴリズムの依存はソフトウェアを脆弱にすることが判明した。ledpad[原文ママ]を提供するnode.jsパッケージが消失し、多くのソフトウェアが動かなくなった。

この事件に注目すると、node.jsベースのソフトウェアがLinuxの「ユーザースペースは壊さない」原則に将来的に頼ることができるので、このような機能を提供するのはカーネルの役目であるという結論に至った。

glibcとAndoid[原文ママ]のbionicは、早急にこの新しいシステムコールのラッパー関数を提供してくれることを望む。

leftpadをカーネルに入れたのはLinuxの安定したABIという理由だけではなく、パフォーマンス上の理由もある。

ご存知のように、カーネルでは、すべてが高速でかつ優れている。leftpadには大勢の利用者がいるので、可能な限り高速でなければならない。また、この新しいシステムコールはleft-pad.ioのようなサービスをより高速に安定して提供するのにも使うことができる。leftpad()システムコールが十分に利用された場合、npm()という、カーネルモジュールがnode.jsでよく使う新しい機能を登録できる、ioctl()のように機能する汎用的なシステムコールを付け加えるのも手だ。そのような機能としては、is_array()やis_int()が挙げられる。

[leftpad()システムコールをLinuxカーネルに追加するパッチ]

これを受けて、以下のような返信が行われている。

動いた。このシステムコールの重要性は筆舌に尽くしがたい。提案と実装してくれてありがたい。

パッチを提出する時はcheckpatch.plにかけてくれ。

これはよさそうだが、他のarchに対応させた上で、適切なメンテナーをCCに加える必要があるな。

これはよさそうだが、可能な限り高速にするために、無駄な範囲外チェックなどの分岐は全部除去したほうがよいし、ユーザーのメモリーに直接書き込むことで、無駄なcopy_from/copy_toを除去すべきだ。これにより、遅いkmallocも除去できる。

文章には注意を払ってくれ[ledpadとandoidのtypoの指摘]

参考: 本の虫: npmからkikとその他諸々が消されたまとめ

2016-03-30

C++標準化委員会の文書: P0190R0-P0199R0

[PDF] P0190R0: Proposal for New memory order consume Definition

memory_order_consumeの定義を変更する提案。RCUだけではなくGCなどにも利用できるようにする。Linuxカーネルでも使えるようにする。

[PDF] P0192R0: Adding Fundamental Type for Short Float

32bit以下のサイズのshort float型の追加の提案。

16bit浮動小数点数は機械学習や画像処理の分野で広く使われるようになっている。IEEE 754-2008では2進数16bitのフォーマットが定義されている。今のARMはネイティブにサポートしている。IntelのCPUでもサポートする計画がある。GPUでは、OpenGLが16bit浮動小数点数を規定している。OpenEXRではfloatの半分のサイズの浮動小数点数を組込型同様に扱えるライブラリがある。nVidiaのCUDAでは16bit浮動小数点数行列があるが、C++規格に存在しないために独自規格になっている。GCCはIEEEやARMのサポートのために__fp16型がある。LLVMにもhalf型がある。

16bit浮動小数点数型は現実の需要があるので、C++標準は早急に取り入れるべきであるとする。

型はshort floatで、浮動小数点数リテラルのサフィックスはsもしくはSだ。


short float s1 = 1.0s ;
short float s2 = 1.0S ;

これは早く入るべきだ。

P0193R0: Where is Vectorization in C++‽

C++に手動のベクトル処理を淹れる方法についての考察。ライブラリベースで入れることを検討している。具体的な話はあまりない。

[PDF] P0194R0: Static reflection (revision 4)

静的リフレクション機能の提案。

この提案では、宣言に何らかの演算子を適用すると、メタオブジェクトという型が生成され、その型を用意された特別なtraitsに渡すことで、名前や型などの詳しい情報を得ることができる。

P0195R0: Modernizing using-declarations

using宣言をpack展開に対応させる提案。

例えば、今提案中のoverloadは、

template< typename Head, typename ... Rest >
struct overloader : Head, overload< Rest... >
{
    using Head::operator() ;
    // コンストラクターなど
} ;

template < typename T >
struct overloader< T > : T
{
    using T::operator () ;
} ;

template < typename ... Types >
constexpr auto make_overloader( Types && ... args )
{
    return overloader< Types ... >( std::forward<Types>...) ;
}

のように再帰的に書かなければならない。これは非効率的だ。

再帰的に書かなければならない理由は、using宣言がパック展開に対応していないからだ。対応していれば以下のように書ける。

template < typename ... Types >
struct overloader : Types ...
{
    using Types::operator() ... ;
} ;

確かに便利だが、利用方法は限られる気がする。あって困ることはないだろう。

[PDF] P0196R0: A generic none_t literal type for Nullable types

型none_tとその値noneの提案。

optionalやanyといったライブラリでは、何も値が入っていないnullな状態になり得る(nullable)。各ライブラリごとにnullを表す別々の型を定義して使うのは冗長であるし、使い勝手も悪い。そこで、nullを意味する共通の型を定義しようという提案。これでジェネリックなコードはnullableな型に対してnullが入っているか確認する場合や、nullを入れる場合、単一の型を扱うだけで良くなる。

これも最近流行りのボキャブラリー型だ。入るべきだろう。

[PDF] P0197R0: Default Tuple-like Access

tupleのようなユーザー定義クラスに対して、tupleのようなアクセス(tuple_size, tuple_element, get)を書くのは面倒だ。そういうアクセスはコンパイラーが自動で生成すればいい。この文書は、tupleのようなアクセスをデフォルトで自動で生成する提案だ。

例えば以下のようなクラス、

struct X
{
    char m1 ;
    short m2 ;
    int m3 ;
} ;
X x{ 1, 2, 3 } ;

に対して、以下のようなtuple風アクセスが何もせずとも自動的に生成される。


tuple_size<X>::value ; // 3
tuple_element< 1, X>::type ; // short
get<2>( x ) ; // int型の値3
get<char>(x) ; // char型の値1

public非staticデータメンバーに対するtuple風アクセスが自動生成される。

protected, privated, virtualな基本クラスがない場合、基本クラスも再帰的に探される。

template  < typename Head, typename ... Rest >
struct X : X< Rest ... >
{
    Head m ;
    X( Head && head, Rest && ... rest )
        : X< Rest ... >( std::forward< Rest >( rest ) ... ),
            m( std::forward<Head>(head) )
    { }
} ;

template < typename T >
struct X<T>
{
    T m ;
    X( T && t )
        : m( std::forward<T>(t) )
    { }
} ;

X< char, short, int > x{ 1, 2, 3 } ;

tuple_size<X>::value ; // 3
tuple_element< 1, X>::type ; // short
get<2>( x ) ; // int型の値3
get<char>( x ) ; // char型の値1

いわば簡易的な静的リフレクションで、シリアライゼーションなどの用途に使えるだろう。ちなみに、提案はConcept TSに依存しているが、見た限り、コンパイル時チェックに使っているだけで、Concept TSの依存を取り除くのは可能のようだ。

いまのConcept TSには依存しないでほしい。

[PDF] P0198R0: Default Swap

クラスに対してデフォルトのswapを自動生成する提案。コンパイラーはデフォルトのスワップを生成する。デフォルトのswapはメンバーごとのswapを行う。

struct X
{
    int m1 ;
    std::string m2 ;
    std::array<int, 10> m3 ;
} ;

void f( X & a, X & b)
{
    // メンバーごとの効率的なswapが行われる
    swap( a, b ) ;
}

std::swapはムーブ可能な型に対しては効率良く動くが、std::arrayのような、ムーブをサポートできない型には効率が悪い。std::arrayのようなクラスは、メンバーごとのswapを行うと効率が良い。そのようなコードは単調で機械的に生成できるので、デフォルトで生成する。swapはfriendなフリー関数として扱われる。

この変更の背景には、swapはコピーやムーブと同じぐらい根本的な操作であるという思想がある。

これは入ってほしい。

[PDF] P0199R0: Default Hash

P0029R0では大抵の型を突っ込めるhash_combineが提案されている。これを使えば、クラス保持する状態のうち、比較に関係のある情報を全部突っ込めばハッシュ計算が素人でも簡単に書けるようになる。問題は、そのようなボイラープレートコードを書くのはダルいということだ。

そこで、そのようなボイラープレートコードをデフォルトで生成されるようにする提案。

P0029とともに入ってほしい提案だ。

ドワンゴ広告

今日は夕方から歯医者だったのでさっさと帰宅した。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

WindowsにLinuxサブシステムを載せてUbuntuのユーザースペースが動く未来が来る?

​Microsoft and Canonical partner to bring Ubuntu to Windows 10 | ZDNet

詳しいことは明日発表されるということで、未だに公式の確証はないのだが、MicrosoftとCanonicalが提携してUbuntuをWindowsに持ってくるという話が上がっている。

現在予測されている内容では、これは単にWindows上で動く仮想環境でUbuntu GNU/Linuxを動かすという話ではなく、WindowsにLinux互換サブシステムを実装して、その上でUbuntuのGNU/Linux上で動くユーザースペースをそのまま持ち込むのではないかという憶測が出ている。つまり、aptでパッケージを管理してbashが使えてその他諸々のUbuntuのユーザースペースのCLIツールが全部使えるということだ。

これは、技術的に可能であろうが、Windowsに十分に互換性のあるLinux互換サブシステムを実装するのは不毛なほど金と労力がかかるだろう。

この憶測が正しいとして、どこまで実装するのかも気になる。CLIツールが動く程度だろうか。X.org互換か、あるいはX.orgが動くまで実装するのだろうか。

Linux互換サブシステムを実装する上で一番だるいのはなんだろうかと考えたところ、システムコールではioctlが一番だるいのではないかと思った。/procと/devもサポートしないと大抵のGNU/Linuxユーザースペースのプログラムは動かないので、やはりダルいだろう。

そしてもうひとつ気になるのが、ターミナルエミューレーターだ。まさかcmd.exeではあるまいな。せっかくのGNU/LinuxユーザースペースCLIプログラムが全部動いたとしても、端末がcmd.exeならば全てが台無しだ。

ということを考えると、やはりGNU/Linuxユーザースペースのターミナルエミューレーターも使いたくなり、ということはやはりX.orgが必要になる。

もうひとつの可能性として、Linuxカーネルを使うという手がある。ただ、これはGPLを考えるとありえないように思う。

何にせよ、そこまでしてGNU/Linuxのユーザースペースのツールを使うぐらいなら、最初からGNU/Linuxをネイティブにインストールしたほうがよい。

2016-03-29

C++標準化委員会の文書: P0174R0-P0189R0

P0174R0: Deprecating Vestigial Library Parts in C++17

標準ライブラリの一部をdeprecated扱いとする提案。

以下のライブラリのdeprecated扱いが提案されている。

std::iteratorは基本クラスとして使い、イテレーターの要件を満たすためのネストされた型名をわざわざ手動で定義する手間を省いてくれる。

しかし、本当に手間を省けるかというと疑問だし、クラステンプレートから非修飾名として使うと、依存名ではない問題が発生するので、わかりにくい。たとえば、以下のコードがエラーになる理由は、とてもわかりにくい。

#include <iterator>

template <typename T>
struct MyIterator : std::iterator<std::random_access_iterator_tag, T> {
   value_type data;  // エラー、value_typeが見つからない 
};

maptとmultimapのvalue_compare。

mapとmultimapの実装には使えないし、ユーザーに使われている様子もない。

入力にイテレーターの片方しか取らない版のアルゴリズム(std::mismatchなど)は危険なのでdeprecated扱いにする。

std::allocatorの冗長なメンバー

allocator_traits経由で使うようになったので、冗長なメンバーはdeprecated扱いにする。

文書では、その他の候補としても、いくつかのライブラリを上げている。

vector<bool>は混乱のもとで廃止したいが、ストレージ効率のよい動的に確保されるストレージ上に構築されたビット列コンテナーの代替案が現在はない。

is_literal

is_literalには実用性がない。というのも、ジェネリックなコードで本当に知りたいのは、ある構築が定数初期化であるかどうかであって、型の構築方法の一つがリテラル型になるかどうかなどは実用性がない。

get_temporary_buffer/return_temporary_buffer

もともと不完全なままSTLに残っていたのがそのまま規格にも残ってしまった誰もまともに使っていないライブラリ。

raw storage iterator

今となってはあまり利用価値がない。

無駄な機能は積極的にそぎ落としてほしい。

P0175R0: Synopses for the C library

C++の規格にC言語のライブラリの宣言を追加する提案。今まではヘッダーファイルだけ参照していた。

ユーザーとしては特に変わることはない。

P0177R0: Cleaning up allocator_traits

allocator_traitsのpropagateがイマイチ理解できない理由がわかった。

propagateはアロケーターが状態を持っているかどうかを判別するのに使うのだが、コピー代入とムーブ代入とswapに対して状態があるかどうかを判定するようになっているので、2^3通りの組み合わせがある。当然、ライブラリ側も2^3通りの組み合わせに対処しなければならない。

しかし、現実的に考えれば、アロケーターは状態を持っているかいないかの2通りの場合しかないはずで、原稿の規格はおかしい。これを簡略化するために、既存のpropagate系の判定を全部deprecated扱いにして、単一のpropagateを追加する提案。

これは当然行われるべき変更だ。

P0178R0: Allocators and swap

コンテナーなどのアロケーターを使う型で、アロケーターが状態を持っていて、アロケーターのオブジェクトが等しくない場合、swapが未定義の場合について、それぞれ一時オブジェクトにムーブした上でムーブする方法を使うことで、未定義を回避するフリー関数swapの追加。

P0180R0: Reserve a New Library Namespace Future Standardization

コア言語に新しい機能が入り、ライブラリの設計方法に新しい手法が考案されていき、また現実の需要と事情が変化する中で、近い将来にC++の標準ライブラリには破壊的変更を伴う大幅な変更が必要になるだろう。そのために、新しい名前空間std2とisoを予約する提案。

死蔵されなければよいが。

Ordered By Default

setやmapは、要素の大小比較にoperator <を使っている。これは大抵の場合うまく行くが、世の中には数学的な大小比較を提供していない型も存在する。例えば、。std::complexだ。ただし、complexはsetやmapのための大小比較は提供できる。しかし、そのためには大小比較を定義した上で、比較子をコンテナーに渡してやらなければならない。

struct complex_order
{
    template < typename T >
    bool operator () ( std::complex<T> const & l, std::complex<T> const & r )
    {
        std::tie(l.real, l.img) < std::tie( r.real, r.img ) ;
    }
} ;

int main()
{
    std::set< std::complex<float>, complex_order > s ; 
}

いちいちコンテナに比較子を渡すのが面倒だ。lessを特殊化してやれば明示的に渡す必要はなくなる。

namespace std
{
    template < typename T >
    struct less< std::complex<T> >
    {
        bool operator () ( std::complex<T> const & l, std::complex<T> const & r )
        {
            std::tie(l.real, l.img) < std::tie( r.real, r.img ) ;
        }

    }
} ;

std::set< std::complex<float> > s ;

しかし、これではlessはoperator <を呼び出すものという既存のcontractがこわれてしまう。

そのため、ユーザーにカスタマイゼーションポイントとして、別のテンプレートを提供する。

template <typename T>
struct default_order {
   using type = std::less<T>;
};

template <typename T>
using default_order_t = typename default_order<T>::type;

template < typename Key, typename Compare = default_order_t<Key>,
            typename Allocator = allocator<Key> >
struct set ;

あとは、default_orderを特殊化するだけだ。

template < typename T >
struct default_order< std::complex<T> >
{
    using type = complex_order ;
} ;

この提案は、既存のコードのABI互換性を壊さない。

どんな問題でももう一段階のラッパーをかますことで解決できる。ただし、ラッパーが多すぎるという問題を除いては。

P0184R0: Generalizing the Range-Based For Loop

range-based for loopでイテレーターの先端と終端の型を別にできるように制限を緩和する提案。

Range TSは番兵という概念を導入している。番兵となるイテレーターは別の型でもよい。

struct range
{
    iter begin() const ;
    sentinel end() const ;
}

void f( range const & r )
{

    auto i = r.begin() ;
    auto e = r.end() ;

    for ( ; i != e ; ++i )
    {
        do_somethign( *i ) ;
    }
}

このようなrange型は、現在のrange-based forには渡せない。なぜならば、コード変換のルールが、イテレーターの先頭と終端の型が同じでなければならない制約になっているからだ。この制約をなくし、上のようなrangeをrange-based forに渡せるようにする変更。

適切な変更だ。

P0185R0: Adding [nothrow-]swappable traits (Revision 2)

std::is_swappable<T>, std::is_swappable_with<T, U>, std::is_nothrow_swappable<T>, and std::is_nothrow_swappable_with<T, U>と、その変数テンプレート版(名前が_tで終わるもの)をtype_traitsに追加する提案。

また、utilityにあるswapを、

void swap(optional<T>& rhs)
    noexcept(
        is_nothrow_move_constructible_v<T>
        && noexcept( swap(declval<T&>(), declval<T&>()))
    );

にする。

いい変更だ。

P0186R0: Iterator Facade -

イテレーターを簡単に書けるライブラリの追加。

標準ライブラリに準拠するイテレーターを正しく書くのはボイラープレートコードが多すぎて面倒だ。そこで、このライブラリはC++17とConcept TSとRange TSがあれば簡単にイテレーターが書けるライブラリを提案している。

Concept TSもRange TSもしばらく入らないことを考えると、このライブラリも当分日の目を見ないだろう。

[PDF] P0187R0: Proposal of Bit­field Default Member Initializers

ビットフィールド付きのデータメンバーにデフォルトメンバー初期化しを書けるようにする提案。

struct X
{
    int data : 6 = 42 ;
} ;

文法上の曖昧性を解消してパースを簡単にするために、初期化子には=しか使えない。そして、=の後には初期化子が続かなければならない。例えば{}は書けない。

まあ、いいのではないか。

[PDF] P0188R0: Wording for [[fallthrough]] attribute.

switch文のcaseラベルを通り抜けるのが意図的であると明示的に記述する[[fallthrough]]属性の文面案。

例えば以下のようなコードを書くと、

switch( n )
{
case 2 :
case 3 : // OK、特に何もない
    f() ;
    break ;

case 4 :
    g() ; // 警告、通り抜けてませんか?
case 5 :
    h() ;
}

最近のおせっかいなコンパイラーはcase 4でbreakを書き忘れていないかという警告をしてくる。もし、プログラマーの意図が、nが4の場合は関数gとhを両方呼び出し、nが5の場合は関数hのみ呼び出すというものであれば、上記のコードは正しい。そこで、プログラマーの意図をコード上で伝えるために、[[fallthrough]]を書くことができる。

case 4 : 
    g() ;
    [[fallthrough]]
case 5 :
    h() ;

いちいち書くのが煩わしい以外はいいか。

[PDF] P0189R0: Wording for [[nodiscard]] attribute.

関数の戻り値を使わないと警告される[[nodiscard]]属性の文面案。

// 失敗する可能性があるとても重要な処理
// 失敗した場合はfalseを返す
[[nodiscard]] bool very_important_operation() ;

int main()
{
    // 警告
    very_important_operation() ;
}

また、型に指定した場合、その型を戻り値として使うと、関数に[[nodiscard]]を指定した扱いになる。


[[nodiscard]] struct error_status { } ;
error_status f() ; // [[nodiscard]]がつく

これはC++17に入るコア言語機能の中でも最も一般に役に立つ機能だと思われる。

ドワンゴ広告

ドワンゴではとある一社員が個人的にお菓子神社という霊験あらたかな神社を開いており、参拝者も多い。筆者もポテトチップスという現世利益のために浄賽を投じようと思ったが、ポテトチップスは一袋335kcalもあり、ジョギング換算で5kmに相当し、脂肪換算で46gにあたるため、強い意志力を持ってやめておいた。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2016-03-24

FBIが2週間でiPhoneをクラックする方法について

FBIがAppleに対してiPhoneをクラックするための特別なOSの開発を要求している裁判において、FBIにほぼ証拠捜査のためにほぼ任意の命令を下せる万能な昔の法律、、All Writs Actそのものの合憲性が問われかねない自体に陥っているため、FBI側も栽培を取り下げたいためか、FBIは2週間でiPhoneをクラックする現実的な方法があるので検証すると発言している。

果たしてそれは何なのか。以下の記事で、その方法が考察されている。

その前に、今回のFBIのiPhoneのクラックというのは、正確に言うと、iPhoneのPasscodeを突破したいというものだ。そのために、正解のパスコードを引き当てるまで入力を繰り返す、いわゆるブルートフォースと呼ばれる愚直な攻撃を実施したいのだが、iPhoneにはパスコードの入力を何度か間違えるとストレージからハッシュ値を削除するという仕組みが存在する。ならばそのストレージをコピーすればいいのではないかと思うだろうが、このストレージというのは、通常のストレージではなく、パスコードを格納するためのチップに内蔵されている極小のストレージのことだ。物理的に簡単にコピーできないように作られている。

My Take on FBI’s “Alternative” Method | Zdziarski's Blog of Things

さて、この記事では、FBIが主張する方法について考察しているが、その前に、FBIが取らないであろう方法が列挙されている。

マイクロプロセッサーを破壊すると、Appleですら修理できないであろうから、そのような方法は取らないだろう。また、脆弱性を利用するものは、おそらく検証に2週間以上かかるから違うだろう。監視カメラの映像を洗って容疑者がパスコードを入力しているところを見つけ出すというのも違うはずだ。というのも、FBIは主張する方法が実際に動くかどうか確証がなく、検証すると言っているからだ。

ではどうするのかというと、NANDミラーリングという方法を使うのではないかと推測している。

NANDミラーリングとは、まずパスコードのハッシュ値を記録している極小のストレージを基板から取り外し、コピーして、再び戻し、パスコードのブルートフォースをする。数回の試行で失敗してストレージが消されたら、コピーしたバックアップを戻して再び試行を再開する。

そんな極小のストレージを基板から剥がしてコピーして差し戻すのはにわかに信じがたい。

npmからkikとその他諸々が消されたまとめ

npmとは、node.jsにおけるパッケージシステムのことだ。npmを使えば、他人の書いたnode.jsベースのプログラムとライブラリの入手と利用がとても簡単になる。

そのnpm界隈が混乱している。発端は以下のURLだ。

I’ve Just Liberated My Modules — Medium

Azer Koçuluはkikという名前のnpmパッケージを公開していた。このkikというソフトウェアの中身についてはここでは関係がない。

さて、それとは別に、kik.comというスマフォ用のチャットアプリを出しているKik Interactive社がいて、kikという名前のパッケージをnpmで出したいので、名前を明け渡すように要求した。

Azerはこの要求を拒否した。すると、Kik Interactive社はnpmの管理者に片っ端からメールを投げまくり、そのうちの一人が反応して、Azerの意思に反して、何の法的根拠もなくパッケージを消した。

Azerはこの行動に対し、npmはもはや信頼できないとし、npmに出していたすべてのパッケージを削除した。

そして阿鼻叫喚の世界に突入する。Azerは様々なCLIツールやライブラリをnpmで公開していた。中でも影響力のあったAzerのパッケージは、left-padだ。

azer/left-pad: String left pad

left-padとは、文字列の左側(先頭)を指定した文字数になるように、指定した文字か指定されない場合は空白文字でパディング(埋める)だけの処理を行う簡単なJavaScriptで書かれたleftpadという名前のライブラリだ。空行を抜けば、10行ぐらいしかない簡単なコードだ。

このコードは有名なnpmパッケージで使われていたらしく、間接的に様々なnpmパッケージが依存していたため、世界中で大混乱を引き起こすことになった。

傑作なのは、当のKik Interactive社すらleft-padに依存していたということだ。Kik Interactive社は今回の件について、メールをすべて公開している。

A discussion about the breaking of the Internet — Medium

Kik社はパッケージ取り下げの理由を、ユーザーの混乱を招くためとしているが、すでに公開されたパッケージの中身が変わる方が混乱を招くし、名前だけ見て中身を確認せずにパッケージを使うバカは混乱して当然だ。

npm運営は、これについて議論しているフォーラムを建設的ではないとして閉じるなど、その後の対応も疑問がある。

今回の件について、興味深い指摘がある。

NPM & left-pad: Have We Forgotten How To Program? | Haney Codes .NET

そもそも、leftpadの中身は10行程度のコードである。空行を抜けば、以下の通り。

module.exports = leftpad;
function leftpad (str, len, ch) {
  str = String(str);
  var i = -1;
  if (!ch && ch !== 0) ch = ' ';
  len = len - str.length;
  while (++i < len) {
    str = ch + str;
  }
  return str;
}

実に多くのパッケージが、このleftpadに依存している。しかし、この程度の関数は数分で書けるのだから、なんでわざわざ依存するんだ?

もっと憂うべきパッケージがある。isArrayだ。このパッケージは一日88万回もダウンロードされていて、2016年2月だけの一ヶ月間に1800万回もダウンロードされていて、72個ものNPMパッケージが依存している。

isarray

isArrayの中身はこうだ。

var toString = {}.toString;

module.exports = Array.isArray || function (arr) {
  return toString.call(arr) == '[object Array]';
};

結局、このコードは本質的にたった一行のコードである。

その他、is-positive-integerという整数が正の整数かどうか判定するパッケージがあるが、これも本質的には4行のコードである。ところが、このパッケージは昨日まで3個もの依存を持っていた(今は0個になっている)

なぜこんなにも多数のパッケージに依存をするのだ?

leftpad, isArray, isPositiveInteger程度、ググる時間を含めても5分程度で書けるはずである。書けない奴はそもそもコードが書けないと言っていい。NPM界隈の人間はコードが書けないのか?

今回の騒動で、以下のような面白いネタパッケージシステムが開発されている。

require-from-twitter

曰く、「Twitterには編集ボタンがないので、最適なJavaScriptモジュールをホストである」

このパッケージシステムを使うには、まずソースコードを自分でツイートして

https://twitter.com/rauchg/status/712799807073419264

しかる後に使う。


const leftPad = await requireFromTwitter('712799807073419264');
console.log(leftPad(1, 5));      // '00001'
console.log(leftPad(1234, 5));   // '01234'
console.log(leftPad(12345, 5));  // '12345'

Twitter社さえ信用すればよい。

ドワンゴ広告

ドワンゴの採用面接を受けると日本Node.jsユーザーグループの「元」代表の@mesoとお話ができるそうだ。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2016-03-18

C++標準化委員会の文書: P0142R0-P0167R1

[PDF] P0142R0: A Module System for C++ (Revision 4)

[PDF] P0143R0: Wording for Modules

[PDF] P0143R1: Wording for Modules

モジュールの提案と文面案。

残念なことに、モジュールはC++17では見送られることが確定した。

[PDF] P0144R1 Structured Bindings

多値から変数宣言と初期化を同時にする文法の提案。

現状では、多値を返す関数の宣言と、多値を返すことは簡単に書ける。

std::tuple< int, double, std::string > f()
{
    return { 1, 2.3, "4" } ;
}

このような関数から、それぞれの型の変数をそれぞれ初期化するのは面倒だ。std::tieを使っても、変数をあらかじめ宣言する必要がある。

int x ;
double y ;
std::string z ;

std::tie( x, y, z ) = f() ;

そこで、以下のような文法で、それぞれの型と値で変数を宣言初期化する機能を提案している。


auto { x, y, z } = f() ;

初期化子としては、std::get<N>をサポートする型(tupleとpair)の他、非staticデータメンバーがすべてpublicなクラス型もサポートされる。また、配列もサポートされていて、それぞれの要素で初期化される。

struct XYZ
{
    int x ;
    double y ;
    std::string z ;
} ;

XYZ f() { return { 1, 2.3, "4" } ; }

auto { x, y, z } = f() ;

int abc[3] = { 1, 2, 3 } ;
auto { a, b, c } = abc ;

これは便利なので入ってほしい。

[PDf] P0145R1: Refining Expression Evaluation Order for Idiomatic C++ (Revision 2)

式の評価順序を固定する提案。

f( a, b, c )という式があったときに、f, a, b, cの式がどの順番で評価されるかは未規定である。例えば、以下のコードの出力結果は未規定である。

void f( int a, int b, int c )
{
    std::cout << a << b << c ;
}

int main()
{
    int i = 0 ;
    f( ++i, ++i, ++i ) ;
}

提案では、ほとんどの式の評価順序を定めているが、唯一、関数の実引数の評価順序は定めていない。そのため、上のコードの出力だけはこの提案でもいまだに未規定である。ただし、f(a)は実引数aより呼び出し可能な式fが先に評価されることが保証されている。

関数の実引数の評価順序が未規定に戻ってしまったのは残念だ。

P0146R1: Regular Void (Revision 1)

void型を完全形にする提案。すなわち、void型のオブジェクトが作れる。

void v1 ;
void v2 = v1 ;
bool b = v1 == v2 ;
void vs[10] ;
auto vp = std::make_unique() ;

テンプレートパラメーターにvoid型を渡した時に例外的に特殊化して対応しなければならない問題が、void型を完全型にするだけで解決する。

[PDF] P0149R0: Generalised member pointers

メンバーポインターの型変換の制限を緩和する提案。

本当に需要がある変換なのだろうか。

[PDF] P0161R0: Bitset Iterators, Masks, and Container Operations

bitsetに2種類のイテレーターを追加する提案。iteratorとindex_iteratorが追加される。

iteratorのoperator *は、イテレーターの指す場所のビットのみがたったbitsetを返す。

std::bitset<3> b{0b110} ;
auto i = b.begin() ;

auto b0 = *i ; // bitset<3>{0b000}
auto b1 = *++i ; // bitset<3>{0b010}
auto b2 = *++i ; // bitset<3>{0b100}

index_iteratorは、イテレーターの指す場所をsize_tで返す。

std::bitset<3> b{0} ;

auto i = b.ibegin() ;
auto i0 = *i ; // 0
auto i1 = *++i ; // 1
auto i2 = *++i ; // 2

既存のコンテナーのイテレーターとは全く違うのでわかりにくい。iteratorは改名すべきだろう。

P0165R1: C++ Standard Library Issues to be moved in Jacksonville

Jacksonville会議で採用が決まった標準ライブラリの問題点の解決案。

P0165R1: Core Language Working Group "ready" Issues for the February, 2016 (Jacksonville) meeting

Jacksonville会議で採用が決まったコア言語の問題点の解決案。

ドワンゴ広告

もうすぐC++17のドラフトが本格的に固まってくるのだが、C++17の新機能として紹介できるわかりやすい大きなコア言語の変更があまりない。どれも小粒な変更ばかりだ。ライブラリはいくつか新しい物が入っているのだが。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2016-03-17

Twitterでつぶやかれている絵文字のリアルタイムなトラッカー

emojitracker: realtime emoji use on twitter

Twitterでつぶやかれている絵文字のリアルタイムなトラッカーがある。

このサービスは近々、Twitterの歴史的に認められていた上限なしAPIアクセスの廃止に伴い、終わる見込みだそうだ。

U+1F647 PERSON BOWING DEEPLY 🙇 — Medium

面白いし参考になるので、今のうちに眺めておこう。

ちなみに、この絵文字トラッカーはユニコードコンソーシアムにおいて絵文字の実際の利用需要の参考に引用されたこともある。

Twitterがまだおおらかな頃、このような面白いサービスを作るために、APIへの上限なしアクセス権を気軽にホイホイ発行していたのだが、Twitterからのメールでの連絡で、近々そのような上限なしアクセスを廃止するので、商用アクセスAPIであるGnipに移行するか諦めろという言われたと報告している。残念なことだ。

Hacker NewsではTwitter社員だと自称する人間が今回の決定について適切な利用法であれば例外的措置もあり交渉も可能であり、我々に交渉もせずに公にしたのは残念であると言い訳がましいことを書き込んでいるが、公開されたメールの文面をみれば、商用APIに移行するか諦めろという最終通告にしか読めないが、公開されているメールの文面は間違っているのか? いかにも言い訳がましいと反論されている。

2016-03-16

C++標準化委員会の文書: P0119R1-P0138R1

今回から、個人的な感想も意図的に書いてみることにした。

[PDF] P0119R1: Overload sets as function arguments

オーバーロードされた関数の名前からlambda式を暗黙に生成する機能の提案。

オーバーロードされた関数名は、関数の集合を表すので、テンプレート実引数に渡すことはできない。

void f( int ) ;
void f( double ) ;

template < typename Func >
void g( Func func ) ;

int main()
{
    // エラー
    // どのfか曖昧
    g( f ) ;
}

これは、lambda式を経由すれば渡すことができる。

g( []( auto && x ) -> decltype(auto) { return f( x ) ; } ) ;

しかし、こんな自明なlambda式をわざわざ書くのは面倒だ。そこで、関数のオーバーロードのセットを指すid-expressionが実引数として指定されたら、このようなlambda式を生成するテンプレートの実引数推定を追加する提案。

テンプレートの実引数推定にルールを追加するので、autoで受けることもできる。

auto less = (<) ;
less( a, b ) ;

確かに便利だが、どの程度の需要があるだろうか。

[PDF] span: bounds-safe views of objects for sequences

連続したストレージとそのサイズを管理して配列のようにアクセスできるライブラリspanの提案。

もともとは、多次元配列としても使えるarray_viewの提案だったが、多次元配列サポートをなくし、また名前も変えてspanとした。Guidelines Support Libraryのspanを

spanは、連続したストレージとその長さを管理できる。つまり、ポインターとその長さを管理するためのクラスだ。

最近のC++の標準ライブラリには、このような"vocabulary type"の提案が多い。vocabulary typeはコードを読みやすくする。

spanはコンパイル時の配列の長さ指定と、実行時の配列の長さ指定の両方をサポートする。

int a[10] ;
// コンパイル時に長さを指定した固定長span
span<int, 10> s1{ a } ; 
// 実行時に長さを指定した動的長さspan
span<int> s2{ a, 10 } ;

spanを経由した配列へのアクセスには範囲チェックが行われる、範囲外アクセスは未定義の動作を引き起こす。固定長と動的長さspanは相互に代入可能だが、長さのチェックはもちろん行われる。

実際の使い方は、arrayとほぼ同じだ。

興味深いのは、P0257の提案されているbyteを使って、standard layout型Tのspan<T>をspan<byte>に変換することで、内部表現を読み書きすることをサポートしている点だ。キャストを手で書かずに済む。

このライブラリは便利なのでほしい。

[PDF] P0123R1: string_span: bounds-safe views for sequences of characters

string_viewがstring_spanに改名された。文字列を共通の方法で操作できるラッパーライブラリ。

string_viewの方がわかりやすい気がするが自転車小屋について議論しても仕方がないのだろうか。

P0124R1: Linux-Kernel Memory Model

Linuxカーネルのメモリモデルについて不文律であるところも含めて完全に解説する文書。

背景として、Linusにatomic操作ライブラリは使い物にならんと言われたので、まずLinuxカーネルにおけるメモリモデルを理解するところから始めるそうだ。

[PDF] P0126R1: std::synchronic<T>

リソースを浪費せずに、あるオブジェクトの値が期待する値になるまで待つライブラリ、std::synchronic<T>の提案

使い方は極めて原始的なcondition variableに近い。

P0128R1: constexpr if

コンパイル時条件分岐constexpr ifの提案。

前回からの変更点は、一つの新しいキーワードconstexpr_ifから、既存のキーワードを連続したconstexpr ifになったこと。

template < typename T, typename ... Rest >
void f(T && t, Rest && ... rest )
{
    constexpr if ( sizeof...(rest) )
    {
        // tを処理
        // 引数ゼロ個のfのオーバーロードは必要ない。
        f( std::forward<Rest>(rest)... ) ;
    }
}

constexpr elseもある。

constexpr if ( ... )
{

}
constexpr else
{

}

どういう形であれ、コンパイル時条件分岐はほしい。

[PDF] P0138R1: Construction Rules for enum class Values

enumを強いtypedefの代わりに使える機能の提案。

内部型が指定されていて、enumeratorの存在しないenumは、縮小変換のないリスト初期化を使えば、キャストを使わずに初期化できるようにする提案。

enum class E : int { } ;

E e{123} ;

void f( E e ) ;

void g()
{
    f( { 123 } ) ;
}

キャストが必要なくなるのは初期化だけなので、これでは使い方が煩わしいことに変わりはない。本物の強いtypedefの方がいい。

ドワンゴ広告

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2016-03-10

ファミコンのゲームを3次元化するエミュレーターがすごい

ファミコン画面立体化エミュレータ「3DNES」ベータ版公開。思い出のゲームをリアルタイムに3D変換してプレイ - Engadget Japanese

ファミコンの画像を立体的にして遊べるファミコンエミュレーターが公開されたそうだ。

これはとても面白いコンセプトだ。

金と労力をかけて、特定のゲームに特化したエミュレーターを作れば、もっと精度は良くなるはずで、すでにファミコンエミュレーターはWiiUや3DSでVCという商業的な流通経路もあるので、将来的には公式にこのようなエミュレーターを出すのはあり得る未来だ。

もちろん、一から作るという手もあるが、そのような再実装よりも商業的価値が高いはずだ。

2016-03-07

C++標準化委員会の文書のレビュー: P0063R1-P0096R1

P0063R1: C++17 should refer to C11 instead of C99

C++規格が参照するC言語規格をC99からC11にする変更。

C11の変更がC++とかち合う部分や、C++とCの文面を厳密に解釈した際の奇妙な結果が考察されていて面白い。t

P0067R1: Elementary string conversions, revision 1

整数と浮動小数点数を文字列と相互変換するライブラリの提案。

このライブラリはロケールのように実行時にフォーマットを切り替える機能がなく、かつ、動的メモリ確保も行わない。

用途は、国際化対応が必須ではないパフォーマンスが重要なテキストベースフォーマットのパース。例えば、JSONやXMLなど。

[PDF] P0072R1: Light-Weight Execution Agents

スレッドより制約がある実行単位(SIMDやGPGPUなど)を、実行媒体(execution agent)として扱うための定義を文面に追加する提案。

[PDF] P0073R1: On unifying the coroutines and resumable functions proposals

コルーチンとレジューム可能関数の統一に向けて。

[PDF] P0075R1: Template Library for Parallel For Loops

インデックスベースの並列forループアルゴリズムを追加する提案。

std::for_loop( std::seq, 0, n, [&]( auto i ){ A[i] = B[i] ;} ) ;

これは、以下と同じ意味だ。

for ( unsigned i = 0 ; i != n ; ++i )
    A[i] = B[i] ;

seqをparにすれば、並列実行版になる。

アルゴリズムには、通常のレンジ版と、カウント版がある。レンジ版は、開始インデックスと終了インデックスを取り、イテレーター風にHalf Open Rangeとして終了インデックスに到達するまでインデックスをすすめる。カウント版は、開始インデックスとイテレート回数を取る。インデックスは指定された回数だけ進められる。カウント版のアルゴリズムは、末尾が"_n"という名前になっている。

std::for_loop_n( i, n, f ) ;

は、

for ( unsigned count = 0 ; count != n ; ++count )
    f( ++i ) ;

のような意味になる。

またこの提案はstride版のアルゴリズムも提供する。これは末尾が"_strided"となっている。stride版はインデックスの刻み幅を指定できる。

std::for_loop_strided( i, n, m, f ) ;

は、

for ( auto I = i ; I != n ; I += m )
    f( I ) ;

のような意味になる。

Reductionのサポート。Reductionとは、ロックを使わずに一つの変数を並列に変更でき、最終的な値はシリアルに実行した場合と同じものを得る方法である。その仕組みは、並列実行には変数のviewを見せておき、複数のviewから最終的な値を計算する方法を提供することによって実現している。

float f(int n, float x[]]) {
    float s = 0;
    for_loop(par, 0, n, reduction(s,0.0f,std::plus<float>()),
        [&](int i, float& s_) {
            s_ += x[i] ;
        });
    return s;
}

この例では、変数sの最終的な値は、途中の変更をすべて加算することで得られるので、そのようなreductionを与えている。for_loopの最後の実引数は、Variable Templatesになっていて、reductionをいくつでも受け取ることができる。パラーメーターパックの最後が呼び出し可能な関数オブジェクトとなる。reductionを使った数だけ、関数オブジェクトの呼び出しに実引数が追加される。

inductionのサポート。inductionはループのイテレート回数に応じて線形に増える値である。そのような値をユーザーが手で計算すると間違いの元なので、ライブラリが用意されている。


float* zipper(int n, float* x, float *y, float *z) {
    for_loop(par, 0, n,
        induction(x),
        induction(y),
        induction(z,2),
        [&](int i, float* x_, float* y_, float* z_) {
            *z_++ = *x_++;
            *z_++ = *y_++;
        });
    return z;
}

inductionもreductionと同じく、いくつでも使える。使った数だけ実引数に渡される。上記のコードは、以下のコードと同じ意味である。


float* zipper(int n, float* x, float *y, float *z) {
    for_loop(par, 0, n,
        [&](int i) {
            *(z+i*2)++ = *(x+i)++;
            *(z+i*2)++ = *(y+i)++;
        });
    return z;
}

[PDF] P0076R1: Vector and Wavefront Policies

Parallerism TS(並列アルゴリズム)にベクトル実行ポリシー(SIMDやGPGPU)を追加したいが、単にpar_vecをシングルスレッドに誓言スルテイ土では、制限がゆるすぎてベクトル化できないので、制限を強めた2つの実行ポリシーを追加する提案。

P0077R1: is_callable, the missing INVOKE related trait

is_callable traitsの提案。関数型をテンプレート実引数に与えると、戻り値の型を引数で関数呼び出しできるかどうかを返してくれる。

void f( int, int ) ;

std::is_callable_v< f( int, int ) > ; // true
std::is_callable_v< f( int ) > ; // false

[PDF] P0082R1: For Loop Exit Strategies (Revision 2)

イテレート文を通常通り抜けた場合(条件がfalseになった場合)と、早期に抜けた場合(break)に実行される文を記述できるようにする提案。

ループを実行したあとで、ループが全部回ったのか、途中でbreakしたのかによって、処理を分けたいことがある。その場合、以下のように書かなければならない。

auto it = get_begin(. . .); // Unfortunate that ‘it’ has to be out here.
auto end = get_end(. . .); // Unfortunate that ‘end’ has to be out here.
for (; it != end; ++it)
{
    if (some_condition(*it)) break;
    do_something(*it);
}
if (it == end) // Extra test here.
    do_stuff();
else
    do_something_else(*it);

もし、ループの条件を二回評価できない状況では、以下のようにbreakで抜けたかどうかを保持する変数を書かなければならない。

bool early = false;
while (some_condition())
{
    . . .
    if (test1()) { early = true; break; }
    . . .
    if (test2()) { early = true; break; }
    . . .
    if (test3()) { early = true; break; }
    . . .
}
if (early)
{ . . . }
else
{ . . . }

range-based forの場合はもっと悲惨だ。ループが途中で中断された時のイテレーターが欲しい場合、以下のように書かなければならない。

something_t last; // Extra construction here.
bool early = false;
for (auto&& element : container)
{
    if (some_condition(element))
    {
        last = element; // Extra copy here
        early = true;
        break;
    }
    do_something(element);
}
if (early)
    do_something_else(last);
else
    do_stuff();

そのため、この文書は、イテレート文から条件がfalseになって抜けたが、breakで抜けたかによって実行される文を記述する文法を提案している。


for ( unsigned i = 0 ; i != 10 ; ++i )
{
    if ( !do_something( i ) )
        break ;
}
catch default
{
    do_normal_exit_thing() ;
}
catch break
{// for文で宣言した変数を使うことができる
    do_break_exit_thing(i) ;
}

前回からの変更は文法だ。if forというわかりにくい文法から、catch default, catch breakというわかりやすい文法になった。

これはたまに欲しくなる。

P0088R1: Variant: a type-safe union (v6).

型安全なunion風ライブラリ、variantの提案。

variantは無効な状態、空の状態を許容するかどうかで議論がもめている。

[PDF] P0089R1: On Quantifying Memory-Allocation Strategies (Revision 2)

グローバルアロケーターのかわりにローカルアロケーターを使うことでどのような状況がパフォーマンスの向上につながるのかを検証した文書。

P0091R1: Template argument deduction for class templates (Rev. 4)

コンストラクターによるテンプレートの実引数推定の提案。

tuple<int, double> t{ 1, 2.3} ;

tuple t{ 1, 2.3 } ;

と書けるようになる。

P0096R1: Feature-testing recommendations for C++

C++の機能テストマクロをC++17に対応させる文書。

C++17に入る変更点の一覧にもなっている。

ドワンゴ広告

今日は社内で筆者のask.fmコーパスを用いて機械学習し、文章が質問かどうかを判定するプログラムの作成を試みた社員がいた。結果は、あまり精度がよくなかった。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2016-03-06

靴を買った話

ボルダリングを始めてから筋肉もついたが、食事量も増えたのか、脂肪もつき始めた。その結果、体重がかなり増え、以前ならば登れていた課題が登りにくくなってきた。

これではいかんと一念発起して、2年ぶりにジョギングを再開することにした。京都に住んでいた頃はジョギングをしていたのだが、東京に引越してからはジョギングをしていなかった。まず、ジョギングをするための靴がないので、近所のスポーツ用品店に買いに行った。

スポーツ用品店には様々な靴が並んでいた。しかし疑問なのは、テニス用の靴とバスケットボール用の靴のどこが違うのだろうかということだ。

ジョギング用の靴にも、だいぶ不思議なものがあった。側面に手動のポンプがついていて、シューズをふくらませることによりフィット感を出すという触れ込みの靴があった。そのようなギミックは信用できないので買うのはやめておいた。

結局、1万円ぐらいのジョギング用の靴を買った。

さて、問題は、クライミング用の靴だ。この8ヶ月ほど、スポルティバのジーニアスを履いて登っていたが、そろそろつま先がすり減ってきた。調べると、ジーニアスのソールの厚みは3mmしかないという。足裏感覚抜群という謳い文句のためには、もちろんソールは柔らかく薄くなければならないが、3mmは薄すぎだ。また、一般的に柔らかいソースは、それだけ耐久性も劣るはずだ。

筆者のクライミングシューズ歴は、タランチュラ3ヶ月、ソリューション3ヶ月、ジーニアス8ヶ月だ。どれもスポルティバの靴なので、そろそろスポルティバ以外の靴を試してみたいものだ。

そこで今回は、あまりダウントゥのきつくない靴を試してみることにした。いろいろと見た挙句、Andrea Boldriniのアパッチライトを買うことにした。なかなか見ないメーカーだが、クライミングシューズメーカーとしては高級靴として有名なのだそうだ。価格は他の靴と比較してそれほど高いわけではないが、他の靴がここ数年で値上げしたのに対し、値段が据え置きなので、やはり相対的に高いという。

さて、アパッチライトのソールはAndrea Boldrini独自のFormulaラバーと称するものを使っている。Formulaラバーには2種類あるらしく、アパッチライトが使っているのは、摩擦と耐久性のバランスがいいと謳っているものだ。実際の感覚では、かなり硬いラバーである。摩擦はあまりよくない。アパッチライトのソースの厚みは5mmもあるそうだ。練習用のシューズとしては悪くないかもしれない。

靴の作りはそれほど極端ではない。足入れはしやすい。ソールは土踏まずの前にしか貼られていない。土踏まず部分が靴の中で盛り上がっていて、偏平足気味の筆者の足に当たる。

ヒールの作りはやや気になる。ゴムの継ぎ目の位置が中央に来ているのだが、これはヒールをかけそこねてこすった時に痛まないだろうか。また、ヒール部分は柔らかすぎて、ヒールをかけてかきこむと足が痛い。

とりあえずしばらくはアパッチライトで頑張ることにする。

2016-03-02

普通のコンピューターからAMラジオを鳴らそう

読者の持っている至って普通のコンピューターは、実はAMラジオを鳴らす発信装置が備わっている。

ラジオを鳴らすコードは以下にある。

https://github.com/fulldecent/system-bus-radio

ただしこれはMac OS Xでしか動かないので、C++11に移植したコードが以下になる。また、このコードはスレッドを回して消費電力を上げることにより、オリジナルより出力も上げてある。

https://github.com/EzoeRyou/system-bus-radio

動かし方(GCCの場合)

git clone git@github.com:EzoeRyou/system-bus-radio.git
cd system-bus-radio
make gmain
make grun

Clangの場合、以下のようにする。

make cmain
make crun

そして、AMラジオを近づけて、周波数をいろいろと変更してみよう。なんと、メリーさんの羊が聞こえるではないか。原作者の環境では1580kHz、筆者の環境では1440kHzが最も聞き取りやすかったが、コンピューターによって最適な周波数は変わる。

一体どうしてAMラジオがなるのか。CPUが命令を実行するとき、コンピューターからは電磁波が発生する。電磁波はラジオで観測できる。つまり、別のタイミングで命令を実行してやれば、ラジオに乗るノイズも別になる。適切な周波数で命令を実行すれば、ラジオに乗るノイズも音階を持ったものにできるのだ。

もともとはTEMPESTガイドラインという、アメリカ合衆国のNSAと国防省の勧告によるもので、サイドチャネル攻撃の危険性を周知しているものである。

オリジナルはMac OS X専用の高精度タイマーを使っていて、かつ、SSE命令を使っていた。C++11に移植するために、高精度タイマーには<chrono>, <thread>を使った。SSE命令の代わりに、<atomic>を使った。また、以下のPull Requestと同等のコードを書いて、スレッドで実行することにより、出力を上げた。

boost sound without radio by andryblack · Pull Request #5 · fulldecent/system-bus-radio

ドワンゴ広告

今日はこればかりやっていて、あまり仕事をしていない。これからする。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2016-02-29

C++標準化委員会の文書: P0033R1-P0059R1

P0033R1: Re-enabling shared_from_this

enable_shared_from_thisの規程を書き直す提案。

enable_shared_from_thisとは、クラスの基本クラスとして使うと、shared_from_thisというメンバー関数が追加され、そのクラスのオブジェクトを現在所有しているshared_ptrが返る。

class X : public std::enable_shared_from_this<X> { } ;

int main()
{
    auto sp1 = std::make_shared<X>() ;

    // sp1とsp2は所有権を共有する
    auto sp2 = sp1->shared_from_this() ;
}

問題は、複数のshared_ptrに所有された場合どうなるのだろうか。

X * ptr = new X{} ;
std::shared_ptr<X> sp1( ptr ) ;
std::sahred_ptr<X> sp2( ptr, [](void *){} ) ;

// sp1とsp2のどちらと所有権を同じくするshared_ptrが変えるのか?
ptr->shared_from_this() ; 

規格はこの場合の挙動について述べていない。既存の実装はすべて、sp2はsp1を上書きする。しかしこの挙動は、単にこの可能性を考えなかっただけにすぎない。Boostのshared_ptrは書きかえない。これはユーザーのフィードバックによるものである。

これを考察すると、最初のshared_ptrが所有権を持つのが自然で、デリーターが何もしないshared_ptrを作りたいことはあるかもしれず、この例が動いてほしい場合はあるが、動かないでいて欲しい場合はない。そこで、最初のshared_ptrから上書きされない決定がなされた。

また、weak_ptrを返すweak_from_thisも追加された。

P0035R1: Dynamic memory allocation for over-aligned data

operator newにオーバーアラインを守るオーバーロードを追加する提案。

問題は、この提案だとだいぶ文法が汚いことになるのではないか。

auto * ptr = new(static_cast<std::align_val_t>(32)) int[128] ;

P0037R1: Fixed-Point Real Numbers

固定少数点数ライブラリ、fixed_point<ReprType, Exponent>の提案。

P0040R1: Extending memory management tools

メモリ管理のためのライブラリとして、デストラクターを呼ぶdestroy, uninitialized_move, uninitialized_value_construct, uninitialized_default_constructを追加。これらはコア言語機能だけでも行えるが、記述が面倒なのでライブラリとしてあると便利だ。

P0046R1: Change is_transparent to metafunction (Revision 1)

連想コンテナーでheterogeneous lookupを許可するかどうかを判断するにはcomparatorにis_transparentというネストされた型名が必要だが、これをpermits_heterogeneous_lookup<T>というわかりやすいメタ関数に置き換える提案。

[PDF] P0052R1: Generic Scope Guard and RAII Wrapper for the Standard Library

汎用RAIIラッパーライブラリの提案。

#include <scope>

int main()
{
    {
        auto file = std::make_unique_resource( fopen("hoge", "w"), &fclose ) ;
    }

    {
        auto memory = std::make_unique_resource( malloc( 100 ), &free ) ;
    }

    {
        auto s1 = std::make_scope_exit( []{ std::cout << "leave scope" ; } ) ;
        auto s2 = std::make_scope_success( []{ std::cout << "leave scope normaly" ; } ) ;
        auto s3 = std::make_scope_fail( []{ std::cout << "leave scope by exception"} ) ;
    }

}

unique_resourceは、ある型のオブジェクトを保持し、破棄されるタイミングでそのオブジェクトを引数に渡してデリーターを呼んでくれる。

scoped_exitは、脱出関数を引数に取り、破棄されるタイミングで脱出関数を呼んでくれる。make_scope_xxxには3種類ある。exitはスコープから抜けたら必ず脱出関数を呼ぶ。successは例外によらずにスコープを抜けた場合にのみ脱出関数が呼ばれる。failは、例外でスコープを抜けた場合のみに脱出関数が呼ばれる。

もうひとつ、make_unique_resource_checked(R r, S invalid, D d)という関数があり、これはrがinvalidに等しい場合、返されるunique_resourceは、すでにreleaseが呼び出されたあとである。

今回の変更点は、unique_resourceのリソースとデリーターは、無例外コピー可能な型でなければならないとするもの。これにより設計が単純になり、無例外コピー可能ではないstd::functionも使う必要がなくなる。また、リファレンスを渡す場合は、std::ref/crefをユーザーが使わなければならない。

P0055R1: On Interactions Between Coroutines and Networking Library

提案されているネットワークライブラリの非同期呼び出しとしてfutureが使われているが、コルーチンを使うようにしたらオーバーヘッドが下がった上にコードも簡潔になったという文書。

[PDF] P0057R2: Wording for Coroutines

コルーチンの文面案。

[PDF] P0058R1: An Interface for Abstracting Execution

スレッドプール、協調型ファイバー、SIMD、GPGPUまで含めた実行媒体を表現できるexecutorライブラリの提案。スレッドからSIMDやGPGPUまでを包括したいいライブラリが設計できるとは思えない。

[PDF] P0059R1: A proposal to add a ring span to the standard library

ring_spanライブラリの提案。

この提案は名前が悪い。ring_viewとでも改名すべきではないだろうか。

いわゆるリングバッファーライブラリなのだが、前回の提案が固定長リングバッファーと動的リングバッファーの2つがあったのに対し、この提案では、ring_spanに統一されてしまっている。ring_spanは連続したストレージ上にリングバッファーを構築するが、ストレージの所有はしない。ストレージはユーザーが用意する。

つまりデフォルト構築もできないコンテナーなのだが、すごく使いづらい気がする。

ドワンゴ広告

来月ドワンゴで開催する予定の勉強会にレーザープリンターを持ち込みたいという猛者がいるので困惑しているが、PostScriptのデモのための実行環境としては極めて普通であり当然予期すべき事態ではある。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2016-02-27

歌舞伎座.tech #9で発表される各言語の簡易的なまとめ

3月20日に以下のような勉強会を企画した。

歌舞伎座.tech#9「異種プログラミング言語格闘勉強会」 - connpass

今回は様々な言語を持ち寄って発表する勉強会にしたかったので、有名な言語の発表枠をいくつか用意して、それ以外の言語での発表は明示的に要求させるようにした。ネタ枠として正規表現とかEsoteric的な何かの言語の発表枠も用意しておいた。

ところが、予想に反して、有名な言語の発表枠が埋まらず、発表されてから数年しか立っていないような先進的な言語やネタ言語が多かった。中には聞いたことのないような言語もあるので、Googleで検索して5分ぐらいでわかるような内容の説明を以下に並べておく。

C++(シープラスプラス)

1983年頃から、ベル研究所内でBjarne Stroustrupにより設計、開発された言語。これ以前のC with Classesの経験を元に一から作られた。我々の知る今のC++は1998年に正式に規格が制定された。そこから規格更新を繰り返して、今は2014年の規格が最新になっている。

C++は低級層のプログラミングや、パフォーマンスが重要な分野に用いられている。

JavaScript(ジャバスクリプト)

1995年に、Netscapeというブラウザーに搭載された言語。Brendan Eichにより、たったの10日間で開発されたと言われている。当初はWebサイトにクライアントサイド側でちょっとした動的なギミックを付け加える程度の用途だったのだが、今ではWebにおける共通言語の地位を確立している。

正規表現(せいきひょうげん)

歴史はコンピューター以前にさかのぼることができる。もともとは数学を記述するための言語として、1956年にStephen Cole Kleeneによって考案された。正規表現がコンピューター上で用いられるようになったのは、Ken Thompsonによって、QEDというテキストエディターの検索機能として実装されたからだ。当時のKen Thompsonの正規表現実装は、高速化のためJITが使われていたという。JITの早期の使用例としても興味深い。なお環境は、IBM 7094でOSはCompatible Time-Sharing Systemである。検索機能として正規表現によるパターンマッチは、他のツールにも取り入れられた。

C++を含む多くのプログラミング言語が正規表現ライブラリを標準で提供している。また、言語によっては、Perlのようにコア言語で深くサポートされているものもある。特に、Perlの正規表現などは、正規表現やマッチした結果を参照できるので、チューリング完全な計算力を持っている。

Esoteric(エソテリック)

これは具体的なプログラミング言語の名前ではなく、難読プログラミングの総称である。例えば有名どころの難読言語としては、Brainfuckがある。Brainfuckはチューリング完全な計算力を持っているので、計算力として根本的に他の汎用的なプログラミング言語に劣ることはない。

今回の発表でどのような言語を使うのかは、まだ知らない。

Elixir(エリキサー)

この言語は2012年に公開されたばかりで、相当に新しい。作者はJosé Valimだ。この言語の現時点でのおそらく唯一の実装はErlang VM上で動くバイトコードを生成する。Erlangの既存の資産を活用しつつ、Erlangより使いやすい言語が欲しかったのが開発動機だそうだ。

Go(ゴー)

2009年に発表された言語。Googleにより開発されていて、設計者はRobert Griesemer, Rob Pike, Ken Thompsonの3人だ。まだ言語としては発表されてから7年しか立っていないが、巨大な民間企業の後ろ盾を得た開発により、すでに現場で使えるほどの品質になっている。Googleによる実装はすでにGoでセルフホストされている。libcにも依存しないかなり独立性の高い言語となっている。

Nim(ニム)

2008年に公開された。設計者はAndreas Rumpfだ。現在の実装は、コンパイル結果としてCかC++かObjective-Cのコードを吐くようになっている。実装はNimでセルフホストされている。

Crystal(クリスタル)

2014年に公開された。設計者はAry BorenszweigとJuan Wajnermanだそうだ。文法はRubyに影響を受けている。強い静的型付けはあるが、変数の型は明示的に指定しなくて良いようになっている。

シェルスクリプト

ここでいうシェルとは、UNIXとUNIX風の環境におけるシェルのことで、そのシェルが提供する言語だ。筆者のデフォルトのシェルはbashだ。こだわりの強い情報強者たる読者はもちろんもっと強力なシェルを使っていることだろう。

ただし、この発表者のいうシェルスクリプトとは、POSIX規格の範囲内のシェルスクリプトだ。/bin/shがbashへのシンボリックリンクになっている環境も多い中で、POSIXの規程によるシェルスクリプトとプログラムだけを使ってコードを書くのは大変だ。

F#(エフシャープ)

2005年公開。主要な設計者というかプロジェクトの管理者はDon Symeだ。ML、とくにOCamlの影響を強く受けているという。実行環境としては.netフレームワーク上で動く。

歴史もそれなりに長く、Visual F#としてWindows環境でとても有名なIDEであるVisual Stdioに同梱されているそうだが、私はMLの分野をよく知らないためどの程度使われているのかわからない。

Pony(ポニー)

2013年に公開されたらしい。背景事情の情報が不足しているが、作者はおそらくSylvan Clebschではないか。

capabilities-secureな言語であると謳っているが、これは別に権限を細かく分割して必要最小限度の権限しか持たないCapability-based securityをサポートした言語という意味ではなく、単に型安全、メモリ安全、例外安全、データ競合フリー、デッドロックフリーのような意味を持つらしい。紛らわしい変な言葉を発明しないでもらいたいものだ。

Frege(フレイガ)

2011年公開。作者はIngo Wechsung。公式に、JVM用のHaskellを謳っていて、文法もほとんどHaskell互換性だ。。外部依存のないHaskellコードはそのままコンパイルできるか、僅かな修正だけで動くことを目指している。また、JVMにかかわらないFregeコードは他のHaskell実装でも実行できるのだという。

それでもHaskellという名前を使わないので、完全互換は目指していないのだろう。Fregeという名前は、Gottlob Fregeに由来する。

Rust(ラスト)

2010年に公開された。もともとの原案の設計者としてはGraydon Hoareで、開発はMozillaの支援を受けている。最初の実装はOCamlだったが、すぐにRustでセルフホストされるようになった。コード生成などのバックエンドはLLVMを使っている。

目標は、並列化処理を安全に書ける言語だそうだ。文法的にはCやC++にかなり似ている。

Nemerle(ネマール)

2003年公開。ヴロツワフ大学の学生と教授が開発したらしい。言語の名前はUrsula K. Le Guin著のゲド戦記、A Wizard of Earthsea(影との戦い)に出てくるキャラクターに由来するそうだ。英語表記ならばこの読みでいいのだろうが、ポーランド人が読むとネメレあたりの発音になるのだという。

それはともかく、言語的には.Net上で動く。関数型かつオブジェクト指向な言語だそうだ。MLの影響が強い。

Postscript(ポストスクリプト)

1982年公開。設計者はJohn Warnock, Chuck Geschke, Doug Brotz, Ed Taft, Bill Paxtonで、Adobe Systemsによって開発された。

この言語は人間が手で書くことを想定しておらず、ツールによって生成された上で、プリンターに送信される。プリンターはPostscriptを解釈してページを生成し、印刷する。Postscriptは印刷物のための中間言語としての規格だ。歴史を紐解けば、デスクトップ描画にPostscriptを使ったシステムもあったようだ。

Postscriptはチューリング完全な計算力を持つ。そのため、プログラミングは可能である。

Common Lisp

1984年公開。設計者はScott Fahlman, Richard P. Gabriel, Dave Moon, Guy Steele, Dan Weinrebだ。ANSI規格にもなっている。

軽くまとめるつもりだったが、意外と時間がかかった。

ドワンゴ広告

この記事はドワンゴ勤務外に暇だったので書いた。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2016-02-25

C++標準化委員会の文書のレビュー: P0003R1-P028R1

P0003R1: Removing Deprecated Exception Specifications from C++17

道的な例外指定を取り除く提案。

動的例外指定とは以下のような機能をいう。

void f() throw( int, double, int * ) ;

C++98の規格が制定される頃には、すでに動的例外指定の利用例はほとんどなかった。C++11で、例外指定から動的例外指定に改名された上で、deprecated扱いにされた。

十分な移行期間を与えたので、C++17で取り除く。

P0005R3: Adopt 'not_fn' from Library Fundamentals 2 for C++17

Library Fundamentals TSで提案されているVariadic Templatesを使ったnot_fnを先行して標準規格に追加する提案。

deprecated扱いされたnot1, not2と違い、引数をいくらでも取れる。

template < typename ... Types >
bool f( Types ... args ) ;

int main()
{
    auto g = std::not_fn(&f) ;

    // 任意個の引数に対応
    g(1) ;
    g(1,2) ;
    g(1,2,3) ;
}

P0009r1 : Polymorphic Multidimensional Array Reference

配列のレイアウト(FORTRANの列優先レイアウトとCの行優先レイアウト)や、構造体の配列と配列の構造体(構造体の各データメンバーがそれぞれ配列になったレイアウト)などの差異を吸収するポリモーフィックな多次元配列ラッパーである、array_refライブラリの提案。

[PDF] P0010R0: Adding a subsection for concurrent random number generation in C++17

C++の乱数ライブラリは並列アクセスできないのでその注意を文面に追加する提案。

P0018R2: Lambda Capture of *this by Value as [=,*this]

lambda式に*thisを値でキャプチャする文法の追加。

lambda式は*thisを値でキャプチャーできない。

struct S
{
    int x ;
    auto f()
    {
        return [=]{ return x ; } ;
    }
} ;

int main()
{
    std::function<int()> f ;

    {
        S s ;
        f = s.f() ;
    }

    // 実行時エラー、オブジェクトsはすでに破棄されている。
    f() ; 

}

なぜならば、コピーしている値はthisポインターであって、*thisではないからだ。上記のコードで、[=]と[&]は同じ意味になる。

そのため、新しいsimple-captureとして、*thisを追加する提案。上記のコードは、以下のように書き換えればエラーにならない。

auto f()
{
    return [*this]{ return x ; }
}

P0019R1 : Atomic View

非アトミックオブジェクトに対してアトミック操作を提供するatomic_viewライブラリの提案。既存のコードの変数の定義を変えるのが現実的ではないコードに足して現実的なライブラリ。


int data ; // 変更不可能

void f()
{
    std::experimental::atomic_view adata( data ) ;
    ++data ; // アトミック操作
}

P0020r1 : Floating Point Atomic

浮動小数点数型に対して使えるatomic_viewライブラリ。

P0024R1: The Parallelism TS Should be Standardized

<algorithm>に並列実行版を追加するParallelism TSの実装経験を検討した結果、標準規格に取り入れるべきであるとする提案。

[PDF] P0028R1: Using non-standard attributes

attirbuteの名前空間の省略記法の提案。

独自のattributeトークンを使った独自拡張は、トークンの重複を防ぐためにattribute名前空間を使うことが多い。

void f() {
    [[rpr:: kernel, rpr:: target(cpu,gpu)]]
    do task();
}

しかし、attribute名前空間をいちいち指定するのは面倒なので、using宣言に相当するような機能がほしい。そこで、この提案は、そのような機能を付け加える。

void g() {
    [[ using rpr: kernel, target(cpu,gpu)]]
    do task();
}

キーワードはとりあえずusingにしているが、変わるかもしれない。

ドワンゴ広告

来月はドワンゴのセミナールームでだいぶ血の気のあらそうな勉強会が開催されます。

歌舞伎座.tech#9「異種プログラミング言語格闘勉強会」 - connpass

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0