自作キーボードとクセをすり合わせる話
この記事は自作キーボード Advent Calendar 2017の4日目です。前日は、@mt_mukko さんの「Nyquistを組み立てた話。Pro Microもげもあるよ!」でした(この記事は ThinkPad T460s で書いてます)。
Let's Split を組み立てた
@matsPod さんの Group Buy に参加して Let's Split のパーツを購入したものの、転職やら何やらでバタバタしていてようやく組み上げたのが 10 月…。
皆に遅れること数ヶ月、ようやく僕の #レツプリ が完成したでござる。RGB どうしようかと思ったけど、やっぱつけると綺麗ね。 pic.twitter.com/uGCEM2Zh1A
— Yuta Okamoto (@okapies) 2017年10月21日
#レツプリ 組み立て中動画(ブログ用。 pic.twitter.com/KhtjeKGMBY
— Yuta Okamoto (@okapies) 2017年12月4日
現在は職場で活躍中。机の上を広く使えるのがいい感じ。
仕事で #レツプリ を使い始めました。まだ色々と調整中。 pic.twitter.com/kaLvSGRPAM
— Yuta Okamoto (@okapies) 2017年10月30日
キー配列の調整
さて、上のツイートに謎のポストイットが写っているが、これは使っている最中に気付いた点をメモっているものだ。これを元にしてキー配列をどう変更するか考えたりしている。言うまでもなく、自作キーボードの魅力の一つは自分の好みに合わせてキー配列を自由に設定できること。
現在は、以下のような配列にしている。記号の位置についてはまだまだ調整を続けているし、Lower/Raise と無変換/変換のデュアルキー化がうまく設定できてないなど課題が多いものの、ひとまず日常業務で支障のない程度には仕上がった。
最初のツイートと見比べてもらうと分かると思うが、初期配列からそこまで大きな変更はしていない。QWERTY 配列そのものとか、Ctrl や Alt などの修飾キーの位置は、昔から愛用している HHKB に合わせるようにしている。
最も頻繁に変更しているのは、Lower/Raise と組み合わせる記号キーだ。Let's Split が 40% キーボードである以上、これらのキーをどこかに押し込む必要があるが、どこでもいいというわけではない。自分がプログラミングや日本語入力をする上で頻出するキータイプの順番というものがあるので、その流れに沿ってタイプしやすい配置を探す必要がある。
面白いのは、単純に頻出するキー同士を近くに置けば良いというものではないらしい、ということだ。経験的には、右手と左手を交互に動かしたり、手首の回転を使うような動きは安定感が高い。
こうして、キーを通常とは別の場所に設定していると「あのキーはどこに置いたっけ」となることが、まぁ…稀によくある(笑。この点については、上の写真を見てもらうと分かるように、キーキャップをアルファベットではなく Lower/Raise レイヤーの記号に対応したものにして解決している。一見すると奇妙に感じると思うが、どの道、アルファベットはブラインドタッチしているのであまり問題がないという寸法。
他にも、Lower/Raise は他のキーとは別形状のキーキャップを持ってきて角度を付けることで、親指で探りやすいようにしている。
キーボードと自分のクセをすり合わせる
上の写真を見て、わりと保守的なキー配列だなと思った人も多いと思う。これは Let's Split を使っているからといって他のキーボードを使う機会が無くなるわけではない、という単純な理由による。僕がキーボードを自作しているのは、身体への負担を減らして効率的に作業をするためなので、一般的でないキー配列を採用して効率を下げては元も子もないし。
一方で、多少のキー配置の変更は慣れで何とかなる部分も大きい。僕の場合、記号の位置は一週間か二週間もすれば体が覚えてしまうし、そこで他のキーボードに一時的にスイッチしても問題なく扱える。
自作キーボードに対するよくある懸念として、標準的でないキー配列ではまともにタイプできないのではないか、というものがある。僕は、自分の経験を通じて人間の適応性は自分自身で思っている以上に高いのでそこまで心配する必要はない、と考えるようになった。キー配置の変更、というのは市販キーボードでも論争のタネになりがちなテーマだが、この点を過大に見積もって新しい可能性に手を出さないのは人生の損失…というのは言い過ぎだろうか。
このように、自作キーボードには「自分のクセをキーボードに合わせる」方向と「キーボードを自分のクセ(習慣)に合わせる」方向の、二つの方向性があるように思う。
これは、どちらかが正しいという話ではない。二つの相反する要求のバランスを取っていく中で、自分が無意識のうちに従っていた習慣を一つ一つ発見し、何を守りどこで殻を破っていくか考えていくのが、自作キーボードという趣味の一つの醍醐味だろう。
「先生のレポートは形式的な縛りが多すぎる。自分はもっと自由に書きたい」という学生からの批判が。ひとまず「形式は、君が既に縛られているものから、君を別様に縛り直す過程で、君を相対的に自由にする道具です。縛りが無ければ自由と考える君は、死ぬまで偶然と慣習の奴隷でしょう」と答えました。
— 久保田裕之(家族社会学) (@hkubota1016) 2017年5月1日
これは、万人にとっての〈理想のキー配列〉は存在しない、ということでもある。キーボードと自分のクセをすり合わせていく際に、使ってみて課題を発見して修正する、というプロセスを回していくと、個々のキー配列はその時点での自分に合ったものでしかない、ということになるからだ。
このことは、自作キーボードの普及を考える上で悩ましいポイントではある。キー配列を編集する GUI エディタのようなものはすでにあるが、日本語で使うキーに十分に対応していないものも多い。その辺はコミュニティで解決していくべき課題なのかもしれない。
Akka HTTP クライアントを使う
この記事は Scala Advent Calendar 2017 の三日目です。前回は @poad1010 さんの「JupyterでScala」でした。
Akka HTTP を使って REST API を叩いてみようと思って色々と試したメモ。基本的には下記のドキュメントを読めば良いのだけど、サーバ側はともかくクライアント側の使い方について日本語で書かれたものが少ないので、使う側の目線での話を書き残しておくのも良いでしょうという感じ。ここでは、最も簡単な API である Request-Level Client-Side API について話をする。
少し難しい話になるが、簡単に使いたい場合は、記事の最後にラッパーコードを貼っておくのでコピペして使ってもらうと良いかと思う。
HTTP ボディを取得する
ドキュメントを見ると、初っ端からこういう感じで脅されるので嫌な予感がすると思うが、その予感は的中する。
「ストリームが一級市民」ではない HTTP クライアントに慣れている人は、最初に Akka HTTP クライアントの裏側にあるフルスタックなストリーミングの概念について説明した「リクエストとレスポンスのエンティティがストリームの性質を持つとはどういう事か」の章を読むことをお勧めします。
とは言っても、レスポンスを受け取るところまでは特に難しいところはなく、単に Http().singleRequest()
に HttpRequest
を渡すだけだ(以下では、スコープに implicit な ActorSystem
, Materializer
, ExecutionContext
が入っていることを前提に話を進める):
implicit val system: ActorSystem = ActorSystem() implicit val materializer: ActorMaterializer = ActorMaterializer() implicit val executionContext: ExecutionContext = ... val request = HttpRequest(uri = Uri("http://example.com/api/v1/users")) val response: Future[HttpResponse] = Http().singleRequest(request)
ややこしいのはレスポンスボディをメモリに読み込むところで、HttpResponse
を見てもそれらしいメソッドが見当たらない。結論から言うと、以下のようにする必要がある。
val body: Future[String] = response.flatMap(_.entity.dataBytes.runFold(ByteString.empty)(_ ++ _).map(_.utf8String))
なぜこういう書き方をする必要があるかというと、HttpEntity
から取得できる dataBytes
は Akka Streams のストリーム (Source[ByteString, Any]
) だから。
Akka HTTP はストリームベースのライブラリなので、サーバから到着したレスポンスを全てメモリに貯めこんでからユーザに引き渡すのではなく、バイト列が到着するたびにイベントを発火して処理する。これにより、例えば巨大なデータファイルや終端がない (unbounded) サーバログのようなようなレスポンスを効率的に扱うことができ、細かい制御(チャンクの区切り方とか)も容易になる。
一方で、従来のように文字列として全体を一回でアクセスできるようにするには、
- 受信した複数のバイト列を全て足しあわせて一つのバイト列に畳み込む (
.runFold(ByteString.empty)(_ ++ _)
) - バイト列を文字列に変換する (
.map(_.utf8String)
)
という処理を明示的に記述する必要がある(ちなみに、1 と 2 を逆にすると多分文字化けが起きる。理由は考えてみよう)。分かってしまえば大した話ではないが、カジュアルな API を期待していると面食らうのは確かだ。
もう一つ注意点があり、Akka HTTP は送信側のデータ送信量を TCP レベルでスロットリング (TCP back-pressure) しているので、あるレスポンスのエンティティを消費せずに途中で放り出してしまうと、その TCP 接続の送信が詰まってしまい、その接続を利用している他のリクエストの処理に影響が出る。したがって、エラーの場合でも必ず response.discardEntityBytes()
を呼び出す必要がある(将来的には自動検出できるようにしたいらしい)。
なお、全てのレスポンスをメモリに読み込む方法はもう一つあり、以下のように toStrict(timeout)
を呼ぶと Future[HttpEntity.Strict}
を取得できる。Strict
を使うと受信したバイト列を集約した data
にアクセスできるので、以下のように書ける:
import scala.concurrent.duration._ val timeout: FiniteDuration = 10.seconds val body: Future[String] = response.flatMap(_.entity.toStrict(timeout).map(_.data.utf8String))
toStrict
はタイムアウトを指定する必要があるが、レスポンスを待つ時間を明示的に指定するならこちらを使うべきだろう(runFold
を使う場合は idle timeout が成立するまで待つ)。
また、タイムアウトは FiniteDuration
という型名が示すとおり「無限」は指定できない。「タイムアウトが無限」はナンセンスである、というライブラリ作者たちの意思表示なので、いつまでも待ち続けたいお気持ちを表明する場合は適当に 100 万秒とかを指定すると良い。
JSON を変換 (unmarshal) する
メモリに読み込んだ JSON 文字列をアプリケーション内部の形式に変換するには、Akka HTTP が提供する Unmarshal(...).to[A]
を使う。ただ、Unmarshal
自体は単なるラッパーで、具体的な処理は他の JSON パーサーに委譲する仕組みになっている。なので、好きなライブラリを直接使っても構わない。
標準では spary-json のラッパーが提供されている。使うには、ライブラリの依存関係に akka-http-spray-json を追加する。
libraryDependencies += "com.typesafe.akka" %% "akka-http-spray-json" % "10.0.11"
例として、JSON を User
型にマッピング (jsonFromat2()
) して Unmarshal
してみる。akka-http-spray-json を使うには SprayJsonSupport
の配下の implicit
をスコープに入れる。こんな感じだろうか:
import akka.http.scaladsl.unmarshalling._ import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport import spray.json._ case class User(id: Long, name: String) trait JsonSupport extends SprayJsonSupport with DefaultJsonProtocol { implicit val UserFormat = jsonFormat2(User) } class FooClient() extends JsonSupport { val res = Http().singleRequest(HttpRequest(uri = Uri("http://example.com/api/v1/users/1"))) res.entity.dataBytes .runFold(ByteString.empty)(_ ++ _) .flatMap(bs => Unmarshal(bs.utf8String).to[User]) }
spray-json ではなく、他の Jackson や circe などのライブラリを使いたい場合は、それぞれに対して Unmarshaller
を実装した akka-http-json というサードパーティのライブラリの開発が進んでいる。
ラッパーを作る
以上のノウハウをまとめて、こういう感じのラッパーを作っておくと便利なのではないかと思う。言うまでもなく、このコードで 10 GB のデータファイルとかを受け取るとヒープメモリが爆発四散するので、その場合はストリームの作法に従って書こう。
def doRequest[A](req: HttpRequest, unmarshal: String => Future[A]): Future[A] = Http().singleRequest(req).transformWith { case Success(res) if res.status == StatusCodes.OK => res.entity.dataBytes .runFold(ByteString.empty)(_ ++ _) .flatMap(bs => unmarshal(bs.utf8String)) case Success(res) => res.discardEntityBytes() Future.failed(new Exception(s"HttpRequest failed: $res")) case Failure(t) => Future.failed(t) }
追記: Unmarshal
に HttpEntity
を直接与えることで、より短く書くことができる:
def doRequest[A](request: HttpRequest) (implicit unmarshaller: FromEntityUnmarshaller[A]): Future[A] = Http().singleRequest(request).transformWith { case Success(res) if res.status == StatusCodes.OK => Unmarshal(res.entity).to[A] case Success(res) => res.discardEntityBytes() Future.failed(new Exception(s"HttpRequest failed: $res")) case Failure(t) => Future.failed(t) }
これは、FromEntityUnmarshaller[A]
の実装がバイト列の集約を実装している Unmarshaller.byteStringUnmarshaller
を呼び出すため(実装を見ると runFold(...)
による畳み込みをしているのが分かる)。
まとめ
Akka HTTP はドキュメントが充実しており、ライブラリの思想や使う上で必要なことは概ね書かれている。また、機能的、非機能的な制約が型として埋め込まれており、自分がどんなコードを書こうとしているのか、常にプログラマに意識させるような作りになっている。
ただ、それはごまかしが効きにくいということでもある。「サーバからデータをガサッと持ってきてババッて変換してさー」的なやり方は技術的にはいくつも穴があるが、ちょっとした作業では不問に付したい場合も多い。なので、Akka HTTP は日々の作業をアドホックにこなしていくツールとしては使いにくい点が多い。ただ、堅牢で高性能なアプリケーションを書く上では強力な道具になりうると感じた。
最近、SoftwareMill が開発する sttp が 1.0 になった。これは、akka-http や async-http-client などをラップしてシンプルな API を提供することを目的としている。こうしたライブラリを、作業に求められている品質に応じて使い分けていくのが良いのではないかと思う。
参考文献
- Consuming HTTP-based Services (Client-Side) • Akka HTTP
- Request-Level Client-Side API • Akka HTTP
- Akka HTTP Timeouts • Akka HTTP
- Akka HTTP, docs: Explain toStrict in more detail · Issue #206 · akka/akka-http · GitHub
- akka stream - Why HttpEntity.toStrict has no variant without a timeout? - Stack Overflow
- JSON handling in akka-http
ネットワークは「切断」しない
Disconnect という英単語を「切断」と訳すのは(特に IT エンジニアリングの文脈では)誤解の余地が大きいので良くないのではないか、という話。
Connect は「結線」しない
Connect という英単語は、一般的に「繋ぐ」とか「接続する」と訳されることが多いと思う。connect は、元々「互いに結びつける」という意味のラテン語から来ていて、初期には「物理的に一つにする」という意味で使われていたようだ。しかし今日では:
connect
- Bring together or into contact so that a real or notional link is established.
- Join together so as to provide access and communication.
- Link to a power or water supply.
- Put (someone) into contact by telephone.
- [no object] (of a train, bus, aircraft, etc.) be timed to arrive at its destination just before another train, bus, etc., departs so that passengers can transfer.
- Associate or relate (something) in some respect.
- Provide or have a link or relationship with.
- [no object] Form a relationship or feel an affinity.
connect - definition of connect in English | Oxford Dictionaries
上記のように、物理的な接続だけではなく、観念的な結びつき (link) とか関わり合い (relationship) を表すのにも使われている。
日本語で「接続する」と書くと、何となく媒体(メディア)を介して二つのモノを物理的に結線する様子を思い浮かべがちだ。しかし、どちらかというと「二者の間に関係性を作る」というニュアンスで理解するのが正しいだろう。
接続は「切断」されない
例えば、「列車の接続がいい」という表現が使われるように、connect を「接続」と訳すのは間違いではない。また、その対義語である disconnect は一般的に「切断」と訳されるが、その意味は英語でも “break the connection”、つまり connection を壊すとか断つとかいう意味になる。
だが、繋がり (connection) を断ち切るとはどういうことだろうか?
そもそも「繋がり」とは何か。ここでは、互いの存在を認識した上で、媒体を介して情報(やエネルギーや社会的な何か)を交換すること、と定義してみよう。既に見たように connection が指す「繋がり」には、物理的なものだけでなく観念的なものも含まれる。注意が必要なのは、disconnect が断つのは「繋がり」であって「媒体」ではないということだ。
あらゆる繋がりは媒体を介した交換行為を通じて実現される。そして、媒体が断たれれば繋がりも断たれることが多いので、我々は両者を同一視しがちだ。しかし、逆は真ではない。つまり、媒体が断たれなくても繋がりが断たれることはある。この世から公衆電話網が無くならなくても、友達同士は絶交できる。
disconnect を「切断」と表現すると、状態がゼロイチでキレイに切り替わる様を想像しがちだが、しかしコトはそう単純ではない。なぜなら、媒体の接続性はそれ自身で完結する問題であるのに対し、繋がりは二者の関係性、つまりお互いが相手のことをどう認識しているかの問題だからだ。
例えば、媒体に(一時的に)障害が起きると二者は一切情報を交換できなくなる。あるいは、情報の一部だけがたまたま失われて届かないような場合もあるだろう。しかし、二者の繋がりは障害が起きた途端に断たれるわけではない。お互いが諦めない限り、媒体の障害が回復した時点で再び交換が行えるようになるからだ。それでも繋がりが断たれるとしたら、例えば、以下のようなことがあった場合だろう:
- どちらかが、相手との交換の意思を捨てる
- 相手に通知して辞める場合も、そうでない場合もあるだろう
- 媒体の障害が原因の場合、一定期間待っても復活しない時点で「媒体はもう二度と復活しないに違いない」と予測して諦めたのだろう(=タイムアウト)
- どちらかが、媒体の先にいる相手が自分との交換の意思を持っていると信じられなくなる
黒やぎさんは、白やぎさんから届いた手紙を食べてしまって、しかも返事を書くのを忘れているだけなのかもしれない。ここで白やぎさんが「黒やぎさんに手紙は届かない」とか「黒やぎさんに無視された」と判断すれば、両者の関係は disconnect される。しかし、それは「白やぎがそう判断した」というだけだ。この時、媒体に物理的な変化は何も起きていない。
特に、「相手が自分との関係をどう思っているか」を知るのは難しい。それを知るためにすら、媒体を介して相手にコミュニケーションを試みるよりないからだ。コミュニケーションを取らなければ家族や恋人が何を考えているのか分からず、相手に示す適切な愛情表現を選べないのと同じように。
ネットワークは「切断」しない
ここまでの話を踏まえると、特に TCP/IP のようなパケット通信において「ネットワークが切断」という表現は、何となく不自然なものに見えてくる:
try { final URL url = new URL("http://example.com"); final InputStream in = url.openConnection().getInputStream(); System.out.println(in.read()); } catch (IOException e) { System.err.println("ネットワークが切断されました!"); // (1) }
ここでの IOException
は、多くの場合、おそらくはネットワークの経路上で輻輳が発生したために、HTTP プロトコルに基づく接続 (url.openConnection()
) や読み込み (in.read()
) の通信が正常に完了しなかったというだけだ。ネットワークという「媒体」そのものが切断されたわけではない。
もちろん、日常の業務では様々な障害発生ケースを念頭に置いた上で、その簡便な表現として「切断」という単語が使われている。しかし、我々はふとすると、ネットワーク経路がゼロイチで開通したり不通になったりすると考えたり、そもそも媒体が完全に正常でも通信の失敗が起きうる(片側のプロセスが応答しなくなるとか)ということを忘れたりしがちだ。
何をもって「通信障害が起きている」と判断すべきかは難しい。例えば、上記で (1)
のパスを通った時点で http://example.com
への経路が死んでいると判断…するのは難しい。その時、たまたまパケット損失が起きただけなのかもしれないからだ。
通信障害が発生しているか否かは、実務的には統計量に基づいて判断するしかない。従って、上記のような「一回ごとの通信」について記述しているコードでそれに対処することはできないだろう。それを忘れると、一度でも IO 例外が起きたらその経路は不通と判断する、みたいなコードを書いてしまうことになる。
まとめ
connect/disconnect とは二者の間に関係を作ったり無くしたりすることであり、二者の関係性を取り持つ媒体はその本質ではない。そして「切断」という語は、二者間の繋がりの有無がゼロイチで判定できるかのような誤解を生み出しがちなので、あまりよろしくないのではないか。
まぁ、すごく細かいことにこだわっているような気もするのだが、一度自分の考えをまとめてみるのも良いかと思って書いてみた次第。
「裏のニコニコ超会議」に行ってみた
GW中の皆さん、休暇をいかがお過ごしだろうか? え、ずっと仕事? それはご愁傷様…。
さて、我々(オタク)にとってGW期間中のビッグイベントといえば、4/29~30 に幕張メッセで開催された「ニコニコ超会議」だろう。今年も 15 万人越を動員して大盛況だったようで、今年は僕も久々に顔を出して知り合いやマストドン本の関係者に挨拶して回ったりしていたけれど、相変わらずのカオスな活気だった。
しかし、その盛況の陰で「裏のニコニコ超会議」とも言える音楽フェスが開催されていたことをあなたはご存じだろうか? ずばり、その名を Electric Daisy Carnival Japan (EDC Japan) という…。
「裏」って?
まぁ、こういうことです:
そう、正真正銘、超会議の裏が会場なのだ。期間も全く同じなので、超会議でオタクや中高生がワイワイやってる隣で、パリピの皆さんがウェイウェイやっていたというわけ。
その結果としてこんな光景も見られた:
刺青入れたパリピのカップルの隣でサーバルちゃんコスの女の子が携帯いじってる。
— Yuta Okamoto (@okapies) 2017年4月30日
EDC って?
EDC は、EDM というこの十年くらい世界的に流行しているダンスミュージックをかける DJ イベント、いわゆる EDM フェスのうちでは最大級のイベントで、世界三大フェスの一つと呼ばれているらしい。規模も桁違いで、ウン十万人分のチケットが一瞬で売り切れることも珍しくない。これまで三大フェス (Ultra Music Festival, Tomorrowland, EDC) のうち、日本で開催されていたのは Ultra Japan だけだったんだけど、今回 EDC が初来日したのだ。
japan.electricdaisycarnival.com
元々、僕は BEMANI がきっかけで電子音楽を聞くようになって、自然と流行りのジャンルである EDM にも触手を伸ばすようになり、そうした楽曲の主なパフォーマンスの場である EDM フェスにも興味があった。まぁ、僕は基本的にお祭り騒ぎを見るのが好きなので。
とはいえ、正直なところ、海外のフェスに関しては治安が悪いしドラッグが蔓延しているという話も耳にするので、わざわざ海外に行ってまで参加するのは敷居が高いナァと感じていた。そんな時、今回の日本での開催を聞きつけ、また以前から聴きたかった Zedd も出演するということで、これはいい機会だと当日券を握りしめて駆け付けた次第。
会場
この手の EDM フェスの特徴としては、とにかく設備や美術にカネがかかっていることが挙げられる。大音量のスピーカーや巨大なディスプレイの上に「おとぎの国」のような世界観を構築して、来場客の非日常感を盛り上げるための様々な仕掛けが凝らされている。
また、これはフォトジェニック(写真写りの良さ)を重視しているということでもあるようだ。この辺は、口コミでの拡散を狙った、いかにもインスタ世代らしい施策と言える。以下の動画が今回のトレイラーだけど、雰囲気は掴めるかと。
システムとしては、「踊ってみた」しかない超会議だと思えばよい。つまり、入場した後は3つある野外ステージのどれを見に行ってもいいという仕組み。出演者としては海外の人気 DJ を多数取り揃える一方で、一日目には中田ヤスタカときゃりーぱみゅぱみゅも出演していたらしい。
会場内を回ると各所にこういう装飾が置いてあり、夜はライティングされて雰囲気を盛り上げる。あと、写真の真ん中に映っているように仮装してきた人たちが結構いて、あちらこちらを闊歩している。
各ステージの様子を紹介しよう。まず、第一ステージは千葉マリンスタジアムの中に構築されてて、巨大なフクロウの像が観客を睥睨する荘厳な作りになっている。一方、第二ステージは海岸線沿いの砂浜にあって、DJ ブースの後ろに巨大なディスプレイが組まれており、演奏と同時にこれを活かした演出が行われる。
普通のコンサートと違うのは、ステージ後方の VIP エリアを除いて指定座席とかはないので、出演者のプレイが始まるとみんなワーッと DJ ブースの前に集まってきてこういう騒ぎになる:
…うーん、俺、よくここから生きて帰ってこれたな。*1
そして、次第に辺りが暗くなってくると「光」による演出が本格化してくる。ここからが、出演者的にも演出的にもフェスの本番だと言っていいだろう。
ステージは爆音で包まれ、頭上を何条ものレーザーが飛び交い、何万人という観客がすし詰め状態で踊り狂い、歌詞を合唱する。そんな中で頭をカラッポにしてひたすら恍惚感に浸るというのは、普段はなかなかできない貴重な体験だったと思う。
確かに、混じりっけ無し純度100%のリア充の中に飛び込むことになるので、我々みたいなオタクにとってかなり参加を躊躇する類のイベントなんだけど、周りに合わせていれば大体問題ないし、コミュ力も必要ないのでそういう意味では楽だった。
観客
既に紹介したように、フェスには仮装してやって来ている人たちがけっこう多い。こういう人たちを特集したユーチューバーの動画があったので紹介…するんだけど、肌の露出が多めなので一応閲覧注意。
しかし、ハロウィンもそうだけど、こういう仮装文化っていつの間にか定着したよね。一体どういう経路で浸透したんだろう。あと、動画には海外から参戦してる人がけっこう出てくるけど、これは実際にそうで、パッと周りを見渡すと必ず外人さんが視界に収まるくらいはいた。周りもちゃんと交流してて、全体的に英語スキルが高めだったという印象。真のコミュ力とは言葉の壁を超えるものなのかもしれない。
驚いたのは、観客みんなが流行りの曲の歌詞を全部覚えているらしいということ。DJ は、基本的に自分の曲だけでなく他人の曲を含めてどんどんプレイしていくので、観客は次に誰の何という曲がかかるかは予想できないんだけど、みんなイントロクイズばりに即座に曲名を割り出して大合唱が始まる。隣の人に聞いたところ「クラブの定番曲のベスト盤とかを聞いていればそのうち覚える」と言われたが…。
このように、「パリピ」について我々オタクの側からは「何も考えていない連中」みたいな偏見が広くあると思うが、これはこれでとても熱心なファン文化なんだな、ということが感じ取れたのは収穫だった。
共通点と差異
そんなわけで、今回、一日のうちにこういう両極端のイベントに参加して思ったのは、意外な感想だと思うけど「あれ、けっこう似てるな?」ということだった。
表面的な違いは山ほどあるんだけど、いろいろな場面で既視感を感じることが多かった。これは多分に感覚的なものだけど、実は世間で言われているほど根本のロジックに大きな違いはなくて、表現の手段が違うだけじゃないか、というようなことを思ったのだった(例えばコスプレ好きな事とか)。
まぁ、ウェイもオタクもお互いに鼻で笑いあってるけど(実際そういう発言は今日も現地で聞いた)ベクトルが違うだけで似たもの同士なんじゃないかと思いますけどね。どっちもコスプレや光りモノのガジェット好きだし。 https://t.co/3rZRrit3AT
— Yuta Okamoto (@okapies) 2017年4月30日
一方で、両者の最も大きな違いはビジネスモデルだろう。超会議が、何十もの「趣味」の島を束ねたロングテールモデルであるのに対して、EDC は高々2~3の島に有名アーティストを据えて集客するモデルだ。その結果として、超会議は EDC の倍近く動員することができている。
動員数 | チケット代 | 予想売上 | |
---|---|---|---|
超会議 | 15万4,601人 | 2,000 円 | 約 3 億円 |
EDC | 8万4,000人 | 16,000 円 | 約 13.4 億円 |
ただ、売上を比べると別の面も見えてくる。元々、超会議は「儲ける」ことを主眼にしたイベントではないとされているが、ここ数年は動員数が伸び悩んでいるようだ。一方で、EDC は同じロケーションで(チケット代だけ考えても)4倍以上の売上を叩き出している。そろそろ転換期なのかな、という気もするのだがどうだろう。
越境
リア充文化とオタク文化の越境、という話として、Porter Robinson(ポーター・ロビンソン)というアメリカ人アーティストを紹介して締めくくりとしたい。彼は EDC に出ていたわけではないんだけど、最近も来日公演があって大変すばらしいパフォーマンスだった(同業者からも称賛の声が相次いでいるとか)。*2
彼は、一般的に EDM の文脈で紹介されるアーティストで、世界の人気 DJ ランキング “Top 100 DJs” にランクインする実力者*3。ただ、本人の音楽性は EDM の主流とは少し雰囲気の違うもので、EDM というジャンル自体が「客を踊らせる」ことを突き詰め過ぎて単純化し多様性を失っている、という声が出ている中、次世代の旗手として期待する声も出ている、とかそういう立ち位置らしい。
個人的には、彼の曲の透明感がありつつ、どこか寂寥感を帯びた曲調が好きで愛聴している。そもそも、僕も EDM の主流のガチャガチャした雰囲気は苦手で、どちらかというと彼や Madeon のような曲調が好みなので、僕の EDM に関する知識はわりと偏っているんだけど…。
ところで、彼は日本文化に非常に造詣が深いことで知られている。造詣が深いというか、はっきり言うとガチヲタである。
そもそも、彼が音楽制作を始めたのは、言わずと知れた日本の音楽ゲーム “Dance Dance Revolution” をプレイしたのがきっかけであり*4、他にも彼に日本の深夜アニメの話を振ると熱く語り始めるとか、度々来日してオタク系の DJ イベントに出没しているらしいとか、自分の DJ パフォーマンスで欧米人相手に唐突に アニソンを 流し始める とか、そういう逸話に事欠かない。ちなみに、最近は「Re:ゼロ」のエミリア推しらしい。
楽曲制作の方でも、わざわざ許可を取って好きな声優の声をサンプリング *5したり、ボーカロイドに歌わせたりと趣味に走ってチャレンジを重ねていたのだが、盟友 Madeon とのコラボ楽曲 “Shelter” で、ついに自分の MV のためにアニメ制作を手掛けるに至った。それがこれ:
見てもらうと分かるが、欧米人が作るアニメによくあるような「バタ臭さ」が一切ない。最大の理由は制作に日本のアニメスタジオ (A-1 Pictures) が関わっているからだが、しかし全体のストーリーやキャラクターイメージの多くは Porter 自身のアイデアなんだとか。アニオタ DJ の面目躍如といったところか。
これが世界でどの程度受け入れられたかというと、現在の YouTube の再生数が 1,700 万越えを達成しており、なかなか成功した数字と言えるだろう。まぁ、先ほど挙げた Top 100 DJs 一位の Martin Garrix(彼は EDC Japan 一日目の大トリを務めた)の MV が軽々と1~10億を叩き出す世界なので、それと比べてしまうと見劣りはするのだが…。
とはいえ、日本のオタク文化が海外のオタクにウケている、という話から一歩踏み込んで、世界的なメジャーシーンの側から日本のオタク文化への越境を達成しつつあるわけで、十分に注目に値する試みと言えるだろう。インタビューによれば、Porter は今後もオーディエンスの反応を見つつ、オタク文化の良さを世界へ発信していきたいと考えているようだ。
ただ、翻って日本のオタク文化から世界のメジャーシーンへの越境ということが可能だろうかと考えると、なかなか課題は多そうだ。上で紹介した Porter の楽曲や DJ パフォーマンスを見ると、自分が好きなものを素材として積極的に使っていく一方で、(当たり前だが)内輪ネタ臭は極力取り除かれていることが分かる。それはもちろん、彼の軸足がメジャーシーンにあるからだ。
これは昔から繰り返されてきた話題なのだと思うが、オタク文化は内輪ネタとは切っても切り離せない関係がある。だから、メジャーへの露出を増やすために内輪ネタを排除する、というのは本末転倒な可能性がある。しかし、国内市場が飽和しつつある(参考: コミケの動員数)中で現状の水準を維持する方向は、新陳代謝を失って緩やかな衰退へと繋がる可能性もある。今や、2020年に向けて、様々なことが岐路にあると言うべきなのだろう。
まとめ
今回、超会議と EDC という全く性質は異なるがどこか似た所のあるイベントが並んで開催されたのは、色々なことを象徴していて面白い経験だった。面倒なこともあった(オタクだとバレて絡まれかけたりとか…)が、文化の越境というのはいつも新鮮な驚きがある。皆さんにもぜひお勧めしたい。
JAPAN 🇯🇵!!!!
— Zedd (@Zedd) 2017年4月30日
I LOVE YOU!!!!!!! ♥️♥️♥️ pic.twitter.com/5JJ7RrWRc0
Mastodon の電脳考古学、あるいは不在の中心としての Twitter について
突然ですが、5月始めに出る「マストドン本」に寄稿させて頂くことになりました。後半の技術パートの導入として、Mastodon の技術的な基盤である OStatus の章を担当しています。
本書の執筆には、mstdn.jp のぬるかるさんや pawoo.net の中の人に加えて、界隈では誰でも名前を知ってるような面々が勢ぞろいで、まさに Mastodon オールスターといった趣であり、わし本当にこんな所に混ざっていいのか…。まぁ、ともかく現在予約受付中です、買ってね!
これがマストドンだ! 使い方からインスタンスの作り方まで (NextPublishing)
- 作者: マストドン研究会
- 出版社/メーカー: インプレスR&D
- 発売日: 2017/05/12
- メディア: オンデマンド (ペーパーバック)
- この商品を含むブログ (1件) を見る
思い返すになかなかの急展開ですが、最初、降って湧いた Mastodon ブームに第二次 P2P ブームの面影を見て手を出したくなり、じゃあ Akka Streams で OStatus プロトコルを実装してみようかなと、さっそく OStatus API の挙動を調べるために Pawoo を curl
でつつき回したり、gist にまとめ記事を書いたりしていたところ、それを見ていた知人の紹介でインプレスさんから依頼を頂いたという次第です。
それが先週の中頃で、一昨日には校了したのでたった一週間で作られたことになります。当然、リアルで紙をやり取りしていては間に合わないので、原稿は Google Drive でやり取りし、著者同士の連絡調整は Facebook Messenger、書き上がったらその場で組版システムに突っ込んで出力結果を見ながら校正、という具合。出版に関わったのは初めてなんですが、最近はこんなスピード感なんですねぇ、いやはや。
担当編集者さん、さすがにこういう進行だと本当に大変そうで、時間が限られてる中で著者10人を相手に原稿集めて組版して校正してと大車輪でヒイヒイ言っておられました。おつかれさまです…。
Mastodon の電脳考古学
ところで、手元に作業時間と紙幅の関係で原稿に入れられなかった謎の図があるのですが、もったいないのでここに置いておきます。
これは、記事を書くにあたって OStatus の背景にある技術思想の歴史を押さえておいた方が良かろうと思い、関連するプロダクトや仕様書の日付を整理してみたものです。まぁ、これだけでは何のこっちゃという感じだと思うので詳しくは書籍をお買い求めください(宣伝)。
この辺の歴史は掘ってみるとなかなか面白いのですが、一つ問題があって、こうした経緯を語る資料が今まさに失われかけているってことですね。OStatus 関連、公式サイトどころか、仕様書自体がネットから消失しかけているものが多く、それを探し出すべくネットを徘徊していると「電脳考古学」という言葉を思い浮かべてしまう。たった十年前の話だというのに。
この辺、興味がある人は今のうちに資料を収集して保全しておくと良いんじゃないかしら。もう十年も経ったら何もかも電子の海の向こうへと消え去りそう。
「不在の中心」としての Twitter
最初に「今の Mastodon ブームを見ると過去の P2P ブームを思い出す」と書きましたが、ただ、ブームを駆動する動機は十年前とは大きく異なっているように思います。その根源は、ネットやそれを取り巻く社会のありようがこの十年で大きく変わったことにありそうだ、というのが僕の意見です。
ゼロ年代前半までのネットは、まだまだ社会の外部であるという意識を強く持っていたと思います。「ネットの自由」と「社会の規範」との間にある緊張関係は今よりもはるかに強く、またネット側の立場を強力に代表する人間や組織もなく、このままでは権威が介入して自由が全てスポイルされる日が来るのでは、という懸念が真剣に語られていた頃です。
そんな時代に分散システムが要請された理由は、一言で言えば「単一障害点をなくす」ということでした。責任主体の分散化、つまり責務を数多くの個人(が所有するコンピュータ)に「分権」して薄めることでシステムと参加者を守ろう、という動機があったわけです。
そして現在。今や、ネットは社会そのものとなりつつあり、また我々は Google や Twitter という中央集権的なシステムを信頼してネットを使うようになりました。そして、彼らは社会の一部に入り込んで「ネットの利益」を代表する存在となり、少なくとも民主主義陣営の国々の多くで、突然ネットに強力な規制がかけられる可能性は下がっています*1。
こうして、十年前と比べれば中央集権的な構造に対する警戒は(良くも悪くも)薄まっており、そういう切迫感が動機付けとなる状況ではなくなっています。例えば、GNU social 陣営と Mastodon 陣営の議論における微妙な温度差は、「自由」について常に危機感を持って活動してきた旧世代と、それをリスペクトしつつも切実さが薄い現行世代の違い…というまとめ方はいささか乱暴かもしれないですが、まぁそんなことも感じます。
では、こうした状況においてなお、我々が分権的なコミュニティを求める動機って何でしょうか?
僕は、「社会そのものと化したネットから一歩引く」という話なのだろうと思っています。全てがグローバルでフラットな場から撤退して、参加者や管理者の「顔」が見えやすい場を求めて移動し、ノイズが少なく心理的な安全性が高い少しだけ閉じたコミュニティを作る。この Mastodon ブームがどこまで続くかは不透明ですが、少なくとも、そういうバランスを取りたいという欲求の現れとして見ることはできそうな。
かと言って、これは Twitter の役割が終わったことを意味しないでしょう。なぜなら、今や Twitter とは概念であり、具体的に OStatus 互換実装たちが「連合」できるのはそのおかげだろうと思うからです。
記事にも少し書きましたが、僕は OStatus を構成する仕様のうち最も重要なのは、インスタンス間の通信プロトコルである PubSubHubbub や Salmon ではなく Atom フィードとその「語彙」だろうと思います。例えば、我々は「フォロー」という語彙が何を指すのか知っており、インスタンス間で「AはBをフォローする」というメッセージが伝えられた時に、利用者や異なる OStatus 実装がその意図を誤解する余地はありません*2。それに対して、そのペイロードを運ぶプロトコルはいくらでも取り換え可能だろうし、むしろもっと良い選択肢がありそうに思います。
思うに、OStatus は Twitter からの「脱出」を目指して作られたものですが、これらは不在の中心である Twitter の周りを巡っているが故に、バラバラにならずに済んでいるのだと思います。Twitter はマイクロブログの語彙を象徴する「バベルの塔」であり、仮に将来それが崩壊するようなことが起きれば、きっとまた、連合も維持できなくなるでしょう。
世界最小級のキーボード The Planck Keyboard を作ってみた
海外の自作キーボード (DIY keyboard) コミュニティで生まれ、近年は日本でもすっかり有名になった ErgoDox ですが、その ErgoDox と並ぶ人気を誇る "The Planck Keyboard" の DIY キットを手に入れて組み立ててみました。
どれくらい人気かというと、現在募集中の共同購入(後述)には開始から一週間で世界中から 1,700 件を超える応募があり、新しいカスタムキーキャップのメニューには大抵 Planck 専用セットが用意されるくらい。
過去の記事でも紹介してきた通り、僕は ErgoDox EZ キーボードを使っています。ErgoDox には大変満足していますが、一方でそれなりに細かい不満があるのも確かです。
ただ、普段使いの道具に対するこだわりというものは、突き詰めていくと極めて個人的なモノにならざるを得ません。必然的に、自分が真に求めるものと、汎用性への目配りが必要な完成品 *1 との間には埋めがたい齟齬が出てきます。
そんなわけで、将来的に自作キーボードの制作に手を出していくことを想定して、比較的に制作が簡単で入手の容易なコレを一個作ってみようと思った次第。噂の "40% keyboard" を試してもみたかったし。
Planck Keyboard できたー。半田付けスキルが上がったので、ひとまず所期の目標は達成。 pic.twitter.com/bT9L342xsN
— Yuta Okamoto (@okapies) 2017年3月11日
あとは、少し電子工作っぽいことをやってみたかったのもあります。IoT だなんだと言っているこのご時世に、物理レイヤから距離を取って出来合いのソフトウェアスタックの世界に引きこもっているのも如何なものかと思っていたので、少し自分の芸風を広げてみましょうと。
で、はんだ付けと聞くと一気に敷居が高く聞こえると思いますが、実際はきちんとした道具を揃えればそんなに難しくないですね。この記事では、はんだ付けの道具の揃え方やコツなどについても紹介していこうと思います。
Planck キーボードとは?
Planck は Jack Humbert 氏が開発・販売している DIY キーボードキットです。ErgoDox 使いには QMK firmware の作者と紹介するのが通りがいいでしょうか。いわゆる 40% keyboard プロジェクトの代表格で、その特異な格子状のキートップとミニマルな外観で有名です。姉妹プロジェクトに、サイズ違いの Preonic というものもあります。
Planck の特徴は公式サイトの "a DIY compact 40% ortholinear keyboard" という紹介で言い尽くされてますが、一つずつ見ていきましょう。以下、画像は氏が制作した販促ポスターより。
"ortholinear"
Planck はキーを格子状に配置するレイアウトになっています。"ortholinear" はこのようなキー配置を指す Jack さんの造語で、Planck キーボードの最大の特徴となっています。
一見すると奇抜に感じますが、そもそも論として「一般的なキーボードのキーが互い違い (staggered) に配置されてるのは、かつてのタイプライターの機構上の都合 *2 でしかない」ということらしい。実際、格子状の配置とすることでレイアウトが左右対称になりフットプリントを最小に抑えられるわけで、なかなか興味深いコンセプトと言えます。
"compact 40%"
お気付きかと思いますが、Planck にはキーが 47~48 個しかありません。これは通常のキーボードの約 40 % で、特に数字キーの列が影も形もありません。これは、主要なキーをホームポジションの隣のみに限定することで、指の移動 (finger travel) を最小限にすることを狙った配置になっているからです。
けれど、76 キーの ErgoDox でさえ「右側のキーが足りない」という声が聞かれるくらいなのに、こんなにバッサリと削ってしまっては実用に耐えないのでは?
心配ご無用。最下段のスペースキーの隣にある "Raise" と "Lower" はファンクション (Fn) キーになっていて、これと組み合わせればホームポジションを崩さずに物理キーの2倍以上のキーにアクセスできます。二つの Fn キーが親指位置に置かれているのもポイントで、直線的でエルゴノミクス性をガン無視しているかのような外観なのに、実は「親指活用」を重視したキーボードなのです。
"DIY"
ErgoDox と同様に、自分でプログラムした QMK firmware を書き込むことでキー割り当てを自分好みにカスタマイズできます。また、LED の取り付けに対応しているので、バックライト仕様に変更してファームウェアで光り方を制御できます。あと、基板にスピーカーが組み込まれているので、キーボードで音楽を演奏するなんてことも可能。
購入方法
3/26 現在、Massdrop で DIY キットの共同購入 (group buy) を実施中です。海外からの輸入になりますが、販売者や工場との間に Massdrop が入ってくれるので比較的安心ですし、日本への配送も問題なく行ってくれます。締め切りが3月末なのであと一週間もないですが、必要なパーツがまとめて安く揃う貴重な機会なので興味のある方はお見逃しなく(次の募集はおそらく三か月~半年後かと)。
いろいろなオプションがありますが、Plate は MX compatible、Switch は純正の Cherry MX か互換品の Gateron を選んでおくのが無難でしょう(Matias スイッチを買ってもいいですが、カスタムキーキャップの入手性が低いのでお勧めしません)。軸色による押下感の違いはこちらの記事が参考になります。
また、キーキャップについては、同時開催の別枠の drop で文字入りのセットが安価に提供されています。
今回は、昨年末に作者のサイトから直接購入したものを使いました。現時点では、Massdrop に出品されているものより古いバージョンの plate しか買えないようなので注意。
また、キーキャップとスイッチは OLKB では Matias スイッチしか提供してない ので、Cherry 互換を使いたい場合は別に調達する必要があります。スイッチは日本でも純正の Cherry MX スイッチを売ってくれる所がありますが、意外にも一番手に入れにくいのはキーキャップです。これらの入手方法については以前の ErgoDox の記事を参考にしてください。
道具を揃える
前述のとおり、Planck は DIY キットなので基本的に完成品の販売はありません。とはいえ、必要な部品は全て加工済みで売ってくれるし、組み立ても簡単なので苦労する所はほぼないです。唯一の問題は、基板にキースイッチを取り付けるのにはんだ付けが必要なところで、そこを敷居が高いと感じる人も多いでしょう。
半田付けの道具が揃った(※半田ごて以外 pic.twitter.com/Vt8zK1aa9X
— Yuta Okamoto (@okapies) 2017年3月4日
ただ、今回やってみたところ「まともな道具さえ揃えれば非常に簡単」という感想でした。最低限、以下のものがあればいいでしょう:
- 糸はんだ(すず 60%/鉛 40%、Φ 0.8~1.0 mm、やに入り)
- はんだごて(温度調整機能付き)と 2C 型のこて先
- こて台(簡易型ではない重いやつ)
- クリーニングワイヤ(こて台に付属している場合もある)
- 工作マット(机を汚れや高温から保護する)
この中で特に重要なのがはんだごてです。千円以下で買える安いものもありますが、断然「温度調整機能付き」のものをお勧めします。少し値が張るものの、作業のやり易さとはんだの品質が天と地ほど違います。学校で安いはんだごてで実習をやらされてトラウマになってる人も多かろうと思いますが、能力不足は全てカネが解決します。ぜひお試しあれ。
また、はんだごてを買うと標準で付いてくる円錐形のこて先(B 型)は実は使いにくいので、別途 2C (or 3C) 型 *3 のこて先を入手して付け替えましょう。C 型のこて先の特徴については以下のページなど:
はんだは、あまり太いと融けにくいので Φ 0.8 mm 程度が良いようです。環境に優しい「無鉛はんだ」というものが売っていると思いますが、融点が高くて扱いにくいので初心者はやめておいた方が無難。
こて台は、ひっくり返ってケガをしないように重いやつにしましょう。また、こて先を掃除するために水を含ませたスポンジを使うのが一般的ですが、温度調整機能付きのこてを使う場合は温度が下がらないようにクリーニングワイヤを使う方が良いようです。こて台とセットの製品があるので、入手できるならそれを。
購入方法ですが、この辺の道具はホームセンターや家電量販店では品揃えが悪く、困った時の Amazon もイマイチだったので、ヨドバシドットコムで買うのが一番早いと思います。ブランドは HAKKO(白光)と goot(太洋電機産業)がメジャーみたいなので好きな方を。今回は基本的に HAKKO 製で統一しました。
組み立てる
組み立て方については、基本的には公式サイトのドキュメントを熟読してください。ここでは、作業の進め方のイメージ作りの一助として、僕が実際にやった作業を簡単に紹介します。
概要
以下の手順で組み立てていきます:
- 基板の動作確認
- プレートにキースイッチを組み込む
- スイッチを基板にはんだ付けする
- スイッチの動作確認
- 基板をケースに取り付けてキーキャップをはめる
- 完成!
1. 基板の動作確認
組み立て終わっていざ電源投入したら認識しませんでした…は悲しすぎるので、念のために動作確認しておきましょう。基板には初期ファームウェアが書き込まれているので、PC に USB ケーブルで接続すれば認識してくれます。成功すれば、表面に実装された LED が緑に点灯してスピーカーからビープ音が出るはずです。
2. キースイッチの組み込み
次にキースイッチをプレートに取り付けていきますが、公式の手順ではまず数個だけ取り付けて確認することを推奨しています。スイッチを取り付けた後に基板を裏からはめてケースに納めてみて、基板の向きが正しいこと、スイッチのピンが基板の穴からまっすぐ出ていることを確認しましょう。
確認が終わったらケースから取り出し、残りのスイッチを全てプレートにはめ込みます。
全てはめ込んだら、基板をプレート側へ軽く押し込み、全てのピンが基板の穴から同じ長さだけ飛び出していることを確認しましょう。ピンを曲げてしまわないように注意。
3. スイッチのはんだ付け
さァ、一番楽しいスーパーはんだ付けタイムです。安全にはくれぐれも気を付けましょう。例えば、こての電気コードを蹴っ飛ばす等の事故を起こさないように、コードの長さには余裕を持ち、作業机の周りはよく整頓しておきましょう。あと、煙は有害物質なのできちんと換気しましょう。
こての温度は 340~360 ℃に調節するのが良いようです。これより高くても低くても良くありません。以下の動画のように、こて先をスイッチのピンとランド(基板の金色の部分)に押し当てて何秒か加熱したら、はんだをピンとランドの間へ送り込みます。この際、量は多くても少なくても良くないとか…。
いい道具(温度調節機能付き)を使うとここまで楽だとは…。中学校の頃の自分に教えてやりたい。 pic.twitter.com/39xD8J4Tib
— Yuta Okamoto (@okapies) 2017年3月11日
注意点は、「はんだをこて先へ直接押し付けない」「こて先との接触面積が大きいほど熱を伝えやすい」の二点です。もし C 型のこて先を使っているなら、こて先の面の部分を加熱する部分に押し当てて使うことになります。また、こて先に黒い汚れが付着してきたらワイヤーにグサグサ刺して拭き取りましょう。
その他のはんだ付けのコツについては、色々なサイトで紹介されているので探してみてください。まぁ、十年こてを触ってなかった僕でも何とかなったので、あまり細かいことを気にする必要はないかも。それよりも、繰り返しになりますが安全に気を使ってください。
4. スイッチの動作確認
はんだ付けが終わったら PC に繋いでスイッチの動作をテストしてみましょう。
至極当然ながらこの状態でも動く。 pic.twitter.com/0WYfpKF7ah
— Yuta Okamoto (@okapies) 2017年3月11日
5. ケースに取り付ける
動作確認が済んだら、プレートと基板をケースにねじ止めします。
あとは好きなキーキャップをはめて完成!
ファームウェアのカスタマイズ
現時点ではファームウェアの書き換えまではやれていないので、書き換え手順を示したページだけご紹介します(Easy AVR は GUI でファームウェアをカスタマイズできるソフトなのかな)。
また、ErgoDox EZ と同じ QMK firmware を使うので、ビルド方法については下記の記事が参考になると思います:
まとめ
QMK firmware の対応キーボードを見たことがある人は分かると思いますが、DIY キーボードコミュニティでは、Planck 以外にも実に様々なプロジェクトが活動しています。この記事が、自作キーボードに関心を持つ人が一歩を踏み出す助けになれば幸いです。
実は、キット自体は昨年末に発注していて1月には届いていたんだけど、道具の入手や場所の確保はどうしようか…と色々と悩んでいるうちにズルズルと時が過ぎ、完成までだいぶ時間がかかってしまったのでした。今回、電子工作の初歩中の初歩的な内容とはいえ、実際にキーボードを一つ組み上げたことでだいぶ自信がつきました。次は、「左右分割型 Planck」とも言える Let's Split に手を出してみようかと思案中(4月中旬に在庫が復活するらしい)。
「関数型プログラミングって何?」日本語訳
この記事は、技術翻訳 Advent Calendar 2016 の15日目です(枠が空いてたので勝手にお邪魔してます)。前回(6日目)は、id:msyksphinz さんの「個人が趣味で技術書を翻訳するという意義について」でした。
今回ご紹介するのは、昨年末に公開された Kris Jenkins さん (@krisajenkins) の "What Is Functional Programming?" です。日本語訳の公開については著者から承諾済みです。また、London Functional Programmers meetup での同タイトルの講演動画が公開されています。
関数型プログラミングの考え方は、世間ではどうも小難しい話だと思われている節があります。その理由の一つに、議論の抽象度が(比較的)高いことが挙げられるでしょう。例えば、以前このブログで紹介した「なぜ関数プログラミングは重要か」も、関数型プログラミングの本質をコンパクトに抽出した優れた論文なのですが、いかんせん数学的な考え方に慣れていない方にはとっつきにくい面がありました。
しかし、この記事では、我々が日々の仕事をこなしていく上で、関数型プログラミングがいかに実践的な方法論であるかを平易かつ具体的に説いています。特に、数学は一切出てこないのでご安心ください。
(いちおう技術翻訳ネタにも触れておくと、この記事、読む分にはスルスル読めたので楽勝かなーと思ってたんだけどそんなことは無かった…。以前 ScalaMatsuri ブログでも検証した通り、Google 翻訳の精度が上がってるので併用したら少しは楽になるかと思ったけど、こういう口語的な言い回しを多用する文章にはまるで無力でした。まる。)
関数型プログラミングって何? (What Is Functional Programming?)
これは、関数型プログラミングの本質は何なのかってことについての僕の見解で、とにかく目先の仕事を片づけたいと思っている職業プログラマ (jobbing programmer) に向けて書いたものだ。
この記事で僕が伝えたいのは、君が書くあらゆる関数には二組の入力と二組の出力があるってことだ。
二つ? え、一つだけでしょ?
いいや、二つ。間違いなく二つだ。一つ目のペアについて例を見てみよう:
public int square(int x) { return x * x; } // 補足: これが何の言語かは重要じゃないけど、入力と出力の型を強調するために明示的に宣言する言語を選んだ。
これを見た君は、この関数の入力は int x
で出力は int
だと考えるんじゃないか。
それが入力と出力の一組目で、言うなれば従来の捉え方だ。では続いて、入力と出力の二組目の例を見てみよう:
public void processNext() { Message message = InboxQueue.popMessage(); if (message != null) { process(message); } }
この関数は、構文を見るかぎりは何も入力を取らず何も出力を返さないように見えるが、何かに対して明らかに依存しているし、明らかに何かをしている。実は、この関数には入力と出力の組が隠れている。その隠れた入力とは popMessage()
を呼び出す前の InboxQueue
の状態だ。そして、隠れた出力とは process
が引き起こしたあらゆる結果と、それに加えて、処理が終わった後の InboxQueue
の状態だ。
間違いなく、InboxQueue
の状態はこの関数の本物の入力だ。その値を知らなければ processNext
の挙動も分からない。そして、出力の方も本物だ。processNext
を呼び出した結果は、InboxQueue
の新たな状態を考慮しないと完全に理解することはできない。
このように、二番目のコード片には入力と出力が隠れている。それは何かを必要として、そして何かを引き起こすが、API を見ただけではそれが何なのかは決して推測できない。
この隠れた入出力にはちゃんとした名前があって、その名を「副作用」という。さまざまな種類の副作用があるけど、それらは全て同じコンセプトの下でまとめられる。「引数リストに含まれないけど、この関数の呼び出しに必要なものは? そして、戻り値に含まれないけど行うことは?」
(僕は実のところ、隠れた出力を表す「副作用 (side-effect)」という語だけでなく、隠れた入力を表す「副原因 (side-cause)」という語も必要だと思う。これ以降の記事では、ほとんどの場所では簡潔に「副作用」とだけ書くが、その場合は間違いなく副原因の話もしている。僕は、あらゆる隠れた入出力についての話をしている。)
副作用は複雑性の氷山だ
関数が副作用(と副原因)を持つとき、こう見立てることができる:
public boolean processMessage(Channel channel) {...}
…で、これを見た君は、これが何をしているのか理解したと思うかもしれないが、それは全くの誤りだ。関数の中身を見なければ、その関数に何が必要なのか、あるいはその関数が何を行うのかを知る方法はない。チャンネルからメッセージを取り出して処理する? たぶん。何かの条件を満たしたらチャンネルを閉じる? おそらく。どこかのデータベースのカウンタを更新するのかな? ひょっとすると。期待したログディレクトリのパスを見つけられなかったら爆発するの? かもしれない。
副作用は複雑性の氷山だ。関数のシグネチャを、そして名前を見たとき、君はそれが何物なのかを何となく分かった気になる。しかし、関数シグネチャの表層の下には、本当にあらゆるものが隠れている可能性がある。あらゆる要件、あらゆる変更、そうしたものが隠れている。実際に何が関わっているかは、関数の実装を見なければ知る由もない。API の表層の下には、さらなる複雑性の膨大な塊があるかもしれない。それを把握する方法は三つしかない: 関数の定義に飛び込むか、複雑性を表層に持ってくるか、無視を決め込んでうまくいくことを祈るか。そして、無視すると、たいてい結局はタイタニック号と同じ過ちを犯すことになる。
これってカプセル化の話じゃないの?
違うよ。
カプセル化とは、実装の詳細を隠蔽することだ。呼び出し元がコードの内部のことを心配しなくても済むように隠そうって話だ。これは変わらず良い方針だけど、この記事で話してることじゃない。
副作用に注目するのは「実装の詳細を隠蔽したい」からではなく、コードとその外側の世界との関係を隠蔽したいからだ。副原因を伴う関数には、その関数が外部のどんな要素に依存しているかについて文書化されていない仮定がある。副作用を伴う関数には、その関数が外部のどんな要素を変化させるかについて文書化されていない仮定がある。
副作用は悪なのか?
いや、それがプログラムの元々の作者が期待した通りに動作するならおそらく大丈夫だ。ただ、副作用の難しいところは、僕らは元のプログラマが暗黙に期待していたことが正しいと、そしていくら時間が経っても変わることなく正しいと信じる必要があるってことだ。
僕らは、この関数を書いた際に期待していた通りに世界の状態を設定しただろうか? さもなくば、世界がどこかで変更された? それはおそらく、一見して繋がりのないコード片が変更されたせいだ。そうでなければ、そのソフトウェアを新しい環境にインストールしたからだ。世界の状態について隠された仮定があるとき、僕らは、世界の状態と、その関数が十分に動作する状態とが似ていると暗に期待していることになる。
このコードはテストできるだろうか? 単独では無理だ。回路基板と違って、僕らは入力にそのままプラグを差し込んだり出力を確認したりできない。僕らはコードをこじ開け、その隠れた原因や作用を把握し、それが存在するはずの世界をシミュレートする必要がある。僕は、テスト駆動開発に取り組んでいる人々が、テストをブラックボックスでやるべきかホワイトボックスでやるべきかについて堂々巡りしているのを見てきた。答えはブラックボックスでやるべきで、実装の詳細を無視できるはずだけど、副作用を許してしまえばそれはできない。副作用はブラックボックステストへの扉を閉ざしてしまう。なぜなら、箱をこじ開けて中身を調べなければ入出力へ到達できなくなるからだ。
これは、デバッグにおいてさらに問題になる。関数が副作用(や副原因)を許さなければ、その関数が正しいかどうか理解するには、単にいくつか入力を与えて出力を確認するだけでいい。だが、副作用を伴う関数だったら? システムの他の部分に対する影響を際限なく考慮しなきゃいけなくなる。関数が何かに対して依存したり影響を引き起こしたりするのを許容すると、あらゆる場所にバグが存在するようになる。
副作用は常に表層に移せる
僕らは、この複雑性に対して何かできるだろうか? うん、始めるのは実のところかなり簡単だ: 関数が何か入力を持つなら、そう言おう。何かを出力として返すなら、そう宣言しよう。それだけだ。
例を試してみよう。この関数には入力が隠れている。素早く見つけられたらボーナスポイントだ:
/** * 訳注: 指定したチャンネルで現在放映しているテレビ番組を返す関数。 */ public Program getCurrentProgram(TVGuide guide, int channel) { Schedule schedule = guide.getSchedule(channel); Program current = schedule.programAt(new Date()); return current; }
この関数には現在時刻 (new Date()
) という入力が隠れている。この複雑性を表層に移すには、こういう追加の入力があるってことをシグネチャの中で正直に表すだけでいい:
/** * 訳注: 第三引数に when を追加して programAt(Date) に与えている。 */ public Program getProgramAt(TVGuide guide, int channel, Date when) { Schedule schedule = guide.getSchedule(channel); Program program = schedule.programAt(when); return program; }
これで、この関数は入力(や出力)を隠し持たなくなった。
この新バージョンの良い点と悪い点を見てみよう:
悪い点
より複雑になったように見える。関数の引数が二つから三つに増えたし。
良い点
複雑にはなっていない。依存関係を隠してもシンプルにはならないし、それを正直に表したらより複雑になるってこともない。
テストははるかに簡単になっている。一日の異なる時刻、時計の変化、うるう年といったすべてのテストがそのまま書ける。なぜなら、好きな時刻を渡せるからだ。僕は、最初のバージョンのような本番コードをテストするために、あらゆる種類の巧妙なトリックで現在のシステムクロックを偽装するのを見てきた。これをパラメータ化するだけで、そんな苦労をしなくて済むんだ!
推論もより簡単になっている。いまや、関数は単に入力と出力の関係を記述しているだけだ。入力が分かれば出力がどうなっているべきか分かるし、そして結果についてあらゆることが分かる。これはすごいことだ。このコードは単独で検証できる。入力と出力の関係さえテストすれば関数全体をテストしたことになる。
(そして余談だけど、便利なのはこれだけじゃない。「一時間後に始まる番組」を返すようなコードがタダで手に入る。)
「純粋関数」って何?
ドラムロールをどうぞ。
これで隠れた入力と出力について把握したので、ついに「職業プログラマ向けの純粋関数の定義」を説明できる:
関数が〈純粋〉であるとは、全ての入力が入力として包み隠さず宣言されていて、同様に出力が出力として宣言されていることだ。
逆に、入力や出力を隠し持っている関数は〈純粋〉ではない。非純粋な関数にとっては、僕らが「関数が提供する契約」だと思っているものは全体のうちの半分に過ぎない。複雑性の氷山が迫っている。純粋でないコードは決して「単独」では使えないし、単独でテストすることもできない。テストやデバッグをしたいときはいつも、そのコードが依存する他のコードを追跡しなければならなくなる。
「関数型プログラミング」って何?
純粋関数と非純粋関数について把握したので、これで「職業プログラマ向けの関数型プログラミングの定義」を説明できる:
関数型プログラミングとは、純粋な関数を書いて隠れた入出力をなるべく取り除き、できるだけ多くのコードを入力と出力の関係だけで記述することだ。
ほとんどのプログラムは何かを返すというより何かを行うために実行されるので、どうしたっていくらかの副作用は避けられないけど、プログラムの中は厳格に制御しよう。副作用(と副原因)を可能な限り排除して、それでも取り除けない場合は厳重に管理するんだ。
別の言い方をするなら、「コード片に必要なものや、コード片が生成する結果を隠蔽するのはやめよう」ってことだ。コード片を正しく実行するのに必要なものがあるなら、そう言おう。コード片が何か有益なことをするなら、それを出力として宣言しよう。そうすれば、僕らのコードはよりクリーンになる。複雑性を表層に移せば、それをかみ砕いて対処することができる。
「関数型プログラミング言語」って何?
あらゆる言語は純粋関数をサポートしている ― 例えば add(x, y)
を非純粋関数にするのは難しい。*1そして多くの場合、非純粋関数を純粋関数に変換するには、関数の入力と出力をすべてシグネチャに持ち上げるだけでいい。そうすれば、シグネチャは関数の挙動を完全に記述するようになる。じゃあ、あらゆるプログラミング言語は「関数型」なのか?
そんなことはない。もしそうなら、「関数型プログラミング言語」なんて言葉は無意味だってことになる。
それじゃあ、「職業プログラマ向けの関数型プログラミング言語の定義」はなんて説明すればいいんだろう?
関数型プログラミング言語とは、副作用なしでプログラミングすることをサポートしたり奨励したりするような言語だ。
より具体的には、関数型言語は副作用の積極的な排除を可能な限り助け、それができない場合は厳重に制御するのに役立つ。
より過激な言い方をするなら、関数型言語は副作用に対して積極的に敵対する。副作用は複雑で、複雑さはバグで、バグは悪魔だ。関数型言語は君が副作用に敵対することも助け、君と共に副作用を力で屈服させるだろう。
それで全部?
そうだ。きっとこれまで、君はそれが隠れた入力であると考えたことがないような微妙なものもいくつかあるだろうけど、それが本質だ。「副作用が第一の敵である」という観点でソフトウェアを構築し始めると、君がプログラミングについて知っているあらゆることが変化するだろう。この記事のパート 2 では、副作用と関数型プログラミングについて把握した上で、プログラミングの現状に散弾銃をブッ放すことにしたい。
謝辞
この記事は、関数型プログラミングの性質について何回か議論したことが元になっている。特に Sleepyfox との「適切なライブラリを組み合わせれば JavaScript は関数型プログラミング言語とみなせるか」を巡る議論からは大いに刺激を受けた。僕の答えは直感的にはノーだけど、それがなぜかを考えることを通じて、非常に実りの多い思索に誘われるきっかけになった。
James Henderson に敬意を。今年は、彼のおかげで関数型について多くの実りあるアイデアに触れることができた。
そして、Malcolm Sparks, Ivan Uemlianin、Joel Clermont、Katy Moe、そして僕のドッペルゲンガー Chris Jenkins。皆の校正と提言に感謝する。
おまけ: Part 2 の概要
パート 2 を翻訳する元気が残ってないので概要だけ紹介しておきます。
関数型プログラミングは何ではないか
関数型言語は副作用(副原因)と戦うための道具であって、つまり:
関数型言語はどれ?
設計の臭い
- 引数なしは副原因のシグナル
public Int foo() {}
- 戻り値なしは副作用のシグナル
public void foo(...) {...}