pyconjp 2017に参加して来ました

概要

9月7,8,9,10で開催されたpyconjp 2017に参加してきました。
カンファレンスは8,9でしたが、7にチュートリアル、10に開発スプリントが開催されています。
また、今年はCfPをだしたが採択されなかったトークを喋るRejectConも開催されたようです。
今年のテーマは「OUTPUT & FOLLOW」
公式サイト : https://pycon.jp/2017/ja/

セッション感想

セッションのスライドはだいたい公開されており、toggterにもまとまっていたので詳しくはそちら
セッションのメモは以下

野球を科学する技術〜Pythonを用いた統計ライブラリ作成と分析基盤構築

https://speakerdeck.com/shinyorke/ye-qiu-woke-xue-suruji-shu-pythontotong-ji-raiburaritofen-xi-ji-pan-number-pyconjp

  • 野球ユニフォームで登壇が正装
  • 分析基盤を構築した話をする
    • 気軽に作って壊せる
    • 使いたい・試したいライブラリを積極活用
    • OSSにする
  • DBはMySQL
  • データはスクレイピング(Scrapy)、時系列データとして使いたいのでAirflow
  • 実験はjupyter
  • scrapyはクローラー界のRoRと読んでいいぐらい高機能
  • airflow
    • ジョブ管理
    • 結構高機能
    • 意外と苦労した
  • 分析
    • 定期的に見るか、分析に使うかで使い分ける
    • 定期的はRedash
    • 実験とかはjupyter

Pythonで大量データ処理!PySparkを用いたデータ分析のきほん

https://speakerdeck.com/chie8842/pythondeda-liang-detachu-li-pysparkwoyong-itadetachu-li-tofen-xi-falsekihon

Kivyによるアプリケーション開発のすすめ

https://www.slideshare.net/JunOkazaki1/pyconjp2017-kivy

  • python3.5
  • mac,Linuxでも動くはず
  • MITライセンス、Qtとは違う!
  • UIはkvという独自言語
    • kvはCSSのBootstrapのようなもの
    • kvを使用するのが普通、その方がコードが簡潔
  • kivyを今使うのは結構たいへんそう
  • デモは良さげ

len()関数がオブジェクトの長さを手にいれる仕組み

https://www.slideshare.net/shimizukawa/how-does-python-get-the-length-with-the-len-function

  • len()が戻り値の型をintで保証
  • Adapter Patternで実装されている
  • スライドがすごく分かりやすかった
  • 公式ドキュメントの「デザインと歴史」を読めばいろいろわかりそう https://docs.python.org/ja/3/faq/design.html

Pythonistaで始めるiOSプロトタイプ開発

Python機械学習によるWebセキュリティの自動化

https://www.mbsd.jp/insight.html https://t.co/thfG8n2080

  • Webアプリケーション診断を自動化
  • 従来
    • アプリをクローリングして疑似攻撃
    • 判定
  • 少ない手数で脆弱性を検出する(いろいろするわけではない)
  • LSTM
  • 高度すぎてついていけなかった

2日目keynote

https://speakerdeck.com/sinhrks/pandasdefalseosshuo-dong-shi-li-tozui-chu-false-bu

  • pythonと科学計算
    • プログラマー以外でもpythonを使ってプログラムをする人が増えてる
    • SciPy2017に行ってきた話 9日間開催
      • クレータの解析をpythonでした話
  • pandasのOSS活動
    • pandas : データ分液のためのデータ構造を提供するパッケージ
      • 現実の汚いデータ(フォーマットがバラバラ)を効率的に扱えるのが便利
      • データの理解、データ準備に使用される
  • OSS活動 最初の一歩
    • コミッタの役割の話は興味深い
      • インフラの整備とかもやってる
      • プロダクトとコミュニティの品質の維持をやるのが大事
      • プロダクト品質の維持

Pythonで実現する4コマ漫画の分析・評論 2017

https://slideship.com/users/@esuji/presentations/2017/08/FSKS46VL9ivVSpUE4Gaamh/

  • 情熱駆動開発!!
  • OCR三国志の人と同じGoogle OCR
  • 誰が何処に出ているか等も分析したい
    • dlibの物体検出器で人物判定
    • 横向き、後ろ向き、顔の重なりがあるのでそれを調査
      • 期待した精度はでなかった
    • 検出人物の分類
      • CNNを利用
      • だめだった

The theory of Serverless development by Python (理論から学ぶPythonによるサーバレス開発)

https://slideship.com/users/@marcy-terui/presentations/2017/09/9PzXZzcJfBR1ENEMmMbGSf/ https://www.slideshare.net/acloudguru/ant-stanley-being-serverless

  • Serverlessとは
    • 管理すべきサーバがない
    • サーバOSがない
    • 常駐サーバプロセスがない
  • Function as a Service
    • 関数単位で独立した環境とリソースを提供
    • 関数単位で横にスケール
    • 高い抽象度
  • Function SaaS
    • 単独ではサービスとしては簡潔しない
      • Fully featured Saasはその逆で単独で簡潔するもの
      • APIエンドポイント,データストア,認証、検索
    • プラットフォームの一部だったり
  • Serverlessがどうして登場したのか
  • どのように実装するか
    • 実態はDockerが多い
      • 特定のイベントによってコンテナが起動されて関数が実行される
      • VMよりも起動のオーバーヘッドは小さいが、オーバーヘッド自体はある
      • オーバーヘッドがあるので、一度起動したコンテナを再利用することもある
    • イベント駆動
      • 何かがトリガーとなって起動する(タイマー、クラウドリソースの変化、画面操作etc)
      • 1イベントにつきふうくすうのFunctionを実行可能
    • pull型のPub/Subモデル
  • Serverlessに向いているもの
    • IoT
      • IN/OUTが明確で各ステップでスケール調整できるのがGood
    • ユーザ行動データ解析
    • 特定のイベントに連動していろんなSaaSが動くやつ
    • 普通のWeb APIアプリケーションには向いていない
      • RequestとResponseが一対一で同期的だから
  • DBAとのコネクションコストを考える

