Rubyのハテナってbool返すんじゃないの?

rubyのNumeric#nonzero?ってself | nilを返すんだ。ハテナってbool返すんじゃないの?
って聞かれた。
自分もこの前までそう思ってたんだけど、たしかそうじゃない便利ケースがAPIデザインケーススタディに出てきた、
ってうろ覚え知識を披露した。なにの時便利だったかは覚えてなかったので、ふわふわ。
なので調べた。

instance method Numeric#nonzero? (Ruby 2.3.0) http://docs.ruby-lang.org/ja/2.3.0/method/Numeric/i/nonzero=3f.html

Rubyではnilとfalseが偽、それ以外の値は全て真とみなされるので、このInteger#nonzero?の振る舞いは、0に対して偽、
それ以外に対して真を返すものと言えます。つまり名前に反する動作というわけではありません。
(snip)
意外な動作は学習コストを上げるので、理由がなければ避けるべき
(snip)
Enumerable#sort メソッドに与えるブロックの中の記述を簡単にするため。
APIデザインケーススタディ 田中哲

enum.sort {|a, b| c = a.x <=> b.x; c != 0 ? c : a.y <=> b.y }
が
enum.sort {|a, b| (a.x <=> b.x).nonzero? || a.y <=> b.y }

と記述できる。

具体的には自分でハテナつきメソッドを書くとき、気を使うときは、
わざわざtrue/false を返すように、最後絶対bool返すぞ!って foo ? true : falseって書くことはある。
どこかで何かを読んで、しかも最近、必ずしもそうしなくて良くて、
truthy/falsy 返すだけで名前に反するわけではない、と何かで読んだ。
そのなにかがAPIデザインケーススタディだった。

別のものを返すことで使いやすいケースだったりそういう使い方しかないケースでは、bool以外が返ることがある。
だったはずだから、ドキュメントにあるはず。

documentみていく。
ObjectやEnumerableにはbool返すのしか生えてなかった。

Numeric#nonzero? -> self | nil
Encoding.compatible?(obj1, obj2) -> Encoding | nil
Kernel.#autoload?(const_name) -> String | nil

だんだん見ていくとだいたいboolなんだけど、いくつかboolじゃないものもあった。
上記は全部ではなく、ぱっと見て出てきたもの。

ほぼだいたいboolだがそうでもないのもいるから、truthy/falsyで判別すればびっくりしなそう。

bitcoin readonly wallet

bitcoinでreadonlyなwalletを使いたい。
リードオンリーじゃなくてもいいけど、レジ端末的なところには秘密鍵なし。
可能なら、取引ごとに異なるビットコインアドレスを生成して表示。
まあ無理でも、ウォレット単位の残高を見たい。見せたい。

結論として、公開鍵あれば読めることはわかった。ただその公開鍵公開していいかはまだよくわかってない。

規格

mastering bitcoinのHDウォレット周り読んだり、ググったりしたがいまいちピンとこない。
また、readonly address というのが、規格もあり実装しているクライアントもある。
しかし、addressをreadonlyにできても、アドレスは使い捨てるほうが良いわけで、だいぶナンダカナー感がある。

xpubで始まる master public key を持ち運べば良さそうに見える。
ただ、copay2.6.0でmaster public keyをimportする口がなさそう?。
なお、electrum 2.6.4にcopay2.6.0からwalletのmaster public keyをimportすることができた。よっしゃよっしゃ。

copayの実装

パスワード制限

いまいちなほうから。

copayは送金時にパスワードを必須にすることができる。
なので、レジ端末側に秘密鍵を入れ、送金するときにパスワードを要求することで、一応守れる。
あとMnemonic code吐き出しも設定から潰せるので、何かの時にだいぶ危ない以外は、目的が多少達成できる。
walletのexportも潰さないとダメな気がするけど、潰せるのかな。

export wallet, Do not include private key (独自実装?)

export wallet時にadvanced optionが設定できる。
秘密鍵含むことなしにexportできて、それにパスフレーズをつける。独自実装かな?

