PyConJP 2016に行ってきた話

初めてのPyCon JP参加でした。

1日目

  • 基調講演

朝がつらいので基調講演は間に合いませんでした。

どんな話かなーと思って見に行ったけど、同時間帯の週末サイエンティストも見たかったので、最初の10分位さらっと聞いて離脱。 「研究者の方と話してみたいという方は、この機会にぜひ講演を聞きに来てください。」という概要だけど、私がその研究者なんですよね。

面白いはなしでした。正直クラウドVPS借りても研究したければそこそこ課金しなきゃならないので、 安価ではないと思いますが「大人の趣味は金を費やすもの」らしいので、なるほどなと納得。

サイエンティストへの指針みたいなかんじでとても良かったのです。

しかし、注文をつけるとすれば、趣味として研究したい人っておそらく専門を持たない人なんじゃないかなーとか思うので、 「研究テーマをどのように見つけるか」とかも話してほしかった。まあ論文読めば流行りのホットなテーマとかわかるんですけど、 論文読むにも基礎知識が必要だったりするわけで。大学で昔やってましたって人はまだ続きやるって選択もあるけど、 まったく新しいこと始めようとすると研究テーマ決めるの難しいんじゃないですかね。その辺、質問タイムがあったら聞こうかと思ったけど、 なかった。

初級対象だったし、まあそんなもんかな、って感じ。PyInstallerを使ったfreezing(exe化のこと)を解説してました。 Qt Designerを使ったGUIの作り方とかも少しだけ解説してましたね。 GUIとかやったことない人も多そうだったので、そういう発表も良いなってとこでしょうか。

私自身はそういうのそこそこすでにやってるので、新しい知見を得られたかというと微妙でしたけど。初級だしそれは仕方ない。

中級向けに、cx_FreezeとPyInstallerとpy2exeの依存解析フローの違いとか、具体的なfreezingの仕組みとかあるといいですね(私がやればいいのだけど調べる時間がね)

がんばって説明してました。時間が足りなくなって後半のおもしろいとこがちゃんと発表できてなかったので惜しいですね。 数学的なところも理解して使おうって気持ちは大事だと思います。

前半部分のニューラルネットの基本的なとこに時間をかけてしまっていたのですが、そういうとこは私は大学1年か2年くらいで数学的にもプログラミング的にも やったことあるので、得たものはそんなにないかな。じゃあなんで見に行ったんだってかんじですが。

私も複数の言語組み合わせてる系なので聞きにいきました。Cython推しでしたけど、私はCython好きじゃないです。 C++でShared Library作ってPythonから呼び出した方がいいと思いますけどね。まあ宗派の違いってことで。

内容自体は、だいたい知ってる話だったかな。。

あまりDeepLearningとか私はやらんのですけど、確率的最適化とかは他の分野でも使われだしてるし、興味持ったので見に行きました。 超満員で立ち見でも場所がないくらいの大人気でした。話もわかりやすく、とても良い発表です。

  • 二日目午前中

すいません。時間はあったんですけど、タイトーステーション行ってDDRしてました。

二日目はこれ目的に行ったようなもんですね、具体的なやりかたはちょっとわからなかったですが、 メタプログラミング始めようとしたときの検索ワードとか仕入れられました。

でもPythonメタプログラミングやりたいとは思わないかなという印象。

  • 雑記

ポスター、オープンスペースありましたが良いと思います。

来年ポスター出してみようかな。トークで出すより参加者と直接話せるし、交流手段としてポスター最強な気がする。 ポスター出してた人達の何人かにガチ質問投げてました、すいません。

オープンスペースは1日目結構空きがあったみたいですけど、自由に部屋使えるしなんかやればよかったですね。

あと、PyConJP、メシがたくさん食べられてよかった。

新しい知見がたくさん得られたかというと、私にとってはそうでもなかったかな。もうちょっとレベル高めを想定してたんですが、 初級から中級の人にもやさしいかんじ。上級者は自分でコネクション作って情報集めればいいので、人が集まる場としてとても良いです。

来年は発表側に回って中上級向けの話した方が良いかなーというのが一番強い感想かなあ。