Clearer Code at Scale: Static Types at Zulip and Dropbox

英語セッションだったので聞くのに必死でメモはなし
英語スライドに機械翻訳ぽい日本語があった
- mypyの話 https://github.com/zulip/zulip/blob/master/docs/mypy.md http://qiita.com/t2y/items/2a1310608da7b5c4860b

Pythonをとりまく並行/非同期の話

https://tell-k.github.io/pyconjp2017/#1

  • python3.6リリースパーティーで聞いた話と大体同じ
  • asyncio のイベントループポリシーを差し替えることができるのは知らなかった

SREエンジニアがJupyter+BigQueryでデータ分析基盤をDev&Opsする話

https://speakerdeck.com/yuzutas0/20170909

カンファレンス感想

  • 初日は新大久保から歩いてみたら結構遠くて辛かったので、今後ここが会場になることがあれば素直に西早稲田駅からいくのがおすすめ
  • 無限コーヒーと無限オレンジジュースは嬉しい
  • 毎年pyconjpのおやつは美味しくて密かに楽しみにしてたが、今年も美味しかった
  • ゴミ箱のインデントは健在
  • ポスターセッションは楽しい、他のカンファレンスでも取り入れて欲しい
  • 1日目のkeynoteで同時翻訳レシーバーを手に入れそこねたがゆっくり喋ってくれていたのでなんとか聞き取れた(メモは取れてない)
  • ブースで話していたらいつの間にセッションが始まっていたので、アナウンスがあると嬉しい

Neovimでgolangを書く設定 備忘録

概要

Macgolangをインストールし、Neovimで書く環境を整えます。

インストール

まずはgolangをインストールします。

$ brew install go
$ nvim .zshrc #下記を追加
if [[ -d /usr/local/opt/go ]];then
    export GOPATH=$HOME/work.go
    export PATH=$PATH:$GOPATH/bin:/usr/local/opt/go/libexec/bin
fi

設定

設定するものは下記です。

GOPATH

golangで使用するディレクトリをGOPATHに指定する必要があるので、設定します。
GOPATH : https://github.com/golang/go/wiki/GOPATH

.zshrcに下記を追加します。
今回は~/devをGOPATHに指定しています。

#go
if [[ -d /usr/local/opt/go ]];then
    export GOPATH=$HOME/dev
    export PATH=$PATH:$GOPATH/bin:/usr/local/opt/go/libexec/bin
fi

GOPATHを指定すると、今後はgo getでインストールするgolangのライブラリがこの下にインストールされるようになります。

補完

deoplete.nvimを使っているので、deoplete-goをセットアップすればいいです。
設定も公式サイトのものをとりあえずそのまま使用しています。
deoplete-go : https://github.com/zchee/deoplete-go

依存しているものをインストールします。

$pip2 install --upgrade neovim
$pip3 install --upgrade neovim
$go get -u github.com/nsf/gocode #GOPATHで指定したディレクトリの下にインストールされる

dein_lazy.tomlに下記を追加します。

[[plugins]]
repo = 'zchee/deoplete-go'
on_ft = 'go'

vim-go

ちょっと前だとvim-goはneovimに対応してなかったようですが、今は使えるようになっているみたいなのでvim-goを入れます。
dein_lazy.tomlに下記を追加します。

[[plugins]]
repo = 'fatih/vim-go'
on_ft = 'go'

インストールしたら下記をneovimで実行すると、vim-goで使うライブラリがGOPATHの下にインストールされます。

:GoInstallBinaries

vim-go自体にチュートリアルがあるのでそれをやれば一通りの使い方はわかりそう
vim-go-tutorial : https://github.com/fatih/vim-go-tutorial

シンタックスチェック

neovimではSyntasticの代わりにneomakeでシンタックスチェックをするので、neomakeをインストールします。
dein.tomlに下記を追加します。

[[plugins]]
repo = 'neomake/neomake'

a tour of go をやりながら書いていたメモのまとめ

エントリーポイント

  • エントリポイントはmainパッケージのmain関数
package main

func main() {
    // write your some code
}

関数

  • 複数の値を返せる
  • 戻り値に名前をつけることができる
// func 関数名 (引数,...) 戻り値の型 { }
func add1(x int, y int) int {
    //引数がx,yでともにint型
    //戻り値の型はint
    return x + y
}

func add2(x, y int) int {
    //add1と同じだが、引き数の型をまとめて宣言
    return x + y
}

func swap(x, y string)(string, string) {
    //引数がx,yで共にstring型
    //戻り値が2つあり、共にstring型
    return y, x
}

//naked returnと呼ばれる方法で関数が短い場合にのみ使うべき
func split(sum int)(x, y int)  {
    //戻り値の指定部でx,yの変数を宣言している
    x = sum * 4 / 9    
    y = sum - x
    //関数の宣言で指定した値を自動的に返す
    return 
}

