kubo39's blog

ただの雑記です。

山陰のうまい飯 2019年

前回の帰省のタイミングでアップデート。松江・米子近郊。

松江

山美世(うなぎ)

  • おすすめ度: 9/10
  • 値段: やや高め

今松江近辺で一番美味しいうなぎはここ。 ちょっと立地がわるいかも、米子空港からは近い。 うなぎの名店は他に「いずも」や「おおはかや」などもある。

神代そば (そば)

  • おすすめ度: 10/10
  • 値段: お手頃

定番中の定番。割子蕎麦がおすすめ。 観光スポットにも近いので観光がてらに。 甘い出雲そばらしさを求めるなら近くにある「きがるそば」のほうがいいかも。

ろんぢん (ステーキ・しゃぶしゃぶ)

  • おすすめ度: 9/10
  • 値段: お高い

高級志向であればここ。島根は牛がうまいのだ。 ここも有名観光地付近なので周辺の散策を兼ねるのがいいかも。

Mr.ビーフ (ステーキ)

  • おすすめ度: 9/10
  • 値段: お高い

島根和牛のシャトーブリアンのステーキが比較的お手頃に食べられる。 ちなみに東京・銀座に姉妹店がある。

博多 (海鮮)

  • おすすめ度: 10/10
  • 値段: そこそこ

郷土料理の鯛まま・かにままをはじめ海鮮がおいしい。

晶福 (飲み屋・海鮮)

  • おすすめ度: 9/10
  • 値段: お手頃

普通の飲み屋っぽい佇まいだが、とれたての海鮮と多種の地酒がおいている。 わりと手頃な価格なのも嬉しいところ。

山陰地ビール館 (地ビール)

  • おすすめ度: 9/10
  • 値段: そこそこ

島根の地ビールが飲める場所。 私的にここのヴァイツェンがわりと好き。

喫茶きはる (和菓子)

  • おすすめ度: 10/10
  • 値段: そこそこ

和菓子職人が作る創作和菓子を楽しめる。松江を感じられるのはここが一番かな。 人間国宝だかなんだからしい?

カフェヴィータ (カフェ)

  • おすすめ度: 10/10
  • 値段: そこそこ

山陰が誇るバリスタ一家の息子・弟の店。 でかいバリスタマシンはみるだけで楽しめる。 なんといってもカフェオレがおすすめ。

クーラン・デ・エール (カフェ)

  • おすすめ度: 9/10
  • 値段: そこそこ

駅前のちょっと大人なカフェ。 コーヒー&アルコールな飲み物が名物。 自家製ケーキもgood。

出雲

吉岡製菓 (洋菓子・和菓子)

  • おすすめ度: 9/10
  • 値段: そこそこ

フルーツを使った創作菓子の店として界隈では有名。 ここは販売のみなので注意。通販でもいいかも。

安来

カフェロッソ (カフェ)

  • おすすめ度: 10/10
  • 値段: そこそこ

山陰が誇るバリスタ一家の息子・兄の店。 ここもカフェオレがおすすめ。 景色も楽しめる。

境港

境港

  • おすすめ度: 8/10
  • 値段: そこそこ~お高い

なんか海鮮いろいろ売ってる、食べれるとこもある。

米子・日吉津

ダックン・ダック (フランス料理)

  • おすすめ度: 10/10
  • 値段: やや高め

コース料理ではここ。素材にこだわった肉も魚も野菜もおいしい。 席は多くないので念の為予約はしたほうがいいかもしれない。 ランチが狙いどころか。

山芳亭 (海鮮)

  • おすすめ度: 8/10
  • お値段: そこそこ

地元民はここにいく。 境港とれたての海の幸を安価に食べられる。

ずっとdruntimeのベンチマークのコンパイルがリンカエラーで落ち続けてる

最近ちっともDMDのビルドがうまくいかない。 ホストのコンパイラとしてDMD 2.087.1にパスを通した状態で、全部(dmd,druntime,phobos)のレポジトリに make -f posix.mak clean をかけた状態でmasterを更新してdmdmake -f posix.mak -j4phobosでも make -f posix.mak -j4 する。

その状態でdruntime直下に移動して make -f posix.mak benchmark-compile-only をかけると以下のようなリンクエラーに遭遇する。