このファイルを別のcopayでimportできる(試したのはdesktop -> android)。
送金しようとすると、readonly側のウォレット的には送信のproposalを出し、秘密鍵持ってる側のウォレットに、approveの画面が出てくるところ。
このproposal機能はじめ独自実装かなと思ってたけど、独自実装じゃないっぽい。
master public key でimportしたreadonly walletのelectrumから送ってみたら、unsignedのtransactionが飛ぶ。
copay側でそれを拾って自分がsign出来そうだったらなんか出すんだ。かしこい。
そしてrejectしたらなかったことになる。かしこい。

master public key

ElectrumはWallet -> Master Public Keysから。
copayは歯車 -> Advanced -> Wallet Information -> Extended Public Keysから。
xpubではじまるやつ。

前述だけど、copayで出したpublic keyをelectrumでimportできた。ほかは試してない。

このmaster public keyがどの強度のやつなのかはよくわからない。

どの強度is何

まんまmastering bitcoinからの抜粋

強化子公開鍵導出(hardened child key derivation)
もし拡張公開鍵の利便性を使い、しかもchain codeの漏洩リスクを回避したいのであれば、
通常の親(親公開鍵)ではなく強化された親(親秘密鍵)からから拡張公開鍵を導出すべきです。
ベストプラクティスとしては、マスターキーの1階層目の子供を常にhardened derivationを通して
導出されるようにしておくことが良いでしょう。

unsigned

unsignedで送れてしまうから、うっかりするとうっかりしそう。

web api

web apiで取れるのかな。少なくともココにはなかった。
https://blockchain.info/api/blockchain_api

やりたかった定点観測

なんか作ったら or 既存のものでreadonlyのwallet定点観測できないかなーと思ってた。
親公開鍵を預ける/預かることがどのくらいリスクなのかまだよく理解してないから、まだあれ。

公開鍵を使って、ビットコインアドレスが生成できる。
また、トランザクションから自分のウォレットに属するかがわかってしまう。
秘密鍵/公開鍵という響きだけから感じる公開鍵は公開していいもの、という印象よりだいぶうかつに公開するとまずそうな気がする。

APIデザインケーススタディ読んだ

ようやく積んでた本を読んだ。読んだというか、途中まで読んでてきつくなったのでパラパラ眺めてどうにか一周終わらせた、ってかんじ。話の内容は多分面白くて書いてある中身もきっと面白いんだけど、対象に今の自分があまり興味がなかったから仕方ない。

APIデザインケーススタディ ――Rubyの実例から学ぶ。問題に即したデザインと普遍の考え方 | Gihyo Digital Publishing … 技術評論社の電子書籍

第1章─I/O, 第2章─ソケット, 第3章─プロセス, 第4章─時刻, 第5章─数,文字列 とあって、要は自分が一番好きなプレゼンの使いやすいライブラリ API デザイン. 日本Rubyカンファレンス2006 コレと近い内容なんだけど、I/O, ソケット、プロセス、時刻まであんまり興味がないので、その、あれ。

URI.encode_www_form出てきてやっと興味あるとこキタ! と思ったらそれが最後でしょんぼり。

なので、あとは思い出したことを並べる。

使いやすいライブラリAPIデザインから、自分は強烈な印象を受けていて、過去の自分の名作 https://github.com/sanemat/slip/blob/b49f8a609741c29054cacf0fe84a2a6d377bba53/slip.rb#L14 に色濃く出ている。

脱線すると、httpライブラリの好みの変遷としては、何使ってたか覚えていない -> 感銘を受けて open-uriに -> httparty で楽して楽しく -> REST厨なのでrest-client -> faraday でインターフェースを統一するんだ -> net-http やっぱり標準ライブラリだね、あとeasy, simpleだとsimpleよりのがいい イマココ

コレも好き。matz を説得する方法. RubyKaigi2008

さがしてまわっちゃったけどここにあった。Publications of Tanaka Akira

MASTERING BITCOIN二周目と商店