defer

  • 呼び出し元が終わるタイミングで実行される
  • 複数のdeferを書いた場合は後に書いてあるものが先に実行される(LIFO)
  • 引数の評価は実行時ではなく、deferが書いてある場所で行われる
  • 絶対開放しないと行けないリソースなどの処理に便利(ファイルのクローズ、ミューテックス(排他制御)のアンロック)
import (
    "fmt"
)

//これを実行すると3,2,1の順番で表示される
func main(){
    i := 1
    defer fmt.Println(i)
    i = 2
    defer fmt.Println(i)
    i = 3
    defer fmt.Println(i)
}

定数

  • constで定義
  • 定数は変数に代入する時や、式の中で型がきまる(宣言時は型が決まっていない)
const u = 1
const p = 2.0

変数宣言

  • varで宣言
  • 変数のスコープはfor,if,func,globalがある
  • 関数の中での宣言には := も使える、varを省略し、宣言と同時に初期化をする
var c,python,java bool //3つともbool型
var i, j int = 1,2  //2つともint型でi=1,j=2で初期化
var c,python,java = true,false,"no" //初期化時に型が決まるので、明示的に型を書かないでも大丈夫
func main() {
    k := 3 //関数の中なのでvarを省略する方法が使える
}

基本型

初期値 備考
bool false 論理値
string “” 文字列
int, int8, int16, int32, int64 0 整数、特別な用途以外ではintを使用
uint, uint8, uint16, uint32, uint64, uintptr 0 符号なし整数、unitptrはポインタの値を表現するようの整数型
byte 0 バイト単位でデータを扱う、alias for uint8
rune 文字単位のデータを扱う、alias for int32
float32, float64 0
complex64 , complex128 複素数

型変換

  • 暗黙の型変換はない
  • 変換後の型をTとした時、T(v)でvをT型に変換する
func main() {
    var x int = 3, 4
    var z uint = uint(x)
    var f float64 = float64(x)
}

ポインタ

  • *変数名で宣言した場合はポインタ
  • ポインタの初期値はnil
  • &オペレータはポインタを返す)
  • *オペレータはポインタが指す先を返す(dereferencingまたはindirecting)
import(
    "fmt"
)

func main(){
    var *p int //int型ポインタ
    i := 1
    q := &i //qもint型ポインタになる
    fmt.Println(*q) //1が表示される
}

構造体

type 構造体名 struct {
    変数1
    変数2
    変数n
}

var v 構造体名{初期値}
v.変数1 = 10 
  • goにはクラスはない
  • 構造体はフィールドの集まり
  • 構造体のフィールド名は大文字で始めるのが多い
import(
    "fmt"
)

type Vertex struct {
    X int
    Y int
}

func main() {
    v1 := Vertex{1, 2}
    v2 := Vertex{x: 1} //yは初期値になるので0
    v3 := Vertex{} //x,y共に初期値は0
    p := &Vertex{1, 2} //構造体のポインタもある
    q := &v1 //構造体のポインタになる
    q.x = 1e9 //本来なら (*q).vで参照するが、syntax sugerがある
    fmt.Println(q)

}

array

//宣言
var 変数名 [要素数]型
var 変数名 [要素数]型{初期値,...}
//代入、参照
変数名[要素] = 値
fmt.Print(変数名[要素])
  • 配列の長さは変更不可
import (
    "fmt"
)

func main() {
    var a [2]string
    a[0] = "Hello"
    fmt.Println(a[0])
    fmt.Println(a)
    primes := [6]int{2, 3, 5, 7, 11, 13}
}

slice

var 変数名 []型 
  • 可変長
  • リストのようなもの
  • sliceは配列への参照をもっているようなもの
  • sliceは参照渡し
  • sliceには下記がある
    • 長さ(length) : 含まれる要素の数
    • 容量(capacity) : sliceのサイズ
  • ゼロ値はnil、長さと容量は0となる
  • 組み込み関数makeを使用して作成できる
  • sliceの入れ子もできる
  • sliceへの要素の追加はappend、追加時にsliceの容量が足りない場合は自動的に良い大きいサイズのsliceが作られ、それを返す
  • forループ時はrangeを利用
import  (
    "fmt"
)

func main(){
    primes := [6]int{2, 3, 5, 7, 11, 13}

    var s1 [] int = primes[1:4] //sはint側のスライスで3,5,7が入ってる
    var s2 []bool{true, true, false} //最初からスライスを作ることもできる
    len(s1) //要素数は3
    cap(s1) //サイズも3

    //下記はすべて同じ意味になる、下限は0、上限は配列のサイズがデフォルト値になるため 
    var s3 []int = primes[0:6]
    var s4 []int = primes[:6]
    var s5 []int = primes[0:]
    var s6 []int = primes[:]

    //nil slice
    var s7[]int //s7 == nil がtrueになる

    a := make([]int, 5) //sliceのcapが5でlenも5、各要素は0で初期化されている
    b := make([]int, 0, 5) //sliceのcapが5でlenは0のsliceを返す
    //要素の追加
    c := append(a, 1,2,3,4,5,6) //aの容量は5ですでにlenも5なので大きいサイズのsliceが作られる
    //戻り値は新しいsliceで元のslice自体は変化していないので注意
    //上記の場合はcは大きいサイズのsliceでaはappend前と変化なし

    //入れ子のslice
    board := [][]string{ 
        []string{"_", "_", "_"},
        []string{"_", "_", "_"},
        []string{"_", "_", "_"},
    }
    fmt.Println(board[0][0])

    //forループ
    for i, v := range s2 {
        // i は index, v はvalue, pythonのenumerate関数と同じような動き
        fmt.Println(i)
        fmt.Println(v)
    }

    for i := range s2 {
        //indexだけ使う場合
        fmt.Println(i)
    }

    for _, v := range s2 {
        //valueだけ使う場合
        fmt.Println(i)
    }

}