(dmd-2.087.1)$ LANG=C make -f posix.mak benchmark-compile-only
../dmd/generated/linux/release/64/dmd -conf= -m64 -I/home/kubo39/dev/dlang/druntime/import -I../phobos -L-L../phobos/generated/linux/release/64 -fPIC -defaultlib=libphobos2.so -L-rpath=../phobos/generated/linux/release/64 -de benchmark/runbench.d -ofgenerated/linux/release/64/benchmark
DMD=../dmd/generated/linux/release/64/dmd generated/linux/release/64/benchmark --repeat=0 --dflags="-conf= -m64 -I/home/kubo39/dev/dlang/druntime/import -I../phobos -L-L../phobos/generated/linux/release/64 -fPIC -defaultlib=libphobos2.so -L-rpath=../phobos/generated/linux/release/64 -de"
generated/linux/release/64/benchmark: symbol lookup error: generated/linux/release/64/benchmark: undefined symbol: _D4core8internal5array5utils12__ModuleInfoZ
posix.mak:346: recipe for target 'benchmark-compile-only' failed
make: *** [benchmark-compile-only] Error 127

この現象がいつまでたってもなおらない。おかげでrunbench.dでなんでパッチが落ちるのかの原因調査ができない。 もうずっとこんな調子で嫌気がさしてきた。CIは動いているので、なんか自分のところの環境が変なんだろうけどまるっきり見当がつかない。

とにかくこんな調子じゃ開発なんてできやしない。

追記

cloneしなおしてきてもできなかったが、dmd 2.086.1をホストにしたら make -f posix.mak benchmark-compile-only が成功した。dmd 2.087.0以降のregression?

いまさらマンデルブロー集合を書くので、なるべく型安全っぽくを意識した

プログラミングRustをちらちら読んでいたら並列化の例としてあったので、いまさらマンデルブロー集合を実装した。

元のコードがRustなのでなるべく型安全な感じに書いてみたつもり。

  • 他の言語でfind相当のものがcountUntilという名前で、findは別の操作を行う関数だった。紛らわしい。
  • PNGファイルの出力はimageformatsというライブラリを使った。ヘッダから自動で画像形式を推定してくれる、手軽に使えるので便利。
  • nogcというライブラリを使えば型変換をnogcでできるようだが、結局write_imageGC必要とするので用いなかった。
  • tupleの中の要素はinoutと組み合わせられないのか、 stack based variables can be inout だそう。

ソースコードは以下。

import core.stdc.stdlib : exit;
import std.complex;
import std.conv : to, ConvException;
import std.parallelism : parallel;
import std.range : chunks;
import std.stdio;
import std.typecons : Nullable, Tuple, tuple;

import imageformats : write_image;

Nullable!uint escapeTime(uint limit)(Complex!double c) @nogc nothrow pure @safe
{
    auto z = complex(0.0, 0.0);
    foreach (i; 0 .. limit)
    {
        z = z * z + c;
        if ((z.re * z.re + z.im * z.im) > 4.0)
            return typeof(return)(i);
    }
    return (typeof(return)).init;
}

alias Pair(T) = Nullable!(Tuple!(T, T));

Pair!T parsePair(T, char separator)(string s) pure @safe if (__traits(isArithmetic, T))
{
    import std.algorithm : countUntil;

    immutable index = s.countUntil(separator);
    if (index == -1)
        return (typeof(return)).init;
    try
    {
        T l = s[0 .. index].to!T;
        T r = s[index + 1 .. $].to!T;
        return typeof(return)(tuple(l, r));
    }
    catch (ConvException) return (typeof(return)).init;
}

@safe unittest
{
    assert(parsePair!(int, ',')("").isNull);
    assert(parsePair!(int, ',')("10,").isNull);
    assert(parsePair!(int, ',')("10,20").get() == tuple(10, 20));
    assert(parsePair!(int, ',')("10,20xy").isNull);
    assert(parsePair!(double, 'x')("0.5x").isNull);
    assert(parsePair!(double, 'x')("0.5x1.5").get() == tuple(0.5, 1.5));
}

Nullable!(Complex!double) parseComplex(string s) pure @safe
{
    immutable pair = parsePair!(double, ',')(s);
    if (pair.isNull) return (typeof(return)).init;
    return typeof(return)(complex(pair[0], pair[1]));
}

