- 日帰りできないレース(トライアスロン中島大会は例外)
- 時間のかかる栄養補給
- 長時間のネットサーフィン
長時間のネットサーフィンはやらなくなった。SNS で時間を潰すのは、死語たるネットサーフィンと同じく「費用対効果の悪い閲覧行為」だと考えている。もちろんウェブで情報を集めたり、SNS で交流/情報交換したりすることの中には費用対効果が高いこともある。ネットサーフィン的な活動を避けた、ということだ。Twitter アプリをPCからアンインストールし、通知もすべて切った。
pyfes 2013.07 に行ってきました。最近、ぜんぜんコードを書いていないので、この機会にエディタを開いてコードを書いたのは楽しかったです。数行のサンプルだけですけどね。
bpython ちょっと使ってみたら面白そうでした。あと suddendeath, xaxtsuxo, aodag.scaffold も便利だよという意見もあったので、気が向いたらカバーします(しねぇよ)。
自習できる人をうらやましがっている増田がいました。
会社を定時上がりしてもダラダラパソコンやったり携帯見てしまう
無駄な時間だと思っててもあとちょっとだけを繰り返して23時
文章どおり受け取り、かつ、勝手に妄想で補完すると、自習自体ができないんじゃなくて、取りかかるのが億劫なんだと思います。それにはとても共感します。自分もずーっとそんな感じだから。想像するだけだでしんどさ、面倒くささに圧倒されて、結局何もやらずに済ませていまいます。
そんな自分もとりあえず10分だけやるというのを実践しはじめて、1年くらいたちました。10分たったたらどんなに進展がなくてもやめてもいい、というルールもつけてます。
よいニュースと悪いニュースがあります。ほんとに何もできずに終わる日もありますが(ほとんどがこのパターン)、気分が乗ってきて数時間続けている日もあります。Better than nothing と言い聞かせて、あんまりしんどい思いをせずに、少しずつだけど何らかの意味ある活動に時間を費やせるようになりました。悪いニュースは、この活動が直接的に昇給など、目に見える結果には反映されていないことです。闇雲に仕事をしたからって昇給しないのと同じですね。
さてさて。こういうプラクティスを、TODO管理ツールなりカレンダーなり、しくみやツールに自然に組み込めるといいんだろうな、と思っています。
先日、Go の型は First-class ではないことを、ぐずぐず書いていたら、こんなコメントがありました。
reflect.ValueOf(x).Type().Name() で型取れますよね?そういう話ではなく?&Foo{} とか? / “Go の型は First-class ではない: Addicted To Indentation” htn.to/L2rfDQ
— mattnさん (@mattn_jp) 2013年5月8日
もともと困っていたのは、型を引数にできないことでした。そして、見たところ Go は型(int とか、type Foo struct{...} の Foo とか)を引数にできません。できないのですが、やりたいことは「型をわたすこと」ではありません。
やりたいことは、「クエリ対象の指定をもうちょい安全にしたい」です。NewQuery(c, "Foo") だと "Eoo" と書いて渡してもコンパイルを通ってしまい実行時にエラーになるけれど、すでに定義してある Foo 型を使うのだ、と記述することができれば少しは安全側に倒れるのではないか、と考えたわけです。その仮定で、型を知らせるために、使いもしない変数を定義することに居心地の悪さを感じていました。
そこで @mattn さんの &Foo{} という書き方ですよ。f(&Foo{}) や f(Foo{}) と書けば型を知らせているのだ、と分かりやすいし、余計な変数宣言もないしで、なかなかいい。たぶん Foo 型の値が生成されそうで、要らないメモリだろうと思ったりもしましたが、自分が書くコードではもっと別なボトルネックがありそうです。そんなわけで、この書き方いいなぁと思っています。
あとですね。そもそも型を渡して〜というアプローチが、 Go の考え方に合っていない気がしています。先日のブログにも書いたのですが、ここではクエリを発行して、そのあとデータストアから Foo の配列に値を取ってくるわけです。非同期に実行するとしても chan を使うでしょう。なので Foo の型情報を持った変数が、文脈上あとで必ず出てきます。であれば、ここからここまでで Foo 配列に対する操作をしまっせー、という中にクエリ発行が出現する、という書き方もできて、それが合っている気もしてきました。
Go の型は First-class ではない、ということにゴールデンウィーク最終日に気づき、悶々としています。(何も Go が悪いわけではない)
ことの発端は、以下の様な関数を定義したところから始まります。
func getName(x interface{}) string { return reflect.TypeOf(x).Elem().Name() }
この関数に、任意の型のポインタをわたすと、型の名前を取得できます。けど、ポインタを渡さなければならないのですね。
var foo *Foo name := getName(foo)
foo は使わないのに! 使わないというのはウソですね。けど、ちょっと違うんですよ。まあこれは私がPython 脳だからであって、別にGoが悪いわけじゃない。
何をしたいかと言うとですね、Google App Engine datastore のクエリの生成をラップしたいのです。標準ライブラリを使うと、以下のように書きます。
c := appengine.NewContext(r) q := datastore.NewQuery("Foo") // ☜(◉ɷ◉ ) q.Filter("Y =", "xaxtsuxo") foos := make([]Foo, 0, 10) keys, err := q.GetAll(c, &foos)
Foo が型が定義されているのに、文字列で "Foo" を渡すのが悔しいわけです。そこはコンパイル時にスペルミスをひっかけて欲しいわけですよ。ストアされているデータと、Foo の定義が違うと、それはそれで実行時エラーになるんだけど。なので、
func createQuery(AnyType) *datastore.Query
のような関数を定義したいな、と思ったのですね。ところが、型は渡せないのです。以下のような方法に落ち着きます。
func createQuery(x interface{}) *datastore.Query { kind := reflect.TypeOf(x).Elem().Name() q := datastore.NewQuery(kind) return q } … var foo *Foo q := createQuery(foo).Filter("Y =", "xaxtsuxo") var foos := make([]Foo, 0, 10) keys, err := q.GetAll(c, &foos)
あぁ foo 使わないのに。いや、 配列の foos があるんで、そっち使えよって話なんだけど。なんなら GetAll せずに、foo を使ってイテレートするのが筋なのかも知れません。
ああ、そんなこと言い出したら、Filter にだって文字列を渡してるぞ。そう考えると GAE/Python の NDB はよくできてるなぁ、あのライブラリ作った人は Python のことよく分かってるなぁ。薄いラッパにしたかったんだけど、やっぱり厚くなってしまうのかなぁ。PropertyList とか PropertyLoadSaver をうまく使ったらよいのか? ぎゃぁ。というわけで連休が終わってしまったので、ペースダウンしていきます。
静的型付け言語たる Go ですが、実行時にごにょごにょすることを reflection と言うらしく、reflect パッケージが標準で入っています。
v := Foo{} structField, found := reflect.TypeOf(v).FieldByName("x")
Foo 型に x フィールドが存在すれば、found に true が入ります。http://play.golang.org/p/F9TY4RcBEC
値とポインタは異なった型なので、もとの struct にたどり着くまでの道筋が異なります。 http://play.golang.org/p/_V19gURisU
v := Foo{} typeFromValue := reflect.TypeOf(v) p := new(Foo) typeFromPointer := reflect.TypeOf(p).Elem()
それから struct 定義のとき、各フィールドにタグをつけられますが、これも reflect パッケージを使って取得できます。http://play.golang.org/p/K__zcCZ7Nd
type Foo struct { int x string `wozozo:"show" hoge:"fuga"` } func main() { v := Foo{} t := reflect.TypeOf(v) field, _ := t.FieldByName("x") fmt.Println(field.Tag) // => `wozozo:"show" hoge:"fuga"` fmt.Println(field.Tag.Get("wozozo")) // => show }
フィールドにつけるタグは文字列ならなんでもいいのですが、key:"value" のフォーマットをスペース区切りにしたものを定義すると、structTag.Get(key) で value を取得できます。Google App Engine では、エンティティのフィールド定義に struct を書くときに、インデックスしてくれるな、とか、struct には含むけどエンティティとして保存するな、のような指示に使われています。
ブラウザから日時を入力させたくて、どうすれば素早く入力できるのかなぁと、いくつか試しました。前提は Bootstrap の responsive を使って、PC とスマートフォンで同じHTML/CSS を使う、ということです。別に、PCとスマートフォンで分けてもいいんだけど、まずは動くものを作りたいので、ブラウザ判定とかしない方向で。一方で、自分が使っている環境、Chrome on Mac OS X と Safari/Chrome on iOS 6、動けばよいので他のブラウザでの互換性は気にしていない。Android とか危うい気がする。
いくつか試してみたところ、 HTML5 の input タグの属性に type="datetime" や type="datetime-local" を指定するのが、いちばん入力しやすく、11秒で入力できました。入力しやすさ、の指標は「iPhone の Safari を使って、テキストフィールドに『ビール飲むぜ』と入力し、さらに、今から1時間以上先のキリのいい時間時刻(今が19:30なら21:00)を入力するまでの時間」です。
他の方法は以下のとおり。
意外とどれを使ってもあまり変わらず。iPhone の場合、wheel scroller っていうんですかね、あれを、複数項目に対して使えるかどうか、が鍵なのかも知れません。
Go で時刻を文字列にフォーマットしたくなりました。結論から言うと、time.Time 型の Format 関数の引数に、「2006年1月2日午前3時4分5秒」を、どう表現したいのかを指定します。
t := time.Time.Now() var x := t.Format("01/02 15:04")
とすると、現在時刻をこの書式で文字列になります。
最初、t.Format("%y") とか %Y とかしても、そのまま %y とか表示されてしまい、困惑していました。ドキュメントを、一瞥したら
The layout defines the format by showing the representation of the standard time,
Mon Jan 2 15:04:05 -0700 MST 2006which is then used to describe the time to be formatted.
と書いてあって「だから年や月のフォーマットはどうやって指定するんだよ」と思ったわけです。
ソースをしばらく眺めていて、あーそういうことであったか、と、やっと分かりました。Parse() 関数も同じ方法で文字列から時刻に変換します。
時刻文字列の書式をこんな方法で指定するのは初めて知りました。知らなかっただけで、実はメジャーなのかも知れません。
明日の自分へ: ドキュメントを読めと、あれほど。
Luper というアプリを知りました。毎月とか、半年ごととかに連絡とりたいコンタクトを登録しておくと、リマインドしてくれるというもの。
今じゃだめ、後でやる必要がある、というタスクの管理も有用であるなぁと最近思い始めました。いろんなアプリがあると同期や移行が面倒なので、Luper は使わないけど。
Mac を使っていて、いつも再起動するとローカルの 8080 ポートが使われていて、Google App Engine のローカルサーバを立ち上げようとするとエラーがでました。それで Evernote にメモしてあるコマンドを叩いて終了させる、ということを繰り返していました。なんか、めっちゃバタバタしているとき(つまり、いつも)に、とりあえずやって、そのままだったのです。
自分のクビをしめるのはやめておこう。ってことで。動いていたのは Jenkins です。朦朧とした頭で、ビルド、インストール、設定したら自動で立ち上がるようになっていました。
Web API をもつアプリケーションのテストを、Python と requests ライブラリを使って書いています。それはよいのですが、テストが通らなかったときですよ。酔ってますよ、もう、休日に仕事してぜんぜんはかどらなくて。それと、これとは別ですけど。
アプリケーションが Python で書かれていない場合、開発者が Python 環境を自由に使えない場合があります。テストのレポートを再現するためだけに、Python モジュールをインストールしてもらうのも気が引けます。
というわけで、requests を使ったアクセスを、 curl で再現するように hooks に追加することにしました。最初から curl 使えよとか、いろいろあると思いますが、すでにレイヤをまたいで requests 使ってたもので。
import curledrequests as requests requests.debug = True requests.post('http://example.com/', auth=("foo", "bar"), data={"hoge":"moge"})
のように書くと、
$ curl http://example.com/ -u 'foo:bar' -w '\n%{http_code}\n' ... ここに body が入る ... 200
と表示されます。これを Web API 開発者に渡して、再現してもらうことができます。gist においてあります。
Go Conference 2013 Spring 略して GoCon に行ってきました。
公式チュートリアルであるところの A Tour of Go というのがあります。1ページにコードと文書があって、Run ボタンをクリックすると実行結果が見られます。以前にこれを読んだことがあったのですが、よく分からないまま Run ボタンを押して、どんどんページを送っていって、結局何も分かっていない、という状態になりました。そこで今回は写経することにしました。
ダウンロードサイト から、OS X のバイナリをダウンロード、インストールして写経をしていたら、主催者の @ymotongpoo が Go Playground を教えてくれました。ブラウザで Go のコードを書いて、その場で実行できます。実行時間が短く、サードパーティのライブラリを必要としないコードであれば、これで簡単に実行できます。そういうわけで、Go Playground でチュートリアルをやっていきました。
ついでに書いたコードを簡単に共有するための URL も生成できます。
Go では変数とポインタが明確に区別されます。普段つかっている Python では名前にオブジェクトをバインドするモデルで、事実上すべてがポインタみたいなものです。ここはちょっと注意が必要でした。Go では x = y と書くと x に y のコピーを代入します。ポインタ(というか参照というか)は明示的に & を使います。
package main import "fmt" type Foo struct {val int} func main() { f := Foo{0} g := f // 変数なので f のコピー h := &f // ポインタ f.val++ fmt.Println(f.val) // => 1 fmt.Println(g.val) // => 0 fmt.Println(h.val) // => 1 }
一方 Python では x = y と書くと、x に y のポインタ(というか参照というか)を代入します。コピーを代入するには明示的に copy モジュールを使うという考え方です。
from copy import copy class Foo(object): def __init__(self, val): self.val = val f = Foo(0) g = copy(f) # copy h = f # pointer f.val += 1 print(f.val) # => 1 print(g.val) # => 0 print(h.val) # => 1
並列処理/並行処理を Go は言語レベルでサポートしていて、go foo(..) と書くと、foo() 関数の呼び出しが非同期で実行できます。
トイレで「goroutine ってコルーチンなんだなぁ」と思っていたのですが、席に戻った瞬間 @Jxck_ さんの発表 で「goroutine はコルーチンではありません」と電撃発言です。どうやら OS のスレッド上で動作する並行ルーチンとして実装されているようです。
実装はおいといて、コルーチンを使ったトランポリンみたいなことが簡単に書けそうです。ちなみにトランポリンの理解は非常に曖昧です。
goroutine として呼び出す時でも、関数は通常の引数をとるので、ポインタを渡すことができます。ということは、複数の goroutine で同じオブジェクトを参照するという事態が起こるんだろうなぁと考えて、簡単なコードを書きました。
package main import ( "fmt" "time" ) type Foo struct { value int } func main() { f := Foo{0} // 初期値は 0 fmt.Println(f.value) go Incr(&f, 1, 1) // +1 go Incr(&f, 2, 200) // +2 time.Sleep(1 * time.Second) fmt.Println(f.value) // => 2 } func Incr(f *Foo, delta int, wait time.Duration) { oldValue := f.value // 古い値を取得して time.Sleep(wait * time.Millisecond) // しばらく休んで f.value = oldValue + delta // 上書き }
プロセスをまたいでいる時にどうなるかは不明です。こんなときにスレッドセーフじゃないようなコードを書くなという話なわけです。
#gocon 会場のはじっこで @ikasamt @torufurukawa と熱いFPGAトークしてたらbuchoがハード設計バリバリな人だってことが判明した
— Kazunori Satoさん (@kazunori_279) 2013年4月13日
これは明らかに誤解なのですが、気分がよかったので、Twitter 上では訂正せずにいました。
以前の職場で開発環境/ツールのマーケティングをしていて、そのラインナップに FPGA 用にコードを書くツールが含まれていました。もともとグラフィカルに記述すると、PC 用に実行形式のバイナリを吐き出すというツールで、簡単に並列処理を記述できたのです。そこ発展して FPGA を搭載した I/O ボードの処理をデプロイできる、というツールです。
そんなわけでハードの設計は、まったくできません。ただFPGAを使うときにはプログラムの書き方が、大きく変わる、というのは感じています。Go も並列処理を念頭においた言語らしいので、あらためて並列処理を考える時期にきているようです。
mock.patch() の挙動について質問されて、即答できなかったので、簡単に調べ直してみました。
まず以下のようなコードを想定します。
# foo.py その1 import random def pickup(seq): return random.choice(seq)
random.choice() 関数は呼び出すごとに挙動が変わり、テストしにくいので、mock の出番です。
# test.py from unittest.mock import patch import foo with patch('random.choice') as m: m.return_value = 0 assert foo.pickup([1, 2, 3]) == 0
ここで foo.py の書き方を以下のように変えます。
# foo.py その2 from random import choice def pickup(seq): return choice(seq)
pickup() 関数を外側から見た挙動は同じです。しかし、なんということでしょう、test.py を実行すると assert が失敗します。pdb や print を使って調べるとわかりますが、choice() 関数が Mock オブジェクトになっていません。
with patch('random.choice') のコンテクストに入るとき、大雑把に以下のようなことが起こります。
import random random.choice = Mock()
※ 実際には Mock ではなく、そのサブクラス MagicMock ですが、この議論の本質ではないので、Mock で話を進めます。
Python のプロセスでは、モジュールはシングルトンとしてふるまうため、プロセス内で random.choice という名前は、Mock オブジェクトを参照することになります。foo.py その1の中では random.choice という名前を使っているため、Mock オブジェクトを参照します。
ところが foo.py その2 は random.choice という名前を参照しているわけではありません。from random import choice すると、大雑把に以下のようなことが起こります。
import random choice = random.choice del random
patch() 適用後、名前の参照先は
のようになっています。このため、foo.py その2では choice がモックにならないのです。
じゃあ、どうするのかというと、普段は patch('foo.patch') としています。上記の問題が発生するような状況だというのが分かっていれば、これで解決です。しかしながら、foo.py を、その1からその2に実装を変えたとき、テストが fail するけれど、どこがどうなっているのか見つけにくいな、と思いました。
その1のときに、test.py に patch('foo.random.choice') と書くとよいのでしょうか。こうすると foo.py その2に書き換えてテストすると、fail ではなくて patch() 実行時にエラーが出るので、名前がおかしいことに気付くような気がします。
あなたは文字揃えの扱いに慣れてきました。しかしいっそうの訓練を積むまでは、 1ページに1種類の文字揃えだけを使うようにしてください。つまりすべての文字列を、左揃えか、右揃えか、中央揃えかのどれか一つにするのです。
もし関連する項目がいくつかあるなら、それを近接させてグループにしましょう。直接的な関連をもたない項目は離しましょう。
反復は、一貫性をさらに強化したものです。約物、書体、線、色など、あなたがす でに繰り返し使っている要素を見つけて、そのうちの一つを強調して反復の要素と して使えないか考えてみましょう
コントラストは、染みを隠すために壁を塗るのに似たところかあります。染みの上に塗る色が周りの色とだいたい同じではだめで、正確に同じ色にするか、それが不可能なら壁全体を塗り直すしかないのです。
Python 温泉の簡易版です。なんと温泉もありません。
文字コード周りの挙動がアヤシイときにはbuchoに助けてもらいました。
@torufurukawa と酔っぱらいUstreamしてたらあんまり出来ませんでした。
html_use_index = False html_show_sphinx = Falseヘッダは layout.html という、すべてのテーマが継承しているファイル document という文字列が定義されているようでした。ようでしたというのは、このあたりで調べるのをやめました。というのは、 conf.py に自前の CSS を定義できることに気づいたからです。
def setup(app): app.add_stylesheet('torumemo.css')
div.related {display: none}
> HSET quiz:1:user alice '{...}'
(integer) 1
> SADD index:quiz:1:answer:X:users alice
(integer) 1
> SADD index:user:alice:quizzes 1
(integer) 1
> HSET quiz:2:user alice '{...}'
> SADD index:quiz:2:answer:Y:users alice
> SADD index:user:alice:quizzes 2
> HSET quiz:1:user bob '{...}'
> SADD index:quiz:1:answer:X:users bob
> SADD index:user:bob:quizzes 1
> HGET quiz:1:user alice
"{...}"
quiz=1 の回答、回答数、および回答したユーザは、このハッシュから取り出します。
> HGETALL quiz:1:user
1) "alice"
2) "{…}"
3) "bob"
4) "{…}"
> HLEN quiz:1:user
(integer) 2
> HKEYS quiz:1:user
1) "alice"
2) "bob"
quiz=1 かつ ans=X の回答数、回答したユーザ、回答は index:quiz:1:answer:X:users セットから取り出します。
> SCARD index:quiz:1:answer:X:users
(integer) 2
> SMEMBERS index:quiz:1:answer:X:users
1) "alice"
2) "bob"
> HMGET quiz:1:user alice bob # クイズ番号とユーザ名を使って、ハッシュから取得
1) "{…}"
2) "{…}"
user=alice の回答数、クイズ番号、回答は index:user:alice:quizzes セットから取得します。
> SCARD index:user:alice:quizzes
(integer) 2
> SMEMBERS index:user:alice:quizzes
1) "1"
2) "2"
> HGET quiz:1:user alice
"{…}"
削除するときには、ハッシュと2つのセットを削除します。
> HDEL quiz:1:user alice
(integer) 1
> SREM index:quiz:1:answer:X:users alice
(integer) 1
> SREM index:user:alice:quizzes 1
(integer) 1
と、こんなやりかたで考えています。筋がいいことを願う。
ビジネスであれば、「アジア市場には出るけど、欧米には進出しない」と決めたり、「インフラビジネスはやるけど、個別商品は売らない」と決めることができるでしょう。
Python で Redis を触ってみました。オートインクリメントやインデックス用のkeyを使うイディオムがある。
import json import redis r = redis.Redis() def create_user(name, auth): uid = r.incr('global:next_uid') # ユニークなIDを取得 return put_user(uid, name, auth) def get_user(uid): value = r.get('user:%s' % uid) if value: return json.loads(value) def put_user(uid, name, auth): user = {'uid': uid, 'name': name, 'auth': auth} r.set('user:%s' % uid, json.dumps(user)) r.set('index:user:auth:%s' % auth, uid) # auth -> uid を引くため return user def get_user_by_auth(auth): uid = r.get('index:user:auth:%s' % auth) if not uid: return return get_user(uid) a = create_user('wozozo', 'xxxxxxxx') b = get_user(a['uid']) assert a == b put_user(a['uid'], b['name'], 'yyyyyyyy') c = get_user_by_auth('yyyyyyyy')