Metashellを使ったC++メタプログラミングの入門とデバッグ

この記事は

C++ Advent Calendar 2015の第1日目です。 今年は初心者向けのゆるい記事を書くための初心者 C++ Advent Calendar 2015も あるにも関わらず、どうやら埋まりそうです。参加者の皆様ありがとう。

この記事ではMetashellの使い方とメタプログラミングの初歩をやります。

対象としてる読者

Metashellとは何か

本家ドキュメントのMotivationをざっくり意訳します(翻訳とはいってない)。

When one starts learning a new programming language such as Haskell, Python or Erlang an interactive shell (python for Python, ghci for Haskell, erl for Erlang) is available for experimenting with the language. Later, after getting familiar with the language, this shell becomes a tool to try code out, verify test results or learn more about the problem during debugging.

対話型環境(例えばHaskellghci, Pythonpython, Erlangerl)を使うと、 色々と試しながらプログラミング言語を習得することができます。習得後でも、 ちょっとしたコードを実行したり、その結果を確認したり、あるいはデバッグの際にも 対話型環境は役立ちます。

When one starts learning C++ template metaprogramming, he has to use a C++ compiler which was designed to compile code and not to play with template tricks. People new to template metaprogramming have to learn how to make the compiler show them the result of simple metaprograms. This makes it more difficult to get started with template metaprogramming.

C++テンプレートメタプログラミングを学び始めるには、 コンパイラを使ってコードを試しますが、コンパイラはコードをコンパイルするためのもので、 テンプレートで色々と遊んでみるものではないのです。 入門者はまず、簡単なメタプログラミングの結果を 「どのようにしてコンパイラに表示させるか」から学ばなければなりません。 このためメタプログラミングの習得は難しいのです。

Later, after getting familiar with template metaprogramming, developers have to use the compiler for testing and debugging. Understanding what is going on in a template metaprogram during debugging is difficult, since the compiler needs to be forced to present the result of a metaprogram (or a part of it) - and compilers are not prepared for this. This extra difficulty in debugging makes simple problems look difficult.

テンプレートメタプログラミングに慣れた後でも、開発者はテストやデバッグコンパイラを使わなければなりません。 デバッグのためには、コンパイラにメタプログラムの結果(あるいはその一部)を表示させますが、 コンパイラはそのような用途を想定して作られてはいないので、簡単なはずの問題が複雑に見えてしまうという余計な問題が生じます。

Metashell provides an interactive shell similar to the Python, Haskell and Erlang shells for template metaprogramming. It uses Clang to evaluate the metaprograms.

Metashellはテンプレートメタプログラミングのためのシェルです。Python, Haskell, Erlangのシェルと同じような対話型環境です。Metashellはメタプログラムを評価するのにClangを利用しています。

C++メタプログラミングのハードルが高いのはなぜか

上記本家ドキュメントのMotivationを要約すると、ちょっとコードを試してみようとしても毎回コンパイルかけなければならず、しかも結果を確認するのも手間がかかると。だからコンパイルかけなくてもコードを試せるメタプロ用の便利なシェルを作りましたということですね。 メタプロが難しい原因はこれだけではないですが、理由の1つではあります。

Metashellの特徴

  • 対話型環境(REPL)なので、結果をすぐ確認できる。
  • Windows,Mac,Linux,BSD(FreeBSD,OpenBSD)で使える。
  • オンライン版ならば今すぐブラウザで使える。
  • ライセンスはGPL3

インストール方法

基本的にはここ読めば書いてあります。 まず試してみたい人はOnline版があるのでとりあえずインストールしなくてもいいです。

Windows

何も考えずにバイナリインストーラ使いましょう。オプション全部デフォルトのままでインストールすればいいです。

Mac

Homebrewでインストールできるそうです

$ brew install metashell

Linux

Ubuntu, Debian, Fedora, OpenSuSEしか公式バイナリは用意されてないみたいですが、それ以外のディストリでもコンパイルすれば使えると思います。私はArch Linuxで素直にコンパイル通った・・気がします(覚えてない)。コンパイル時間は長かった気がしますので覚悟。Building manuallyのところ読めばLinux使ってる人はたぶん普通にできるので解説省略。