@safe unittest
{
    assert(parseComplex("1.25,-0.0625").get() == complex(1.25, -0.0625));
    assert(parseComplex(",-0.0625").isNull);
}

Complex!double pixelToPoint(Tuple!(size_t, size_t) bounds,
                            Tuple!(size_t, size_t) pixel,
                            Complex!double upperLeft,
                            Complex!double lowerRight) @nogc pure nothrow @safe
{
    immutable width = lowerRight.re - upperLeft.re;
    immutable height = upperLeft.im - lowerRight.im;
    return complex(upperLeft.re + pixel[0] * width / bounds[0],
                   upperLeft.im - pixel[1] * height / bounds[1]);
}

@nogc @safe unittest
{
    assert(pixelToPoint(tuple!(size_t, size_t)(100, 100),
                        tuple!(size_t, size_t)(25, 75),
                        complex(-1.0, 1.0), complex(1.0, -1.0))
           == complex(-0.5, -0.5));
}

void render(ref ubyte[] pixels, Tuple!(size_t, size_t) bounds,
            Complex!double upperLeft, Complex!double lowerRight) @nogc @safe
in { assert(pixels.length == bounds[0] * bounds[1]); }
do
{
    foreach (row; 0 .. bounds[1])
    {
        foreach (column; 0 .. bounds[0])
        {
            immutable point = pixelToPoint(bounds, tuple(column, row),
                                           upperLeft, lowerRight);
            immutable count = escapeTime!(255)(point);
            pixels[row * bounds[0] + column] =
                count.isNull ? 0 : cast(ubyte)(255 - count.get()); /* ensure count.get <= 255 */
        }
    }
}

void writeImage(string filename, const ubyte[] pixels,
                Tuple!(size_t, size_t) bounds)
{
    write_image(filename, bounds[0], bounds[1], pixels);
}

version(unittest) { void main() {} }
else
{
void main(string[] args)
{
    if (args.length != 5)
    {
        stderr.writeln("Usage: mandelbrot FILE PIXELS UPPERLEFT LOWERRIGHT");
        stderr.writefln("Example %s mandel.png 1000x750 -1.20,0.35 -1,0.20",
                        args[0]);
        exit(1);
    }
    immutable bounds = parsePair!(size_t, 'x')(args[2]).get();
    immutable upperLeft = parseComplex(args[3]).get();
    immutable lowerRight = parseComplex(args[4]).get();
    auto pixels = new ubyte[bounds[0] * bounds[1]];

    auto bands = pixels.chunks(bounds[0]);
    foreach (top, band; parallel(bands))
    {
        auto bandBounds = tuple(cast() bounds[0], 1UL);
        immutable bandUpperLeft = pixelToPoint(bounds, tuple(0UL, top),
                                               upperLeft, lowerRight);
        immutable bandLowerRight = pixelToPoint(bounds,
                                                tuple(cast() bounds[0], top + 1UL),
                                                upperLeft, lowerRight);
        render(band, bandBounds, bandUpperLeft, bandLowerRight);
    }
    writeImage(args[1], pixels, bounds);
}
}

追記

imageformatsのnogc版のimagefmtというライブラリがあった。

https://github.com/lgvz/imagefmt

これを使ってちょっとリファクタリングしたコードもはっておく。

import core.stdc.stdlib : exit;
import std.complex;
import std.conv : to, ConvException;
import std.parallelism : parallel;
import std.range : chunks;
import std.stdio;
import std.typecons : Nullable, Tuple, tuple;

import imagefmt : write_image;

Nullable!uint escapeTime(uint limit)(Complex!double c) @nogc nothrow pure @safe
{
    auto z = complex(0.0, 0.0);
    foreach (i; 0 .. limit)
    {
        z = z * z + c;
        if ((z.re * z.re + z.im * z.im) > 4.0)
            return typeof(return)(i);
    }
    return (typeof(return)).init;
}

alias Pair(T) = Nullable!(Tuple!(T, T));

Pair!T parsePair(T, char separator)(string s) pure @safe if (__traits(isArithmetic, T))
{
    import std.algorithm : countUntil;

    immutable index = s.countUntil(separator);
    if (index == -1)
        return (typeof(return)).init;
    try
    {
        T l = s[0 .. index].to!T;
        T r = s[index + 1 .. $].to!T;
        return typeof(return)(tuple(l, r));
    }
    catch (ConvException) return (typeof(return)).init;
}

