MacPro に似た形状のアレを1年使ってみての感想

当時話題沸騰だったアレを、2013年6月11日に購入した。

f:id:moriyoshi:20140602194259j:plain

こんな感じでアップル製品と一緒に並べてみて一通り満足してから、Garbage Collectorとしての利用を開始。

f:id:moriyoshi:20140602200520p:plain

中側の筒 (写真左) の上から外側の筒 (写真右) をかぶせる形で使用する。このような構造になっているのは、ビニール袋を中側の筒にかぶせてあっても、外側の筒で覆い隠せるようにし、美観を損ねないようにするための配慮だ。

近影
f:id:moriyoshi:20140602191928j:plain

  • ビニール袋を中に入れても外側の筒で覆い隠せるので美観が損なわれないのは良い
  • 中の筒は外側の筒よりも半径が3cmほど小さいので、見た目よりかなり容量が小さく感じられる
  • 性能上は競合製品と際立った差は見られない

ロシアでは

別れの時にNginxのモジュールを贈るのが習わしとなっていますので、作りました.

https://github.com/moriyoshi/ngx_ymsr_module

nginxをビルドするときに、

$ ./configure --add-module={ngx_ymsr_moduleのパス}

を指定してあげればOKです。

id:Yamashiro0217 を偲ぶパスを心に決めてください。

あとは、

location / {
    ymsr on;
}

そのURLにアクセスしてください。