mastering bitcoin一周目が途中でさっぱりわからなくなったのでMastering Bitcoin一周目とbitcoin買うまで | 實松アウトプット、社内商店のとなりにbitcoinでしか買えない商店を開いて、実験してみた。

50-100円ぐらい単位で消費したい社内商店だとtransaction feesにまけちゃうなーとか、なかなかたのしい。一般的なモバイルクライアント?だとそこまでtransaction feesけちれない。

二周目はコレがこうなって、とblockchain.info みながら、なるほど、なるほどと読めた。秘密鍵なしにビットコインアドレスの残高は取れるけど、秘密鍵なしにウォレットの残高取れないと、決済とか資産管理とかつらいんじゃないかなーと思うけどどうなんだろう。

bitcoinで少額を送る

From electrum 2.6.4 (desktop)
8000bits送ろうとしたら、fee 40bitsでは送れなくて、50bitsかかった。

From Mycelium (android)
2000bits送ろうとしたら、41.46bitsかかった。

From Copay (android)
2000bits送ろうとしたら36bitsかかった。

一度8000bits受け取って、それを原資に2000bitsおくると、お釣りの計算できるまで5964bitsあるわけではなく、
0bitsになるんだ。なるほど…

Copay androidはよくあることだけどnexus 5xでカメラが逆になる。
phonegap のplugin?のバージョン上げる必要がありそうだ。

bitcoinとmoneyforward

moneyforwardでbitcoinはアグリゲーションできる。できるのだけど、1ビットコインアドレスあたり1金融機関扱いになってしまうので、実用性があんまりない。せめて1walletが1金融機関扱いじゃないとなあ。もっというと、1walletはビットコインという金融機関下の、普通預金とか定期預金とかそのカテゴリーでほしい。

現状こんなかんじになってしまう。

Screenshot from 2016-08-14 16-48-46

bitflyerだと1金融機関にまとめられる気はするが、取引所においておくってのナンセンスなのでなし。

Mastering Bitcoin一周目とbitcoin買うまで

Mastering Bitcoinの日本語版がCC by SAで読めるTranslations of Mastering Bitcoin | Mastering Bitcoinので、読んだ。

一周目、途中でさっぱりわからなくなったが最後までたどり着いた。

翻訳にむむむってところがあれば、ここから直しに行くと良さそう。多分typo直せた気がする。
Mastering Bitcoin | Overview

あとは自分でいじってみたり、alt coinやalt chain作ってみたりしないとわからんな、ということでbitcoinを買った。

1JvMhFUq7BDF1RFxXednUHSVbdvQ4j3RW7 Screenshot from 2016-08-14 00-17-37 送ってみたい人受け取ってみたい人は連絡ください。

ビットコインの保管(ウォレット比較) | Bitcoin日本語情報サイト こういうところ読んだりしつつ、まあたいていこういうのの日本語情報って周回遅れになってること多いので、コレも話半分に見ていく。

ubuntu desktop環境なので、いろいろ困るかと思いきや、Electrum (Pythonベース、GUIも)とCopay(Javascriptベース、nwjs)とで、Electrumはaptで、Copayはファイル伸長するだけで動いた。先にElectrumで環境整えたので、Electrumでやってるが、制限などなければChrome extensionなどあるCopayもよさそう。

スマホ側はandroidなのでMyceliumいれた。iosにはbreadwallet入れたが、breadwalletはまだ試してない。

クライアント側の準備ができたので、早速ビットコインを買う。ビットコインは購入所と交換所がある、などの基礎的なところからふむふむ読んでいく。bitflyer.jp にアカウント作って、銀行口座登録して承認され、住信SBIネット銀行から7000円入金。ビットコインが0.01BTC単位で買えるので、1BTC 61000円ぐらいだったので 0.11BTC購入。取引所に滞空させておく意味はないので、bitflyerの自分のアドレスから、デスクトップの自分のアドレスに送金してbitflyerの出番は終わり。transaction feeはbitflyerが今のところ負担してくれる。日本円端数がbitflyerに残り続けてしまうけど、まあしゃーない。