@safe unittest
{
    assert(parsePair!(int, ',')("").isNull);
    assert(parsePair!(int, ',')("10,").isNull);
    assert(parsePair!(int, ',')("10,20").get() == tuple(10, 20));
    assert(parsePair!(int, ',')("10,20xy").isNull);
    assert(parsePair!(double, 'x')("0.5x").isNull);
    assert(parsePair!(double, 'x')("0.5x1.5").get() == tuple(0.5, 1.5));
}

Nullable!(Complex!double) parseComplex(string s) pure @safe
{
    immutable pair = parsePair!(double, ',')(s);
    if (pair.isNull) return (typeof(return)).init;
    return typeof(return)(complex(pair[0], pair[1]));
}

@safe unittest
{
    assert(parseComplex("1.25,-0.0625").get() == complex(1.25, -0.0625));
    assert(parseComplex(",-0.0625").isNull);
}

Complex!double pixelToPoint(T)(Tuple!(T, T) bounds, Tuple!(T, T) pixel,
                               Complex!double upperLeft,
                               Complex!double lowerRight) @nogc pure nothrow @safe
{
    immutable width = lowerRight.re - upperLeft.re;
    immutable height = upperLeft.im - lowerRight.im;
    return complex(upperLeft.re + pixel[0] * width / bounds[0],
                   upperLeft.im - pixel[1] * height / bounds[1]);
}

@nogc @safe unittest
{
    assert(pixelToPoint!int(tuple(100, 100), tuple(25, 75),
                            complex(-1.0, 1.0), complex(1.0, -1.0))
           == complex(-0.5, -0.5));
}

void render(T)(ref ubyte[] pixels, Tuple!(T, T) bounds,
               Complex!double upperLeft, Complex!double lowerRight) @nogc @safe
in { assert(pixels.length == bounds[0] * bounds[1]); }
do
{
    foreach (row; 0 .. bounds[1])
    {
        foreach (column; 0 .. bounds[0])
        {
            immutable point = pixelToPoint!T(bounds, tuple(column, row),
                                             upperLeft, lowerRight);
            immutable count = escapeTime!(255)(point);
            pixels[row * bounds[0] + column] =
                count.isNull ? 0 : cast(ubyte)(255 - count.get()); /* ensure count.get <= 255 */
        }
    }
}

int writeImage(T : int)(string filename, const ubyte[] pixels, Tuple!(T, T) bounds) nothrow @nogc
{
    return write_image(filename, bounds[0].to!int, bounds[1].to!int, pixels);
}

version(unittest) { void main() {} }
else
{
int main(string[] args)
{
    if (args.length != 5)
    {
        stderr.writeln("Usage: mandelbrot FILE PIXELS UPPERLEFT LOWERRIGHT");
        stderr.writefln("Example %s mandel.png 1000x750 -1.20,0.35 -1,0.20",
                        args[0]);
        exit(1);
    }
    immutable bounds = parsePair!(int, 'x')(args[2]).get();
    immutable upperLeft = parseComplex(args[3]).get();
    immutable lowerRight = parseComplex(args[4]).get();
    auto pixels = new ubyte[bounds[0] * bounds[1]];

    auto bands = pixels.chunks(bounds[0]);
    foreach (top, band; parallel(bands))
    {
        auto bandBounds = tuple(cast() bounds[0], 1);
        immutable bandUpperLeft = pixelToPoint(bounds, tuple(0, top.to!int),
                                               upperLeft, lowerRight);
        immutable bandLowerRight = pixelToPoint(bounds,
                                                tuple(cast() bounds[0], top.to!int + 1),
                                                upperLeft, lowerRight);
        render(band, bandBounds, bandUpperLeft, bandLowerRight);
    }
    return writeImage(args[1], pixels, bounds);
}
}

zshを自前でビルドして使う

zshにパッチあてて使ってるんだけど、ビルド方法とか一応メモしておく。

zshのビルドは楽にできる、まあ今回の作業では必要なかったのだけれど。

$ apt install -y yodl # 依存ライブラリ, あとPerlとかも必要
$ ./Util/preconfig
$ ./configure
$ make

パッチ自体は特にとりあげるほどの内容ではないので割愛。

補完にパッチをあてた場合は、fpathを上書きしてそっちを優先的にみるようにする必要がある。 設定ファイルは邪魔なので読み込まないようにした。