map

var 変数名 map[キーの型]値の型 
  • キーと値を関連づける
  • mapのゼロ値はnil,nilはキーを持っておらず、キーを追加することもできない
  • make関数を使用して初期化する
  • 新しいキーは代入するだけで作れる
  • 値を指定して初期化もできる
  • キーの削除はdelete関数
  • キーの存在確認は参照時の戻り値で判定する
import (
    "fmt"
)

//緯度経度を持つ構造体
type Vertex struct {
    Lat, Lon float64 
}

func main() {
    var m map[string]int //キーがstring,値がint,この時は型が決まっているが値はnil
    m = make(map[string]int) //map型のインスタンスを作ったような状態
    //m := make(map[string]int) //上の2行をまとめてこれでもOK
    m["age"] = 26 //代入
    fmt.Println(m["age"]) //参照

    //宣言と初期化と同時に
    var n map[string]Vertex {
        "Bell Labs" : Vertex{
            40.68433, -74.39967,
        },
        "Google" : Vertex{
            37.42202, -122.08408,
        },
    }

    //値の型が単純な型名の場合は値の型から推測できるので、省略可能
    var o map[string]Vertex {
        "Bell Labs" : { 40.68433, -74.39967, },
        "Google" : { 37.42202, -122.08408, },
    }

    //要素の削除
    delete(n, "Bell Labs") //Bell Labsを削除

    //キーの存在確認
    elem, ok := n["Bell Labs"] //Bell Labsは削除済みなのでokはfalse, elemは要素の型のゼロ値なので今回はnil
    elem, ok = n["Google"] //Googleはまだあるのでokはtrue,elemは要素の値を返す


}

関数型(function values)

  • 関数も変数として扱える
  • 他の関数に関数を渡すことができる
  • 関数の戻り値として関数を返すこともできる
import (
    "fmt"
    "math"
)

//compute関数は引数としてfloat64型の値を2つとり,float64型を返す関数をとり、float64型を返す
func compute(fn func(float64, float64) float64) float64 {
    //引数として受け取ったfloat64型の値を2つとり,float64型を返す関数に引数3と4を指定して呼び出す
    return fn(3, 4)
}

func main() {
    //hypotは関数型
    hypot := func(x, y float64) float64 {
        return math.Sqrt(x*x + y*y)
    }
    //hypotに格納されている関数を呼び出す
    fmt.Println(hypot(5, 12))

    //compute関数にhypot関数を引数として渡す
    fmt.Println(compute(hypot))
    //compute関数にmath.Pow関数を引数として渡す
    fmt.Println(compute(math.Pow))
    }

closure

  • 関数の外の値を関数に対して紐付ける(bind)する仕組み
  • closure関数を返す関数を作成し、closure関数を返す前にclosure関数に紐付ける変数を宣言する
import "fmt"

//adderはint型と引数としてとり、int型を返す関数を返す
func adder() func(int) int {
    sum := 0 //adderで返す下記の関数からはsumを参照でき、adderを呼び出して新しい関数を返すたびにそれぞれの関数に別々のsumが紐づく
    return func(x int) int { //closure関数 
        sum += x
        return sum
    }
}

func main() {
    //posとnegにはそれぞれ別のsumが紐づく
    pos, neg := adder(), adder()
    for i := 0; i < 10; i++ {
        fmt.Println(
            pos(i),
            neg(-2*i),
        )
    }
    }

if

if 条件式 {
} else if 条件式 {
} else {
}

if 式; 条件式 {
}
  • ()はいらない
  • 条件の前に簡単な式を書くことができる
import (
    "math"
)