起動方法

インストールした場合

Windowsをターゲットに解説。基本的にはLinuxでもMacでも同じです。

インストールするとスタートメニューに出てくるのでクリックすれば起動できますが、この方法ではBoostとかのヘッダパスを探してくれません。しかもC++0xモードになってしまいます。なのでコマンドプロンプトからオプションつきで起動させましょう。

"C:\Program Files (x86)\metashell 2.1.0\bin\metashell.exe" --std c++14 -I C:\Users\ignis\Documents\boost_1_59_0\boost_1_59_0

パスは適宜書き換えてください。 -I以降はBoostを利用しない場合は不要です。

f:id:ignisan:20151201180909p:plain こんな感じで起動するはずです。わからなければとりあえずOnline版を使いましょう。

Online版を使う

Metashell demo から Start Metashellに行けば使えます。C++14オプションはいれましょう。

メタプログラミング入門

簡単なコンパイルタイム計算をやってみます。本家ドキュメントではBoost.MPLを使ってますが、ここでは標準ライブラリのみで進めます。

整数を型で表そう

std::integral_constant

まず std::integral_constant を使って整数を型として表現します。integral_constantC++11から標準ライブラリに入りました。type_traitsヘッダをincludeすることで使えるようになります。典型的には

template<class T, T v>
struct integral_constant {
    static constexpr T value = v;
    typedef T value_type;
    typedef integral_constant type;
    constexpr operator value_type() const noexcept { return value; }
    constexpr value_type operator()() const noexcept { return value; } //since c++14
};

と定義されます。C++メタプロ入門者はまず、static constexpr T value = v;に注目してください。例えば、

std::integral_constant<int,4>;

は、int型で値が4というvalueを内包する型になります。

metashellで見てみる。

まずはヘッダファイルを読み込みます。

> #include<type_traits>

次に、integral_constantを使って整数を型として表現します。

> std::integral_constant<int,4>

すると次のOutputが出ます。

std::integral_constant<int, 4>

この型のvalue_typeintのはずです。確認してみましょう。

Input:

> using four = std::integral_constant<int,4>;
> four::value_type

Output:

int

このようにMetashellでは、型を入力すると即座に結果が見られるので非常に便利です。

値を表示するには

Metashellは型を表示させることはできますが、値を表示させることはできません。したがって、

decltype(3)

intと表示されますが、

> 3

は型ではなく値なので、エラーとなります。これはなかなかに不便なので、metashellは値を型に変換するSCALARマクロを用意しています。

Input:

> #include<metashell/scalar.hpp>
> SCALAR(3)

Output:

std::integral_constant<int, 3>

足し算を定義してみよう

整数を表す型が表現できたので、次はその型同士のコンパイルタイム足し算を作ってみます。

Input: (※metashellでは複数行の入力は行末にバックスラッシュをいれます)

> template<class L, class R> struct plus {           \
...> using type = std::integral_constant<            \
...>                  decltype(L::value+R::value),   \
...>                  L::value+R::value>;            \
...> };

LとRにはstd::integral_constantが入ります。LとRそれぞれが持つ値は::valueで取れますので、足し算は L::value + R::valueです。足し算の結果の型は少し厄介です。 intintの足し算の結果はintですが、実際に渡される型はintとは限らないため、 decltypeで足し算の結果となる型を得ています。

足し算ができるか、確認してみます。

Input:

> using one = std::integral_constant<int,1>;
> using five = plus<one, four>::type;
> five

Output:

std::integral_constant<int, 5>

できました!

0から10までの和を計算してみよう

ループに相当する処理を含むメタプロです。和の計算は

{ \sum_{i=0}^{N} = N + \sum_{i=0}^{N-1} }

とかけるので、これをこのまま再帰で計算すれば良さそうです。N=0を特殊化することで終了条件にできます。

Input:

template<int N>
struct sum {
    using type = std::integral_constant<
                    decltype(N+sum<N-1>::type::value),
                    N+sum<N-1>::type::value>;
};

template<>
struct sum<0> {
    using type = std::integral_constant<int,0>;
};

試してみましょう。

Input:

sum<10>::type