moriyoshi@chicwab ~% curl -vv http://localhost/
* About to connect() to localhost port 80 (#0)
*   Trying 127.0.0.1...
* connected
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8y zlib/1.2.5
> Host: localhost
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: ngx_openresty/1.4.3.6
< Date: Sat, 15 Feb 2014 12:45:51 GMT
< Content-Type: text/html
< Content-Length: 5
< Last-Modified: Sat, 15 Feb 2014 11:09:21 GMT
< Connection: keep-alive
< ETag: "52ff4ae1-5"
< X-Yamashiro: エンジニアにメモリを与えないと転職する。あると思います。
< Accept-Ranges: bytes
<
test
* Connection #0 to host localhost left intact
* Closing connection #0

おおっ、 リクエストのたびに名言が出力される X-Yamashiro ヘッダが追加されましたね!

まとめ

R.I.P.

Publishing encoded images via GitHub's public key listing

http://thechangelog.com/github-exposes-public-ssh-keys-for-its-users/
http://blog.id774.net/post/2013/12/16/441/

I wrote a couple of scripts that embed / retrieve images in the disguised ssh public key container.

There surely is some room for improvement since the script doesn't take care of the payload's validity as the ssh public key at all while GitHub actually tries to validate it somehow before importing it to their database. That said, most of the encoded images, which of course need to be small enough, seem to have been accepted so far.

Run embed.py to generate a public-key like string:

$ python embed.py lena.jpg

Then use retrieval.py to actually get the embedded images:

$ curl https://github.com/moriyoshi.keys | python retrieval.py

GoのツールチェインのCコンパイラを使う

(この記事は Go Advent Calendar 2013 の12月24日に公開されるはずの記事でした。関係者の皆様大変申し訳ない。)

はじめに

Goコンパイラをビルドすると、なぜかアセンブラ (5a, 6a, 8a) やCコンパイラ (5c, 6c, 8c) までもがビルドされます。これらはPlan 9のツールチェイン由来のもので、ランタイムライブラリ (src/pkg/runtime) の一部のソースコードのコンパイルに使われます。システムデフォルトのコンパイラを使わない (使えない) 理由は、GoのABIがPlan 9のものをなぞっており、Goランタイム上ではこのツールチェインの生成するコードしか動かせないからです。*1

つまり、このツールチェインを利用することで、Goランタイム上で動くコードをGoではなく全部C言語で書くことができます。

Goのアプリケーション初期化シーケンス

Goアプリケーションのmain関数に処理が渡るまでのステップは次のようなものです。

  1. OSによってバイナリがメモリにロードされる
  2. OSからエントリポイントとして_rt0_{arch}_{os} (例: _rt0_amd64_linux) が呼び出される (cf. src/cmd/ld/lib.c)
  3. _rt0_{arch}_{os} がOSから受け取ったコマンドライン引数 (argc, argv) をスタックに積んで _rt0_go を呼び出す
  4. _rt0_go で main の goroutine の生成、及び main·init() と main·main() の呼び出しが行われる

main·init()

main·init() では動的なグローバル変数の初期化が行われます。また、利用しているパッケージの、{package_name}·init() もここからネストして呼び出されます。この様子は、次のようなコードで確かめることができます。

package main

func test() bool {
    panic("nooo!")
    return false
}

var a = test()

func main() {}
panic: nooo!

goroutine 1 [running]:
runtime.panic(0x21a40, 0x2100d1010)
        /Users/moriyoshi/Sources/go/src/pkg/runtime/panic.c:264 +0xb6
main.test(0x2210254fa0)
        /private/tmp/test.go:4 +0x55
main.init()
        /private/tmp/test.go:8 +0x45
exit status 2

main·main()

メインルーチン。mainパッケージのmain関数がこれに相当します。

Hello World

ここまでの内容を踏まえ、hello worldを書いてみます。

ソースコード

#include <runtime.h>

void main·init() {}

void main·main()
{
    runtime·prints("Hello, world!\n");
}

middle dot

· (U+00B7) は、Mac OS XであればOption + Shift + 9で入力することができます。

  • コンパイル

6cの部分は、アーキテクチャによって変えてください。(ARMであれば5c, x86_64であれば6c, i386であれば8c)

$ go 6c -I $GOROOT/src/pkg/runtime hello.c
  • リンク

6lの部分は、アーキテクチャによって変えてください。(ARMであれば5l, x86_64であれば6l, i386であれば8l)

$ go 6l -o hello hello.c
  • 実行
$ ./hello
Hello, world!

ちゃんと実行されました。

goroutine をCから使う

いきなりハードルを上げて、goroutineをCから使ってみましょう。

#include <runtime.h>


/* runtime.h で宣言されていないので */
extern void runtime·newproc(int32 sz, FuncVal* fn, ...);

void main·init() {}

/* runtimeモジュールには用意されていない */
String itos(intgo i)
{
    byte buf[128];
    byte *e = buf + nelem(buf), *p = e;
    if (i < 0) {
        *--p = '-';
        i = -i;
    }
    while (--p >= buf) {
        *p = "0123456789"[i % 10];
        i /= 10;
        if (i == 0)
            break;
    }
    return runtime·gostringn(p, e - p);
}

/* UTF-8クリーン */
static void ゴ〜(String s)
{
    runtime·printstring(s);
    runtime·prints("\n");
}

void main·main()
{
    FuncVal fv = { (void(*)(void))ゴ〜 };
    intgo i;
    for (i = 0; i < 10; i++) {
        String hello = runtime·gostring((byte*)"Hello from #");
        String is = itos(i);
        String s = runtime·catstring(hello, is);
        /* 第1引数に引数のサイズを与える */
        runtime·newproc(sizeof(String), &fv, s);
    }
    /* goroutineをyieldする前に終了するのを防ぐため適当にwaitする */
    runtime·tsleep(10000000000l, "wait");
}

String構造体がGoのstring型にそのまま対応していて、Goの文字列操作と等価のことをランタイムライブラリの関数呼び出しによって行うことができます。FuncVal構造体は、Goの関数型に相当します。

String構造体はruntime.hで次のように定義されています。

struct String
{
    byte*    str;
    intgo    len;
};


上記のコードの実行結果は次のようになります。

$ ./gohello
Hello from #0
Hello from #1
Hello from #2
Hello from #3
Hello from #4
Hello from #5
Hello from #6
Hello from #7
Hello from #8
Hello from #9

まとめ

  • GoランタイムをCから使うことができました
  • Pythonなど単純な処理系をGoランタイムの上に載せて動かすというようなことができそうで夢が広がります

次は najeira さんです。

*1:ちなみに、このツールチェイン、cgoでも使われます

Goとerror monads

GoCon 2013 autumnの後、yuroyoroなどとと飲んでいて

「Goのエラーを戻り値で引き回すのがどうも冗長」
Haskellのエラーモナドみたいな何かがあればいいのに」
「型パラメータがサポートされればそういうのが書きやすくなるのに」

という話をしていて、クロージャーで関数呼び出しを囲えば今の言語仕様でもいいんじゃないかなと思ってその場で書いてみたものの話。

monad というのがインターフェイスになっていて、次のメソッドを定義している。

  • Do(what func () (interface {}, error)) monad

戻り値であるmonadに対して次にDoもしくはEndが呼ばれたときに呼ぶべき関数を受け取り、その関数への参照を保持するmonadを生成して返す

  • DoIt() (interface{], error)
    • monadの保持している参照先の関数を呼ぶ。内部用のメソッドでDo()から呼び出される
  • End(errorfn func (error)) interface {}
    • モナドの過程のどこかでエラーが発生していたら errorfn を呼び、エラーがなければ最終的な戻り値を返す

そして、これらを実装する just と _error という型がある。

  • just の Do() の中で monad の保持している DoIt() を呼び、DoIt() の戻り値がエラーを示していれば _error を返し、正常ならば新しい just に Do() に渡された引数を入れて返す
  • _error の Do() は中で何もせず、ただ受け取った _error のコピーを返す

しかし

func main() {
    monad := &just {}
    monad.Do(func () (interface {}, error) {
        println("test1")
        return nil, nil
    }).Do(func () (interface {}, error) {
        println("test2")
        // return nil, nil
        return nil, errors.New("1")
    }).Do(func () (interface {}, error) {
        println("test3")
        return nil, nil
    }).Do(func () (interface {}, error) {
        println("test4")
        return nil, nil
    }).End(func (err error) {
        fmt.Printf("I got an error: %s\n", err.Error())
    })
}

こんなメソッドチェイン、誰も書きたいと思わない。

ターミナルで動画を観る試み

Unicode文字セットの一部に、これといって用途がわからないものがある。block elements というものだ。

Block Elements (Range: 2580-259F)

マイコン世代にはおなじみのセミグラフィクス用キャラクターだ。なぜ Unicode 時代にもなってこれが必要だったのだろうという疑問はあるが、何にせよ、ノスタルジーをかき立てる身近な存在には違いない。

今日はこれを使ってターミナルで動画を見てみたいと思ったのでこんなコードを書いた。

出力はこんな感じ。


charfb: semigraphics on a Unicode-capable terminal.

py♨ advent calendar day 12

みなさんこんばんわ。py♨ advent calendar day 12 です。

PySpaに初めて行ったのは第4回、2008年10月24日でしたね。不安と期待が入り交じる中、芳泉閣へと向かったのです。PySpaを知ったのは主催者のVoluntasと知り合ったからで、Voluntasとはビープラウドさんの勉強会 (BPStudy) で出会いました。現地に到着すると、ブログでしか見た事のない有名人が大勢いて。西尾さんとかyoshioriとか怖そうだったのですが杞憂でしたね。ただ予想外に変なメガネかけててわけわからんこと言っている人がいて怖い思いをしたのですが、いつも参考にさせてもらっていた「回転と脱線」というブログを書いてる人だと後で知りました。アメリカ県の人がいたりだとか、サーファーがいたりだとか、なんといろいろなバックグラウンドを持ったギークの集まりなんだろうってかなり触発されましたよね。

ちなみに一番左にいるのが僕です。

第5回 (2009年6月26日) は何を血迷ったか自宅のあった湘南台から来宮まで自転車で行ったのですが、真鶴あたりの坂道で死にそうになりましたね。

寝込みをやられた。

第6回は何らかの事情でキャンセル。

第7回 (2010年6月26日) はどんなんだったかなあ。資料がない。

第9, 10回、何らかの事情でキャンセル。

第11回 (2012年10月26日) ひさしぶりに参加。白い猫がいない。

PySpaにはずっと続いてほしいです。

明日はtakabowです。