func main() {
    x := 1
    if x < 0 {

    } else if x >= 5 {

    } else {

    }

    n := 2
    lim := 10
    if v := math.Pox(x, n); v < lim {
        //v := math.Pox(x, n);を実行したあとにv < limが評価される
        //vのスコープはこのifの中だけ
    } else {
        //vはelseでも使える
    }

ref : https://gobyexample.com/if-else

switch

  • breakがなくても次のcaseは実行されない
  • 他言語でbreakを書かなかった場合と同じ動作をさせたい場合はfallthroughを書く
  • case式に関数を指定できる
  • switchに式を書かない場合は、case式を評価し、trueになったcaseを実行する
func main() {
    i := 10
    switch i {
        case 0:
        case 1:
            fallthrough 
        case 2:
        case f():
            //f()を呼び出した結果の戻り値をiを評価する、f()の前のcaseで実行する箇所が決まった場合はf()も呼ばれない
        default :
            //今回はこれが実行される
    }

    now := 1
    switch { //一番最初にcase式がtrueになったcaseが実行される
        case now < 12:
            //今回はこれが実行される
        case now < 18:

        default:
    }
}

for

for 初期化部; 条件式; 増分 {
}

for 条件式 { //whileの代わり
}

for { //無限ループ
}
  • ()はいらない
  • 条件の前に簡単な式を書くことができる
  • whileはないので、whileの動作を実現したい時はforで初期化部と増分を書かない
  • break,continueはある
  • goにはpythonのrange的なのものはない
import (
    "fmt"
)

func main(){
    for i := 0; i < 10; i++ {
        //iのスコープはforの中だけ
    }

    sum := 1
    for sum < 100 { //whileの代わり
        sum += sum
    }

    x := 0
    for { //無限ループ
        if x >= 3 {
            break
        }
        x++
    }

    for i := 0; i < 10 ; i++ { 
        if i % 2 == 0 { 
            continue
        }
        fmt.Println("奇数:", i) 
    }

メソッド

//func レシーバ- 関数名 戻り値の型 
func (i Vertex) Abs() float64{}
  • golangにはクラスはないが、型にメソッドを定義できる
  • 特定の型にメソッドを追加する場合はレシーバーを使う
  • レシーバーは同じパッケージにある型にだけ追加できる
  • 組み込み型にレシーバを追加したい場合はtypeで型に別名をつける
  • ポインタに対してもレシーバを追加できる
  • ポインタに対してレシーバを追加した場合は参照渡し、それ以外は値渡しになる
  • ポインタレシーバ(ポインタに対してレシーバを追加したもの)と変数レシーバ(ポインタ以外にレシーバを追加したもの)を混在させるべきではない
  • ポインタレシーバの場合はメソッド呼び出し毎に変数のコピーを作らないので、こちらを使うのがおすすめ
  • 関数の場合は引数で渡すの値がポインタかそうでないかを意識しないと行けないが、レシーバの場合はgoが良しなに変換してくれる
import (
    "fmt"
    "math"
)

type Vertex struct {
    X, Y float64
}

//型VertexにAbs()を紐付ける
func (v Vertex) Abs() float64 {   
    //vの値を参照できる
    return math.Sqrt(v.X * x.X + v.Y * v.Y)
}

//ポインタレシーバ
func (v *Vertex) Scale(f float64) {
    v.X = v.X * f 
    v.Y = v.Y * f
}

type MyFloat float64 

//float64にMyFloatという別名をつけ、MyFloatに対してレシーバーをつける
func (f MyFloat) Abs() float64 {
    if f < 0 { 
        return float64(-f)
    }
    return float64(f)
}


func main(){
    v := Vertex{3, 4}
    //Vertex型のvはAbs関数を呼び出せる
    fmt.Println(v.Abs())
    v.Scale(5)
    fmt.Println(v)
    f := MyFloat(-math.Sqrt2)
    fmt.Println(f.Abs())
}

インターフェイス

type 型名 interface {
    //実装すべき関数
    //実装すべき関数
    //実装すべき関数
}
import (
    "fmt"
)

type Abser interface{ Abs() float64 }

type MyFloat float64

//Absを実装したのでMyFloatはAbser型にもなる
func (f MyFloat) Abs() float64 {
    if f < 0 {
        return float64(-f)
    }
    return float64(f)
}

type Vertex struct { X, Y float64 }

//Absを実装したのでVertexはAbser型にもなる
func (v *Vertex) Abs() float64 {
    return math.Sqrt(v.X * v.X + v.Y * v.Y)
}

type I interface {
    M()
}

type T struct {
    S string
}
func (t *T) M() {
    //tがnilの場合でも適切に処理をする
    if t == nil {
        fmt.Println("<nil>")
        return
    }
    fmt.Println(t.S)
}

func main() {
    var a Abser
    f := MyFloat(-math.Sqrt2)
    v := Vertex{3, 4}

    a = f  // a MyFloat implements Abser
    fmt.Println(a.Abs()) //MyFloatのAbs()が呼ばれる
    a = &v // a *Vertex implements Abser
    fmt.Println(a.Abs()) //VertexのAbs()が呼ばれる

    var i I

    var t *T
    //この時のTはまだnil
    i = t
    i.M()

    i = &T{"hello"}
    i.M()
}

nil インターフェイス

import "fmt"

type I interface {
    M()
}

func main() {
    var i I
    //ここのiの型はIインターフェイスだが、具体的な型(実装を持っている)が代入されていないので、ランタイムエラーになる
    i.M()
}

emptyインターフェイス

  • ゼロ個のメソッドを定義したインターフェイス
  • 任意の型を代入できる
  • 未知の型を扱うコードで使用する(fmt.Println()が代表例)
package main

import "fmt"

func main() {
    //iはemptyインターフェイス型なので任意の型を代入可能
    var i interface{}
    describe(i)

    i = 42
    describe(i)

    i = "hello"
    describe(i)
}

func describe(i interface{}) {
    fmt.Printf("(%v, %T)\n", i, i)
}

type assertions

import "fmt"

func main() {
    var i interface{} = "hello"

    //この時iがstring型じゃなければここでpanicが引き起こされる
    s := i.(string)
    fmt.Println(s)

    //sにはiの値が入る,okにはtrue
    s, ok := i.(string)
    fmt.Println(s, ok)

    //fはfloat64のゼロ値になりokはfalse
    f, ok := i.(float64)
    fmt.Println(f, ok)

    f = i.(float64) // panic
    fmt.Println(f)
}

type switch

  • type assertionsを直列に使用する方法
import "fmt"

func do(i interface{}) {
    //iの型で分岐するswitch文
    switch v := i.(type) {
    case int:
        fmt.Printf("Twice %v is %v\n", v, v*2)
    case string:
        fmt.Printf("%q is %v bytes long\n", v, len(v))
    default: //一致する型がcaseにない場合はdefaultが呼ばれる
        fmt.Printf("I don't know about type %T!\n", v)
    }
}

func main() {
    do(21)
    do("hello")
    do(true)
}

よく使われるインターフェイス

  • Stringer : stringとして表現できる型
type Stringer interface {
    String() string
}
import "fmt"

type Person struct {
    Name string
    Age  int
}

//PersonはこれでStingerインターフェイスを実装した
func (p Person) String() string {
    return fmt.Sprintf("%v (%v years)", p.Name, p.Age)
}

func main() {
    a := Person{"Arthur Dent", 42}
    z := Person{"Zaphod Beeblebrox", 9001}
    fmt.Println(a, z) //ここでPersonのString()が呼ばれる
}
  • Errors : エラーの状態を表現する
    • goでは関数がよくerror型の値を返す、この値がnilの場合は処理が成功したことを示す
type error interface {
    Error() string
}
import (
    "fmt"
    "time"
)

type MyError struct {
    When time.Time
    What string
}

//errorインターフェイスを実装
func (e *MyError) Error() string {
    return fmt.Sprintf("at %v, %s", e.When, e.What)
}

//errorインターフェイスを返す
func run() error {
    return &MyError{
        time.Now(),
        "it didn't work",
    }
}

func main() {
    if err := run(); err != nil {
        fmt.Println(err)
    }
}
  • Readers : データストリームを読む
//byte型を引数にとり、int型とerrorインターフェイス型を返す
//bにデータをいれ、入れた数をnとして返す
func (T) Read(b []byte) (n int, err error)
import (
    "fmt"
    "io"
    "strings"
)

func main() {
    r := strings.NewReader("Hello, Reader!")

    b := make([]byte, 8)
    for {
        //rの値をbに入れる
        //入った値がnに、失敗した場合はerrがnil以外になる
        n, err := r.Read(b)
        fmt.Printf("n = %v err = %v b = %v\n", n, err, b)
        fmt.Printf("b[:n] = %q\n", b[:n])
        if err == io.EOF {
            break
        }
    }
}
  • Images : 画像を表現する
package image

type Image interface {
    ColorModel() color.Model
    Bounds() Rectangle
    At(x, y int) color.Color
}
import (
    "fmt"
    "image"
)

func main() {
    //imageインターフェイスが実装されているクラスを使ってみる
    m := image.NewRGBA(image.Rect(0, 0, 100, 100))
    fmt.Println(m.Bounds())
    fmt.Println(m.At(0, 0).RGBA())
}

goroutine

go 関数名()
変数名 := make(chan 型) //指定した型のchannelを作成
channel変数 <- 値 //値をchannel変数に書き込み
変数 := <- channele変数  // channel変数の値を読み込む
  • メモリ空間は共有
  • 通常の関数をgo 関数名で呼び出せばgoroutineとして呼び出せる
  • goroutine間でデータを渡す時はchannelsを使用
  • channelの読み書きの時にchannelのバッファに対して処理ができない場合は、他のgoroutineの処理を待つ
  • channelにはバッファサイズを指定できる
  • channelにこれ以上値を送信することがない時はchannelをcloseする
  • channelに対してrange でループをしている時はchannelがcloseされるまでループする
  • channelはgoroutine以外からもいじれる
  • 使用できるchannelで分岐したい時はselectを使用する
  • ブロックしないでchannelを使用したい時はdefault付きのselectを使用する
import (
    "fmt"
    "time"
)

func say(s string) {
    for i := 0; i < 5; i++ {
        time.Sleep(100 * time.Millisecond)
        fmt.Println(s)
    }
}

func sum(s []int, c chan int) {
    sum := 0
    for _, v := range s {
        sum += v
    }
    c <- sum // send sum to c
}

func fibonacci(n int, c chan int) {
    x, y := 0, 1
    for i := 0; i < n; i++ {
        c <- x //書き込みの毎に読み込みがあるまでここでロックされる
        x, y = y, x+y
    }
    close(c) //cに対してもう書き込まないのでそれを明示する
}

func fibonacci2(c, quit chan int) {
    x, y := 0, 1
    for {
        select { //cに書き込めるかquitが読み込めるようになるまでここでロック
        case c <- x:
            x, y = y, x+y
        case <-quit:
            fmt.Println("quit")
            return
        }
    }
}

func main() {
    go say("world") //sayをgoroutineとして起動
    say("hello")

    s := []int{7, 2, 8, -9, 4, 0}

    c := make(chan int) //chanel作成
    go sum(s[:len(s)/2], c)
    go sum(s[len(s)/2:], c)
    x, y := <-c, <-c // cに値が入るまでここでロックされる

    fmt.Println(x, y, x+y)

    ch := make(chan int, 2) //channelのバッファサイズを2で宣言
    ch <- 1
    ch <- 2 //バッファサイズが2なので、連続して書き込める
    fmt.Println(<-ch)
    fmt.Println(<-ch)

    cf := make(chan int, 10)
    go fibonacci(cap(cf), cf)
    for i := range cf { //cfがcloseされるまでは読み込みを繰り返す
        fmt.Println(i)
    }

    cf2 := make(chan int)
    quit := make(chan int)
    go func() {
        for i := 0; i < 10; i++ {
            fmt.Println(<-cf2)
        }
        quit <- 0
    }() //宣言と同時に呼び出し
    fibonacci2(c, quit)

    tick := time.Tick(100 * time.Millisecond)
    boom := time.After(500 * time.Millisecond)
    for {
        select {
        case <-tick:
            fmt.Println("tick.")
        case <-boom:
            fmt.Println("BOOM!")
            return
        default: //tickとboomの両方が読み込めない場合はdefaultを実行
            fmt.Println("    .")
            time.Sleep(50 * time.Millisecond)
        }
    }
}

mutex

import (
    "sync"
)

変数名 sync.Mutex 
変数名.Lock()
//LockとUnLockの間が排他制御になる
変数名.Unlock()
  • goroutine間でコミュニケーションを取る必要がないが、データのロックが必要な時に使用
import (
    "fmt"
    "sync"
    "time"
)

// SafeCounter is safe to use concurrently.
type SafeCounter struct {
    v   map[string]int
    mux sync.Mutex
}

//SafeCounter型にメソッドをつける
func (c *SafeCounter) Inc(key string) {
    c.mux.Lock()
    //LockとUnlockで挟んでいるここが排他制御
    c.v[key]++
    c.mux.Unlock()
}

// Value returns the current value of the counter for the given key.
func (c *SafeCounter) Value(key string) int {
    c.mux.Lock()
    defer c.mux.Unlock() //deferでUnlockを実行することもできる
    return c.v[key]
}

func main() {
    c := SafeCounter{v: make(map[string]int)}
    for i := 0; i < 1000; i++ {
        go c.Inc("somekey")
    }

    time.Sleep(1 * time.Millisecond)
    fmt.Println(c.Value("somekey"))
}

Pythonのパッケージ周りについて調べた時のメモ

用語

パッケージングツール

  • destribute : python標準のパッケージ管理用モジュール、destributeよりも多機能なsetuptoolsが基本的には使われる
  • setuptools : 2017年8月2日現在、すくなくともpython2系のパッケージング時のデファクトスタンダード
  • distutils : setuptoolsよりも機能が少ないので、setuptoolsを使っていればよい

インストールツール

  • easy_install : setuptoolsに付属している、PyPIからパッケージをダウンロードしてインストールできるコマンド
  • ez_setup.py : setuptoolsをインストールする際に利用されるスクリプト
  • pip : easy_installよりも高機能なインストーラー、easy_installではパッケージのアンインストール等ができない

配布形式

  • egg : setuptoolsで定義されたpython Packageの配布形式、中身はpythonのコードやメタ情報を所定のフォーマットでzip圧縮したもの
  • wheels : eggの後続のフォーマット

配布物の作成

  • bdist : setup.pyを使ってビルド済み配布物を作成するコマンド、bdist_rpmやbdist_wininst等を作成できる
  • sdist : setup.pyを使ってソースコード配布物を作成するコマンド

その他

  • setup.py : パッケージに必要な情報を記述する
  • init.py : pythonがあるディレクトリの目印
  • PyPI : the Python Package Index、Pythonのパッケージが登録されている場所

テンプレート

from setuptools import setup, find_packages
setup(
    name = "HelloWorld",
    version = "0.0.1",
    packages = find_packages(),
    #find_packages()はsetup.pyがあるディレクトリから__init__.pyがあるディレクトリを探す
    author = "repli",
    author_email = "repli@example.com",
    description = "This is an Example Package",
    license = "MIT", 
    keywords = "package example examples", # 検索用のワード
    url = "",   # もしあれば、プロジェクトのホームページ
    install_requires = ['docutils>=0.3'],
    #python以外に含めるデータ
    package_data = {
        '': ['*.txt', '*.rst'],
    }
)

ref

builderscon 2017に参加して来ました

概要

8月3,4,5で開催されたbuildersconに参加してきました。
buildersconとは
公式サイト(https://builderscon.io)より引用

buildersconは「知らなかった、を聞く」をテーマとした技術を愛する全てのギーク達のお祭りです。

セッション感想

1日目は完全オフレコなので、内容については何もかかないですが、ああいう話を聞ける機会はめったにないので、次同じようなものがあったらぜひまた聞きたいと思うぐらいには最高だった。

オンプレ、クラウドを組み合わせて作るビックデータ基盤 -データ基盤の選び方-

  • 普段はオンプレの環境しか触っていないのでクラウド側の知識は新鮮で面白かった
  • MetaデータのDBはすごく便利そう、テーブルの説明のコメントを追加できるのはよさげ

横山三国志に「うむ」は何コマある?〜マンガ全文検索システムの構築

  • うむ
  • 横山三国志は規格が揃っているので処理に適しているとか面白すぎ
  • コマ取得アルゴリズムは聞いてみると以外と単純で驚き
  • python whooshは便利そうなので触ってみたい

OSS開発を仕事にする技術

  • 無理ゲーな目標を立てる
    • コントローラブルとアンコントローラブルをわける
    • コントローラブルに集中する
  • もっとも生産性が高いのは「作らない」こと

Chrome拡張を使って様々なWebサービスをハックする

  • 正規表現置換はよさげ、各言語で作るのいいかも
  • 独自ライブラリ便利そう
  • Chrome拡張から触れるのは基本DOMだけ

Googleが開発したニューラルネット専用LSITensor Processing Unit」

  • DCの温度管理も機械学習でやって、電力効率が15%よくなった
  • スマホのDeepLerningをtensorflowをDSPで動かすと速くて省電力でいける
  • TPU第一世代の話
  • ASIC : アプリケーションスペシックIC (application specific )
  • 15ヶ月でASICを作り終わった
  • 2015年から使ってる
  • 第一世代TPUは学習と推論の推論にしか使ってない
  • 2006年ぐらいから計画してた

OSSで始めるセキュリティログ収集

  • auditログを取ろう、見よう
  • ただauditログは見づらいのでパースしたい
    • osqueryかElastic Beatsが良さそう
  • osqueryはrocksDBのというKVSを内部で持っている
  • osqueryの今のバージョンだとアプリケーションに影響はでてない
  • auditログが見づらいのは思っていたので、osqueryは是非試してみたい
  • 個人的には今回一番ためになったセッション

Factory Class

  • キーボードを作って販売した話
  • ぜひ発送の問題とかも入れて本して欲しいぐらい面白かった

カンファレンス感想

  • 刺激的な3日間だった
  • 普段は聞かない分野の話もきけて最高
  • 試してみたい技術がいっぱい知れた
  • 施設的にしょうがないけど、コーヒーが一つ部屋でしか飲めないは残念
  • 名札にベストスピーカーの投票ページのQRコードがあるソリューションすごい
  • ランチ美味しい
  • 同時通訳の人すごい、ありがとう
  • ペパボラップが頭に残り続ける

denite.nvim の設定 備忘録

denite.nvimはvimでいうところのUnite

インストー

dein.tomlに以下を追加

[[plugins]]
repo = 'Shougo/denite.nvim'

#インストール後にNeoVimで以下を実行して再起動することで有効になる
:UpdateRemotePlugins

設定

まだまだ設定しきれてないが設定したのは下記

  • grepでagを使用する まずはagをインストー
$ brew install the_silver_searcher

neovim側の設定

"grepでagを使用するように設定
call denite#custom#var('grep', 'command', ['ag'])
"カレントディレクトリ内の検索もagを使用する
call denite#custom#var('file_rec', 'command', ['ag', '--follow', '--nocolor', '--nogroup', '-g', ''])
"その他のgrepの設定
call denite#custom#var('grep', 'default_opts',['-i', '--vimgrep'])
call denite#custom#var('grep', 'recursive_opts', [])
call denite#custom#var('grep', 'pattern_opt', [])
call denite#custom#var('grep', 'separator', ['--'])
call denite#custom#var('grep', 'final_opts', [])
"denite時に使用するキーマップ
"ESCキーでdeniteを終了
call denite#custom#map('insert', '<esc>', '<denite:enter_mode:normal>', 'noremap')
call denite#custom#map('normal', '<esc>', '<denite:quit>', 'noremap')
"C-N,C-Pで上下移動
call denite#custom#map('insert', '<C-n>', '<denite:move_to_next_line>', 'noremap')
call denite#custom#map('insert', '<C-p>', '<denite:move_to_previous_line>', 'noremap')
"C-J,C-Kでsplitで開く
call denite#custom#map('insert', '<C-j>', '<denite:do_action:split>', 'noremap')
call denite#custom#map('insert', '<C-k>', '<denite:do_action:vsplit>', 'noremap')

" 以下はdenite起動時に使用するキーマップ
" バッファ一覧
noremap <C-P> :Denite buffer<CR>
" ファイル一覧
noremap <C-N> :Denite -buffer-name=file file<CR>
" 最近使ったファイルの一覧
noremap <C-Z> :Denite file_old<CR>
" カレントディレクトリ
noremap <C-C> :Denite file_rec<CR>
"バッファ一覧
nnoremap sB :<C-u>Denite buffer -buffer-name=file<CR>

"Denite でバッファ内検索 
nnoremap <silent> <Leader><C-f> :<C-u>Denite line<CR>
nnoremap <silent> <expr><Space>l ":<C-u>DeniteWithCursorWord line<CR>"
  • 表示をカスタマイズ
" プロンプトの左端に表示される文字を指定
call denite#custom#option('default', 'prompt', '>')
" deniteの起動位置をtopに変更
call denite#custom#option('default', 'direction', 'top')

MacのSpotlightからneovimを起動する方法

そもそもSpotlightから起動するのが、しっくり来てない人もいると思いますが、
下のGIFを見て貰えればどういうことかわかると思います。

f:id:replicity:20170602015004g:plain

私は普段、Spotlightから様々なアプリを起動しており、 ちょっとメモが取りたいなーって時とかはターミナルでvimを開かず、ここから起動してました。
なので、neovimもここから起動できるように設定します。

neovimはMacVimのようにアプリケーションとしてMacにインストールされず、GUI版もないのでインストールをしただけだと、Spotlightからは起動できないです。

ではどうするかと言うと、neovimを起動するスクリプトを書いて、それをSpotlightから実行することでSpotlightからneovimを起動するのを実現します。
スクリプトをSpotlightから実行できるようにするには.command拡張子でファイルを書けばいいので、下記のファイルを適当な場所に作成しておきます。

今回はファイル名はneovim_run.commandにしてます。

!#/bin/sh
nvim

ファイルをおいたらもうSpotlightから起動できるはずです。

f:id:replicity:20170602015048g:plain