Output:

std::integral_constant<int, 55>

フィボナッチ数列を計算してみよう

(書く時間が足りなくなってきたのでやめます)

メタプログラミングデバッグ

メタプロ初心者だとすでに難しくなってるかもしれないので、デバッガを使って1ステップごとに処理を確認してみます。

デバッグモードに入ります。

Input:

#msh mdb sum<10>::type

Output:

(mdb)

(mdb)という表示になったら、デバッグモードです。デバッグモードをやめるにはquitを入力します。

1ステップ毎に実行する (Stepping)

2回ほどstep 1と入力してみましょう。

(mdb) step 1
sum<10> (TemplateInstantiation from <stdin>:2:26)
(mdb) step 1
sum<9> (TemplateInstantiation from /tmp/just-hiSTUS/metashell_environment.hpp:14:77)
   12  #include<utility>
   13  #include<metashell/scalar.hpp>
-> 14  template<int N> struct sum { using type = std::integral_constant<decltype(N+sum<N-1>::type::value), N+sum<N-1>::type::value>; };
   15  template<> struct sum<0> { using type = std::integral_constant<int,0>; };
   16  #include<metashell/scalar.hpp>
(mdb)

一度目のstep 1でテンプレートのInstantiationが始まります。2回目のstep 1ではsum<9>template<int N> struct sumで呼ばれています。10+sum<9>::type::valueのところですね。その後何度もstep 1を続けていくと、

sum<0> (Memoization from /tmp/just-7ReGgQ/metashell_environment.hpp:14:77)

とでます。Memoizationというのは、雑に説明すると1度評価したことがあるので、以前の計算結果を使うという意味です。sum<0>は厳密に言えば評価済みではありませんが、特殊化してあるのでMemoization扱いになります。

このようにMetashellでは1ステップ毎に(もしくはnステップ毎に)メタプログラムを実行していくことができます。

やってから気づいたのですが、単純な総和だとデバッガ走らせても面白くない。。

指定したところで中断させる、そして再開させる(Breakpoints and continue)

sum<0>が呼ばれるまで実行させたい場合はブレークポイントを使います。まずはメタプログラムの最初の実行まで戻ります。

(mdb) evaluate
Metaprogram started

もしくは単純にeでも良いです。

sum<0>が呼ばれたら停止する、というブレークポイントを設置します。

(mdb) rbreak sum<0>
Breakpoint "sum<0>" will stop the execution on 2 locations

2箇所で停止するようです。では実行させてみましょうcontinueもしくはcコマンドを使います。

(mdb) continue
Breakpoint "sum<0>" reached
sum<0> (Memoization from /tmp/just-nOimAz/metashell_environment.hpp:14:77)
   12  #include<utility>
   13  #include<metashell/scalar.hpp>
-> 14  template<int N> struct sum { using type = std::integral_constant<decltype(N+sum<N-1>::type::value), N+sum<N-1>::type::value>; };
   15  template<> struct sum<0> { using type = std::integral_constant<int,0>; };
   16  #include<metashell/scalar.hpp>

きちんとsum<0>の呼び出し時でデバッガが停止しました。

実行履歴をみる (BackTrace)

ブレークポイントで停止した位置までの履歴をbtコマンドで見ることができます。

(mdb) bt
#0 sum<0> (Memoization from /tmp/just-nOimAz/metashell_environment.hpp:14:77)
#1 sum<1> (TemplateInstantiation from /tmp/just-nOimAz/metashell_environment.hpp:14:77)
#2 sum<2> (TemplateInstantiation from /tmp/just-nOimAz/metashell_environment.hpp:14:77)
#3 sum<3> (TemplateInstantiation from /tmp/just-nOimAz/metashell_environment.hpp:14:77)
#4 sum<4> (TemplateInstantiation from /tmp/just-nOimAz/metashell_environment.hpp:14:77)
#5 sum<5> (TemplateInstantiation from /tmp/just-nOimAz/metashell_environment.hpp:14:77)
#6 sum<6> (TemplateInstantiation from /tmp/just-nOimAz/metashell_environment.hpp:14:77)
#7 sum<7> (TemplateInstantiation from /tmp/just-nOimAz/metashell_environment.hpp:14:77)
#8 sum<8> (TemplateInstantiation from /tmp/just-nOimAz/metashell_environment.hpp:14:77)
#9 sum<9> (TemplateInstantiation from /tmp/just-nOimAz/metashell_environment.hpp:14:77)
#10 sum<10> (TemplateInstantiation from <stdin>:2:26)
#11 sum<10>::type