$ zsh -d -f # no-rcs && no-global_rcs
$ fpath=("$(pwd)"/Completion/Unix/Command "${fpath[@]}")
$ autoload -Uz compinit
$ compinit -C
$ nm --demangle= # 補完で `dlang' が出てくるパッチの確認

一応パッチ自体はPR出した。マージされるかわからないけど, わりとすんなり修正できるのでみなさんもzshにパッチ投げてみるといいかもしれません。 (そのあとちゃんとマージされたのでコントリビュッタです)

jailingをD言語にポーティング、やってみた!

kazuho/jailingD言語に置き換えてみました。

これです。

目的

実用的にはLinuxであればどの環境でもPerl5が入っていることは期待できるし外部依存もないので特に意義はないです。 あくまで学習目的というやつです。コードサイズも小さいし、いいかなって。

jailing

説明はここを読んで。

もう少しカスタムできるツールだとfirejailだとかnsjailとかあるけど、このくらいの分量だと学習しやすくてありがたいです。 というかこれだけで立派なchroot+jailになるのいいですね。

D言語

Q: なんでD言語なの?
A: 言わせんな恥ずかしい

書いてみての雑感。

  • わりと標準ライブラリでなんとかなるところがよい?でもけっきょく executeShell ばっかりになるもんなあという気もしないではない。
  • あとはなんか std.path.buildPath なんかはきっちり書きたい感出せる気がする。
  • あ、FFIextern (C) だけすればなんとかなるのでだいぶよい。

D言語で書けばバイナリを配るだけ作戦が使える、のだけど元がPerlPythonスクリプトの場合だと書き換え自体がメリットになりにくい。 jailingのようなツールだとそんなに速度とかいらなさそうだし、どうせプロセス起動が遅いのでさほど変わらんだろう。 Rubyとかだったらスクリプトと別に処理系入れるの面倒じゃない?みたいなところに対してメリットが言えそうなんだけど。 なおこの作戦はGoやRustでも別によいという話もある。

jl

だいたい似たような動機のプロジェクトで yoshitsugu/jl というRustのやつがありました。

Rustだと caps とか libmount とかライブラリがあったりして外部コマンドを使わないで実装できるのはいい感じがします。実行時のメモリフットプリントとかにうれしい。 あと clap みたいなコマンドラインパーサがあるとCLI書くとき便利。 ここでは使われていないけど他にもstructoptとかも便利系のやつです。

ところでjlはコマンド実行も外部プロセスにしてしまってるけどここは CommandExtexec 関数を使うべきでは。

ベイルート・ロンドン・リバプール旅行記

3/25~4/2でベイルート(レバノン)、ロンドン・リバプール(イギリス)旅行に行っていたので雑に記録を残しておく

ベイルート

  • 直行便がないのでフランクフルト経由。フランクフルトのラウンジで食べたパン・ソーセージとビールがこの旅で一番うまかった可能性がある。
  • 到着後もろもろの事情で国防軍の出迎え&謎の力ですんなり滞在ビザを取得できてしまった。
    • 滞在ビザは長蛇の列で質問も結構長くやってたぽいので助かった。
  • ホテルはめっちゃいいホテル
    • やたらおいしいチョコレートが置いてあった
    • ベイルート市内からちょっと離れてるけど景色も綺麗だった
  • 近辺を散策していると生々しい銃痕の痕が。現在でも緊迫した状況を感じる。
  • ホテルで朝食をとっているとどんどんアラブ料理を勝手に運んできてくれてとてもよかった。ヨーグルトやフルーツジュースがめちゃ美味しい。
  • 市内散策ツアー
    • 前後を長銃もった兵士に囲まれるバスツアー
    • ベイルート国立博物館にいったけどローマ時代の遺跡はみられず延々鉱石をみることになった
    • アラブ料理のレストラン。なかなか美味しかったけどホテルのほうがおいしかった。ここでもチョコレートケーキ、そして美味しい。
  • 出国はけっこうたいへんで、3回は危険物チェックゲートを通ったとおもう。