最小単位は現在のところ1 satoshi。100 satoshis = 1 bits (あるいは1 μBTC)。1000 μBTC = 1 mBTC、1000 mBTC = 1 BTC。
546 satoshis 以下はdustとして送金できない。
1BTC 60000円ぐらいなので、1 mBTC 60円、 1μBTC 0.06円 ぐらい。

よく、手数料安いよ、最高!の文脈でbitcoin出てくることある。ただ、それは相場として情報転送量あたりに値段をつけて、それを処理してもらうので、supereconomyモードでもコレぐらいだよ、ってcopayは表示してる。 165bits/kiB。なので、安い安いとはいっても、少ない額を送金するほど手数料の割合は増す。実際Electrumでは、少なすぎるfeeは弾かれてしまった。800bitsにfee8bitsとかそのくらい。Electrumは圧縮転送サポートしてないからデータでかくなりがち、っての数年前のフォーラムで出てきたけどいまどうかはよくわからない。8000bitsにfee40bitsは送れた。ずっと承認されなかったらどうなるんだろ?とおもうが承認されたので良かった。少額決済はやっぱりまとめないとダメなのかなあ。むー。

ECMAScript 2016 I18n API

ECMAScript® 2016 Internationalization API Specification がECMAScript 2016と同時にリリースされた。
I18n APIってなんだよってことで、MDN読んでた。Intl – JavaScript | MDN
specは読んでもわからんので…

I18n系のライブラリはいくつもあるし、なんでそんなのあるのって言うの読んでた。
The ECMAScript Internationalization API

ES5にもES2015あたりにも、ちょっとだけ仕組みが入ってるのをおしすすめた。
各ライブラリが個別に再実装するはめになってる。でかい変換テーブルがいる。インターフェースを決める。

そのへんか。なるほど。
まあ例によってユーザーがそのままこのAPI使うわけではなく、ライブラリ作者が楽に高速になるよね、系のアレ。fetchとかみたいな。

ブラウザ実装状況見ると、
chrome 24, firefox 29, ie 11, opera 15, safari 未実装。
chrome for android 26。モバイルはあと未実装。
なので、あーというかんじ。
ただ、safari 10に実装されることが発表されているので、mac os x sierra, ios 10で入る。
将来的にはいい感じになりそう。

ここから下は、仕様の話じゃなくて、もうあるchromeとfirefoxの実装の話。注意。

あとはだいたいMDNからのコピペ。コードを動かしてみるのは主にchrome 51。

Intl

Intlという名前空間があって、その下にオブジェクトがあるのと、あとString, Number, Dateにメソッドが生えてる。

コンストラクタ
Intl.Collator
Intl.DateTimeFormat
Intl.NumberFormat
メソッド
String.prototype.localeCompare()
Number.prototype.toLocaleString()
Date.prototype.toLocaleString()
Date.prototype.toLocaleDateString()
Date.prototype.toLocaleTimeString()

String.prototype.localeCompare()

ウムラウト区別できても関係ないよなーと思ってた。
けど、ふとひらがなカタカナ半角カナで試してみたら、なるほどーとなった。
まあブラウザ実装依存なんだろうけど、おおーってならない? そうでもないか。

'a'.localeCompare('c');
-1
'check'.localeCompare('against');
1
'a'.localeCompare('a');
0
'ä'.localeCompare('z', 'de')
-1
'ä'.localeCompare('z', 'sv')
1

# ドイツとスウェーデンでソート順が違う。ここまでMDNコピペ

'あ'.localeCompare('ア')
-1
'あ'.localeCompare('ア', 'ja')
0
# !?
'あらすか'.localeCompare('アラスカ', 'ja')
0
'あらすか'.localeCompare('アらスカ', 'ja')
0
'あらすか'.localeCompare('アラスカ', 'ja')
0

Number.prototype.toLocaleString()