一番上が現在位置(breakpoint)一番下がメタプログラムの最初です。順番にN-1しながらsumが呼ばれています。

(Forwardtrace)

バックトレースの逆です。これから実行されるメタプログラムを順番に表示していきます。 以下、記事を書く時間が尽きましたので、またの機会に加筆します(やらないパターン)。

Profiling

Formatter

次は

adatcheyさんの C++ - Variadic Template を使って switch を使ったテンプレート関数呼び出しを除去する - Qiita

です。

mpld3でmatplotlibの図をWebに表示させる。

mpld3

mpld3 -Bringing matplotlib to the Browser- http://mpld3.github.io/

Install

とりあえずvirtualenv

$ mkdir mpld3
$ virtualenv3 mpld3
$ cd mpld3
$ source bin/activate

numpy, matplotlibをいれる。 そこそこ時間かかるので待つ。

$ pip install --upgrade pip
$ pip install numpy matplotlib

mpld3はgithubから取ってくる。pipのやつを使うと古いのでエラー出る。

$ git clone https://github.com/jakevdp/mpld3.git
$ cd mpld3
$ python setup.py install
$ cd ..

試しに動かす

sin.py

#!/usr/bin/env python
import numpy as np
import pylab as pl
import mpld3

x = np.linspace(0,2*np.pi)
y = np.sin(x)

pl.plot(x,y,"-o",lw=3)
mpld3.show() # localhostで動かす
#mpld3.show(ip="example.com") # サーバを指定する場合
$ python sin.py

デフォルトでは8888番ポートを使うので、 http://127.0.0.1:8888/ にブラウザからアクセスすると見れる。 左下のアイコンをクリックすると移動とか拡大縮小とかできる。

f:id:ignisan:20150903224911p:plain

2.7 Dynamic

目次に戻る

2.7 Dynamic

Haxeは静的型システムをもっているが、Dynamic型を使えば 事実上この型システムを切ることができる。 dynamic値はどの型にも代入できるし、どの型の値もDynamic型に代入できる。 これには次の弱点がある。

  • コンパイラは変数への代入、関数呼び出し、その他のconstructsで、 どの型が使われるべきかという型チェックができなくなる。
  • 特に静的型システムを使うターゲットにおいて、最適化が使われなくなる。
  • よくあるエラー(例えばtypoとか)をコンパイル時に見つけることができなくなる。 これらは実行時エラーとなる。
  • Dead Code Eliminationは、 Dynamicを通して使われると使用されているフィールドを検出できない。

Dynamicの利用によって実行時にエラーが出る例を考えつくのは簡単だ。 静的ターゲットで次の2行をコンパイルする。

var d:Dynamic = 1;
d.foo;

コンパイルしたプログラムをFlash Playerで実行すると Property foo not found on Number and there is no default value というエラーが出る。Dynamicにしなければこのエラーはコンパイル時に検出されたはずだ。

Tribia: Haxe3以前のDynamic Ingerface

Haxe3コンパイラは何かの型をDynamic型と推論することはない。so users must be explicit about it (訳注:訳せない)。以前のバージョンのHaxeは異なる型が混ざった配列、例えば[1, true, "foo"]Array<Dynamic>と推論していた。我々はこの振る舞いは多くの問題を引き起こすことがわかったんで、Haxe3ではやめた。

Dynamicの使用は最小限にするべきだ。通常は他にもっといい方法がある。しかし、稀にDynamicを使うことが現実的である場合もある。Haxe Reflection APIの一部ではDynamicを使っている。コンパイル時にはわからないようなカスタムデータ構造を扱うような場合には、それが最良の選択になることもある。

Dynamic behaves in a special way when being unified with a monomorph(訳注:unifiedの訳に困る). MonomorphはDynamicになることはない。このため次のような例にみられるような意外な挙動となる。

