XAMLに思いを馳せすぎてReactにDataTemplateを輸入した
WPF、もとい MVVM 信者としては、どうしても pure な Class で ViewModel を作りたいというのがあって*1、React にその思想を持ち込んでみた。
React では往々にして Container Component といわれる MVC の Controller みたいなものと Presentation Component と言われる View みたいなものを多層に重ねて UI を作る。V と C が交互に折り重なるように見えるので、ミルフィーユ方式と呼びたい。
それに対して、MVVM(って言っていいのかな)では、ViewModel という名のただのインスタンスのオブジェクトグラフが1本あって、それとは別に View がある。で、この View は ViewModel のオブジェクトグラフとトラバーサルして変換するような形で作られる。XAML がわからない人は XSLT を想像してください。ああいう感じです(ちょっと違うけど)。
ミルフィーユ方式ではどうしても状態管理と VDOM 生成の責務がべったりしがち、ということがあってあまり好きではないんです。Controller が View を知ってる、みたいになってしまって気持ちよくない。それに対して MVVM の View はロジック(ViewModel)に対してとことん非破壊的なんですね。これがよい。ViewModel は好きなように書いて、View がそれに合わせる。理想じゃないですか。
で、VDOM のポテンシャルを活かせばそれくらいできるでしょう、と午前2時くらいの脳がひらめいたのでちょろっと書いてみました。
まず、なんの変哲もない木構造のクラスを定義します。
export abstract class Node { constructor(public value: string) {} } export class Tree extends Node { constructor(value: string, public children: Node[]) { super(value); } } export class Leaf extends Node { }
こう、pure な感じで普通に書くわけですね。
で、それをレンダリングする View を書きます。
class TreeView extends ScopedComponent<{ root: Node }, {}> { render() { const {root} = this.props; return ( <ul> <DataTemplate type={Tree}> { ({content}: { content: Tree }) => <li> {content.value} <ul> { content.children.map((node, i) => { return <ContentControl key={i} content={node} />; }) } </ul> </li> } </DataTemplate> <DataTemplate type={Leaf}> { ({content}: { content: Leaf }) => <li> {content.value} </li> } </DataTemplate> <ContentControl content={root} /> </ul> ); } }
実装はこちらにおいてあります。XAML に恋い焦がれている方はどうぞ。PoC なので、スコープが hierarchical cascade じゃないとかで全然実用的ではないですが。
GraphQLのはじめかた
トレンドに乗るためにはトレンドを自分の方に捻じ曲げるのが一番いい、ということで、Twitter で日夜 GraphQL, GraphQL と騒いでいる日々であります。
GraphQL の話、スライド上げました https://t.co/hTUvA9Fajt ハンズオンに良さそうなコードや解説記事などもそのうち公開します #tng23
— KOBA789 (@KOBA789) 2016年10月22日
先日、tng23 で「GraphQLの話」をしてきました。解説記事とか書くみたいなことをノリで口走ったので、これは伏線回収です。
GraphQL は公式のドキュメントが充実しています。とはいえ、全部英語なので日本にはあまりリーチしてないですね。みなさん英語読んで……。
母語でない言語で書かれた文章を自分のペースで読みながら、そこに書かれている新しい概念を獲得するってのは結構な重労働です。そこで、おすすめの学び方はカンファレンスでの GraphQL に関する発表の映像を視聴することです。YouTube の自動字幕はすごくて、 "GraphQL" が "graphical" になったり "graph kill" になったりするくらいで他はめちゃくちゃ精度よく文字起こしされます。スライドもあるので言葉だけのドキュメントよりも概念の理解が楽だと思います。以下のページにたくさん動画へのリンクがあります。
この動画なんかは導入としてとてもいいです(作者が喋ってるので当たり前ですね)。
動画は脳にいいんですよ。
GraphQL でリアルタイムなフィードとか扱いたいです、みたいな一歩進んだ人はこれも見ましょう。
動画を見て興味が出てきたら手を動かしましょう。
express-graphql とかを使うと GraphiQL (API コンソール)付きのサーバーがサクッとできるので便利です。
Node.js で GraphQL するなら使うことになるであろう実装が graphql-js です。作者が作ってるリファレンス実装です。
半年くらい前まで結構実装に粗が目立ってたんですが、最近はコミュニティも活発でこなれてます。低レベルな API と高レベルな API がわかれてて、どちらもちゃんと export されててえらいです。えらい。
あと、flow で書かれてるので type annotation があって読みやすいですね。自分は TypeScript 派ですが。
はじめかたはこんな感じです。とりあえずはじめましょう。
LINEインターンに参加した
40万円
LINE Payのチームでなんかの実験環境を作ったりしました。
例えば、これは最終日の昼に食った肉です。
たまたま倒壊していなかったときの建物です。
ほかにもなにかを作ったりしました。はやくリリースされるといいですね。
つくばから東京までは自転車で行って、五反田のベッドで寝てました。
これは見えるやつです。
夜になるとよりよい。
LINE Pay は LINE ID: koba789 にお金を送ることができる良いサービスです。
はい
調子が悪い
1年ぶりくらいに調子が悪い
Rustのstd::io::copyとEchoサーバー
気が向いたので Rust でも書いてみるかという感じになって書いてるんですが、TCP Echo サーバーを書くだけで躓いたのでメモ。
fn main() { use std::io::prelude::*; use std::net::{TcpListener, TcpStream}; use std::thread; let listener = TcpListener::bind("127.0.0.1:8124").unwrap(); fn handle_client(mut stream: TcpStream) { std::io::copy(&mut stream.try_clone().unwrap(), &mut stream); } // accept connections and process them, spawning a new thread for each one for stream in listener.incoming() { match stream { Ok(stream) => { thread::spawn(move|| { // connection succeeded handle_client(stream); }); } Err(e) => { /* connection failed */ } } } // close the socket server drop(listener); }
handle_client
内、std::io::copy
の引数に std::io::copy(&mut stream, &mut stream)
とやりたくなるが、ownership が第1引数に渡ってしまうので第2引数が不正とみなされコンパイルエラーになる。それを避けるために try_clone()
しているが、内部的にはファイルディスクリプタの複製をやっているようで、ちょっと無駄っぽい気がする。
std::io::copy
を使わずにこうすれば平気。
fn handle_client(mut stream: TcpStream) { let mut buf = [0; 128]; let mut written = 0; loop { let len = match stream.read(&mut buf) { Ok(0) => break, Ok(len) => len, Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => continue, Err(e) => break, }; stream.write_all(&buf[..len]); written += len as u64; } }
とはいえ、せっかくのユーティリティ関数使いたいよなぁ。
Rust に詳しい人、ベストプラクティスを教えてください。
Raspberry Pi 2 Model Bが届いたのでB+と比較したりベンチマークしたりしてみた
来月の生活費がありません。KOBA789 です。 来月の生活費がないのに Raspberry Pi 2 が出たと聞いて速攻でポチりました。10人位でまとめて購入したので一気に口座から5万くらい飛んでいきました。未払い各位は僕に生活費を払いに来てください。よろしくお願いします。
さて、その Raspberry Pi 2 Model B が早速届いたのでベンチとかしてみよう、というのが今回の主題です。では張り切っていきましょう。
スペックで見る Raspberry Pi 2 Model B
公式サイトの解説ページ曰く、
A 900MHz quad-core ARM Cortex-A7 CPU (~6x performance) 1GB LPDDR2 SDRAM (2x memory) Complete compatibility with Raspberry Pi 1
とのこと。CPU が速くなってたり、RAM が倍増してたりします。RAM が 1GB あると VRAM を増やせるので嬉しいですね。
ちなみに Model B+ と比較するとこんな感じ。
Raspberry Pi Model B+ | Raspberry Pi 2 Model B | |
---|---|---|
SoC | BCM2835 | BCM2836 |
CPU | ARM1176JZ-F | ARM Cortex-A7 |
GPU | Dual Core VideoCore IV | Dual Core VideoCore IV |
RAM | 512MB | 1GB |
引用元: High Definition 1080p Embedded Multimedia Applications Processor - BCM2835 | Broadcom, Raspberry Pi 2 on sale now at $35 | Raspberry Pi
写真で見る Raspberry Pi 2 Model B
左が B+ 右が 2 B。ロゴがちょっと小さくなってます。また、B+ の SoC には SUMSUNG のロゴが印字されていますが、2 B は Broadcom のロゴですね。
向きを変えてもう1枚。左が B+ 右が 2 B。
特徴的な裏側。左が B+ 右が 2 B。2 B は裏に ELPIDA のメモリセルがあります。B+ のときは SoC 内蔵だったから容量が小さかったのでしょうか。
追記: こういうことっぽい。賢くなった。
@KOBA789 Model B+で真ん中にSamsungの刻印がついてるのは、PoP実装といってRAMがCPUのパッケージの上に重ねてくっつけてあるからです。Pi 2では裏面に付いてるので露出していて刻印が読めるということのはずです
— 鈴谷 (@numpad0) February 5, 2015
起動
とりあえず手元の microSD に Raspbian を焼いて起動してみました。クアッドコアの証として、2 B はコンソールの左上にロゴが4つ表示されます。
起動速度
参考までに dmesg
のログを貼っておくとこんな感じです。
B+
[ 32.236583] Adding 102396k swap on /var/swap. Priority:-1 extents:2 across:2162644k SSFS
2 B
[ 15.395821] Adding 102396k swap on /var/swap. Priority:-1 extents:2 across:2162644k SSFS
速いっぽいです。
/proc/cpuinfo
クアッドコアと聞いて、まずやってみたくなるのはこれですよね?
pi@raspberrypi ~ $ cat /proc/cpuinfo processor : 0 model name : ARMv7 Processor rev 5 (v7l) BogoMIPS : 38.40 Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x0 CPU part : 0xc07 CPU revision : 5 processor : 1 model name : ARMv7 Processor rev 5 (v7l) BogoMIPS : 38.40 Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x0 CPU part : 0xc07 CPU revision : 5 processor : 2 model name : ARMv7 Processor rev 5 (v7l) BogoMIPS : 38.40 Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x0 CPU part : 0xc07 CPU revision : 5 processor : 3 model name : ARMv7 Processor rev 5 (v7l) BogoMIPS : 38.40 Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x0 CPU part : 0xc07 CPU revision : 5 Hardware : BCM2709 Revision : a01041
うひょー! マジで4コアある!!!! しかし、Hardware: BCM2709
というのが気になりますね……。
/opt/vc/src/hello_pi/hello_encode
CPU はたぶん速くなってるだろうという予想がつくので、どちらかというと気になるのはOpenMAX のほうではないかと思います。というわけで動画のエンコードの実験をしてみます。
まずは B+ から。
pi@raspberrypi /opt/vc/src/hello_pi/hello_encode $ time ./hello_encode.bin /dev/null > /dev/null real 0m4.781s user 0m3.600s sys 0m0.450s
次に 2 B。
pi@raspberrypi /opt/vc/src/hello_pi/hello_encode $ time ./hello_encode.bin /dev/null > /dev/null real 0m2.595s user 0m1.870s sys 0m0.130s
2倍とまでは行きませんが有意な差が出ています。この速度差が CPU の高速化によるものなのか、あるいは CPU 同様に GPU もクロックアップしているのかという点については今後更に詳しく調べる必要がありそうです。
まとめ
2 B 速いです。まぁこの小さいボードがそんなに速くなってなにが嬉しいんだという気もしますが、$35 でこの性能ですから非常に遊びやすくなったと言えると思います。なにより RAM 1GB が本当に嬉しいですね。
さてなんで私がこれほどまでに(今更) Raspberry Pi で興奮しているのかというと、Raspberry Pi 向けの HDMI キャプチャユニットを開発中だからです。Raspberry Pi で HDMI がキャプチャできれば LT のスライドにオーバーレイでコメント流すデバイスを作ったり、LiveShell のような使い方をしたりということができるようになるんではないかと考えています。
それではまた。