プリセットでいろいろある。通貨は結構うれしい。デフォルトプリセット気に入らなかったら、設定上書きできる。
数字部分だけ色変えたいとかあるのはまあ自分で文字列切り刻んだり文字列追加したりでやれってことかな。

var number = 123456.789;
undefined
number.toLocaleString()
"123,456.789"
number.toLocaleString('de-DE')
"123.456,789"
number.toLocaleString('ar-EG')
"١٢٣٬٤٥٦٫٧٨٩"
number.toLocaleString('en-IN')
"1,23,456.789"
number.toLocaleString('zh-Hans-CN-u-nu-hanidec')
"一二三,四五六.七八九"
number.toLocaleString('de-DE', { style: 'currency', currency: 'EUR' })
"123.456,79 €"
number.toLocaleString('ja-JP', { style: 'currency', currency: 'JPY' })
"¥123,457"
number.toLocaleString('ja-JP', { style: 'currency', currency: 'JPY', minimumFractionDigits: 2 })
"¥123,456.79"

Date.prototype.toLocaleString()

chromeやるな。 平成って文字列出てきた。でもMDNと違うぞ。でfirefoxで動かしてみたらMDN通りになった。
やっぱりブラウザ間実装差が。

var date = new Date(Date.UTC(2012, 11, 20, 3, 0, 0));
undefined
date.toLocaleString('en-US')
"12/20/2012, 12:00:00 PM"
date.toLocaleString('en-GB')
"20/12/2012, 12:00:00"
date.toLocaleString('ja')
"2012/12/20 12:00:00"
date.toLocaleString('ar-EG')
"٢٠‏/١٢‏/٢٠١٢ ١٢:٠٠:٠٠ م"
date.toLocaleString('ko-KR')
"2012. 12. 20. 오후 12:00:00"
date.toLocaleString('ja-JP-u-ca-japanese')
"平成24/12/20 12:00:00"

firefox 47

var date = new Date(Date.UTC(2012, 11, 20, 3, 0, 0));
undefined
date.toLocaleString('en-US')
"12/20/2012, 12:00:00 PM"
date.toLocaleString('ja-JP-u-ca-japanese')
"24/12/20 12:00:00"

エレクトロンならワンちゃんあるかな。

rubykaigiのトークに何応募するか考え中

話したいこと

rubyのコマンドラインツールとプラグインシステムと設定の読み込みを作ってみて、設計に失敗したはなしとどうすればよかったのかについて

題材

tachikoma

tachikoma.io

saddler

項目

  • 言語選択
  • 大きな方針
  • アーキテクチャ選択
  • 設定の読み込み
  • shell or script language
  • エラー設計
  • リリースと依存、またその確認
  • テスト容易性
  • 本体の配布、プラグインの配布
  • 実行ファイルを単一
  • アプリケーションと同じGemfileに入れるか
  • 他のツールとの親和性

話した結果自分は何を得たいか

  • 自分の考えたことをダンプして、次作るならもうちょっとマシにしたい
  • 誰か詳しい人の知見を吸いたい
  • 似たようなこと考えてる人の設計の参考になればいい

聴衆に何をしてほしいか 明日から何を始めればいいか

  • ruby, node, golangでツールを作りだそう
    • 言語、ツールの特性、エコシステム的に最適なところを選べる
  • gem, npmなどのエコシステムを活用する
  • 柔軟なやつも作りはじめられるぞ たぶん

rubyでの成功例

  • fluentd
  • omniauth
  • fog
  • rails(?)
  • rubygems(?)

先行資料

1個のライブラリにまとめたくなる呪縛

rubyのgemは1個のgemがやろうとすることが多すぎる。npm moduleは1メソッドが1packageぐらいの粒度。だから自分はnpmが好き。

って普段から言ってるのに、似たようなことやるからこのgemにメソッド生えてたほうがいいかな、とメソッド増やそうとしてしまった。気づいたから良かった。packageわけよう。rubyだから、nodejsだから、というわけでもないと思うんだが何なんだこの呪縛は。