class Main {
  static function main() {
    var jsonData = '[1, 2, 3]';
    var json = haxe.Json.parse(jsonData);
    $type(json); // Unknown<0>
    for (i in 0...json.length) {
      // Array access is not allowed on
      // {+ length : Int }
      trace(json[0]);
    }
  }
}

Json.parseの返り値の型はDynamicであるが、ローカル変数jsonDynamicにならず、monomorphのままである。そして、json.lengthとフィールドアクセスしたときに、anonymous structure型推論される。この結果、次のjson[0]という配列へのアクセスはエラーとなる。これを避けるためには、変数jsonを陽にDynamicとして宣言、つまりvar json:Dynamicとすればよい。

Trivia: 標準ライブラリにおけるDynamic

DynamicはHaxe3以前では標準ライブラリで頻繁に使われていた。Haxeの型システムを改良し続けた結果、Dynamicの使用箇所はHaxe3のリリースまでに少なくなった。

訳注: 雑な訳だなあ

Latex / URLのフォントを変える。

\url{}で書いた文字のフォントスタイルを変更する。

hyperrefパッケージを使うと

\url{www.example.com}

とするだけでPDFにリンクを挿入できる。しかしデフォルトではURLの部分だけフォントが違っていて違和感がある。

\renewcommand\UrlFont{\rmfamily}

のようにするとフォントを変えられる。

Haxe入門 / 型

目次に戻る

2. Types

Haxeコンパイル時に型関連のエラーを検出できる素晴らしい型システムを持っている。 Stringによる分割(Stringを引数にとる文字列分割?)や、Intergerのフィールドへのアクセス、あるいは引数の数が足りない(もしくは多い)関数呼び出しといったような、型の不一致は不正な操作である。

他の言語では、この型システムの恩恵を得るために冗長な書き方になることがある。変数の型宣言とコンストラクタ呼び出しの両方で型名を明示的に書かなければならなかったりする。

var myButton:MySpecialButton = new MySpecialButton(); // As3

(Haxe manualではC++も載ってたがC++にはすでにautoによる型推論があるので外した)

Haxeでは型宣言で明示的に型名を書く必要はない。コンパイラは型を推論できる。

var myButton = new MySpecialButton(); // Haxe

詳しくは型推論の項で触れる。上の例でmyButtonMySpecialButtonクラスのインスタンスと推論されているとわかれば今は十分。

Haxeには次の7グループの型がある。

  • クラスインスタンス
  • 列挙インスタンス
  • 構造体
  • 関数
  • 動的型: 他のどの型にも適合するようなやつ
  • 抽象型: コンパイル時での型、実行時には別の型になってる。
  • Monomorph(訳語が思いつかない): 未定型(でしょうか?)。途中で別の型になるかもしれないとか。

目次に戻る

Haxe入門 / 目次

記事が増えてきたので早々に目次を作る

Haxe Manual

Introduction - Haxe - The Cross-platform Toolkit

方針

haxe.orgのManualに沿って説明していきます。書いてる人が読んですぐ記事にしてるので間違ってることは十分ありえます。オリジナルへのリンクも張っておくので自分で確認することを強く勧めます。訳すのが目的ではないので、わかりにくいと判断した場合は改変を加えます。オリジナルのドキュメントのライセンスが何なのかよくわからないのですが、ライセンスはhaxe.orgのドキュメントに準じることにします(少なくともHaxeと同じくオープンソースであると考えてます)。飽きたら更新やめます。

目次

  1. Introduction
  2. Types
    1. 基本型 Basic Types
    2. Nullability Nullability
    3. クラスインスタンス Class Instance
    4. 列挙型 Enum Instance
    5. 無名構造体 Anonymous Structure
    6. 関数型 Function Type
    7. Dynamic
    8. Abstract
    9. Monomorph
  3. Type System
  4. Class Fields
  5. Expressions
  6. Language Features
  7. Compiler Reference
  8. Compiler Features
  9. Macros
  10. Standard Library
  11. Haxelib
  12. Target Details

その他Haxe入門記事

完成は遠い...