ロンドン

  • ヒースローでかすぎ
  • むこうだとビートルズピンク・フロイドは別格らしい
  • ロンドンはそこかしこで中国語や日本語がきける
  • ホテルはそこそこ
  • イカー・ストリートでホームズ博物館へ。とくになにかあるわけでもないが雰囲気が味わえるのでけっこうよかった。
  • 本場のパブでフィッシュ&チップスとビール、まあこんなもんか
  • コベント・ガーデンでめちゃくちゃ歌うまいおっさんが歌っててよかった
  • 夕飯はチャイナタウンで中華
    • 普通の中華料理だけどイギリスじゃ別格にうまいってわけw
  • 本場ピカデリー・サーカスレ・ミゼラブルをみた
    • ジャベール役の人がめちゃくちゃよかった、多くの人が最後の登場のところでスタンディング・オベーションしていた
    • ソロで特によかったのは star, on my own, bring him home かな

リバプール

  • ホテルは建物すごかったけど設備とかつらかった
    • 朝食がびっくりするほどまずかった。あいつらこれうまいとおもってるんすか・・
    • リバプールはどこで食ってもイマイチだったけど
  • ビートルズゆかりの地を訪ねるツアーに参加
  • 中心部はけっこうオシャレタウン
    • 変なおっさんが火の輪くぐりのパフォーマンスしてた、日本じゃできないだろうな
  • 郊外は労働者の街といった感じ
    • 治安もあまりよくなさげ
  • アンフィールドでliverpool vs spurs観戦
    • 住宅地に突然あらわれるスタジアム
    • 肖像画ダルグリッシュ、ファウラー、ジェラード!など
    • あまりうまくないバンドが「wish you were here」や「Don't look back in anger」を歌ってた。ビートルズは逆に歌いにくい?
    • 生You'll never walk aloneに白熱した試合展開に泣きそうになる

けものフレンズ2を総括する

人にはそれぞれの感想がある、これは自分のために整理するくらいの意味合い

よかったところ

  • ゴマちゃんことゴマすりクソバードがいいキャラだった
  • フレンズのキャラデザがよかった
  • ごまちゃんやチーターの声優演技がよかった
  • 次回予告
    • かわいい
  • ペパプライブの映像クオリティ
    • ここは一期よりもよかったと思えるところ
  • キュルル ロシアのスパイ説

だめだめだったところ

  • 尾崎のサーバル演技がほんとうにひどい
    • 一期の演技が好きだったのでこれはわりと苦痛だった
    • かなりいらいらするレベル
  • サーバルbot感、自我を持っていないような感じ
    • すっごーいbotになっていた
    • 一期サーバルはかばんちゃんのために怒ったりツッコミ役やったり、しっかりキャラクターがあったのに
  • 違和感しか感じないかばんさん
    • サーバルちゃんやラッキーさんをいきなり呼び捨てにしているところ
    • それ自体が悪いというより背景がまったくないので違和感しかない
  • 全体的に脚本がひどすぎる
    • 話として単純におもしろくない
    • 前後のつながりに意味がなさすぎる
  • 設定のガバ
  • キュルルの叡智パート全体的にいらなかったし意味わからなかった
    • 7話でリレーにするのまじで意味がわからなかった
  • フレンズ型セルリアン弱すぎて話盛り上がる要素がない
    • 「緊迫感がまったくない」って言われてたけどほんとうにそのとおりとしかいいようがない
  • まじでいらなかったフウチョウコンビ、というかあれなんだったの?
    • メインの話にもぜんぜん絡まないし単体としてもなんも影響がない
    • 歌も演技も微妙なのでゴリ押しだったんだろうな

おきもち

  • だめなところがとことんだめだった
  • もっとひどいアニメ(例をあげるならいくらでもあるが魔法戦争とか)があるがそれがこの作品を許す理由にはならない
  • 制作陣のSNS対応もけっこうひどいなとおもった
    • アンチにあれだけ絡まれると精神的にもつらいだろうけどそれ抜きでも邪悪だよな
  • けフ2好きな人がいてもいいとおもうしそこを叩くのはよくない
    • ただけフ2好きな人はアニメ作品としての出来ではなくてけものフレンズプロジェクト自体が好きなんだろうなとはおもう
    • で、この人たちは現行の「けものフレンズプロジェクト」のやり方を(消極的かもしれないにしろ)認めているわけで、やっぱりわかりあえないんだろうな、と
  • キュルル叩かれすぎでは
    • 人間の子供としてはあんなものじゃないかなあ、そんなに悪人的な描写なかったとおもうんだけど