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 { //実装すべき関数 //実装すべき関数 //実装すべき関数 }
- goのインターフェイスは型
- インターフェイス型にはその型が実装すべきメソッドが定義されている
- インターフェイス型に定義されているメソッドをすべて実装した時に自動的にそのインターフェイスを実装したことになる(明示的にどのインターフェイスを実装するのか書かないでいい)
- goではnilをレシーバとしてメソッドを呼び出されても、適切に処理するようにメソッドを記述する
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はすごく便利そう、テーブルの説明のコメントを追加できるのはよさげ
横山三国志に「うむ」は何コマある?〜マンガ全文検索システムの構築
OSS開発を仕事にする技術
- 無理ゲーな目標を立てる
- コントローラブルとアンコントローラブルをわける
- コントローラブルに集中する
- もっとも生産性が高いのは「作らない」こと
Chrome拡張を使って様々なWebサービスをハックする
Googleが開発したニューラルネット専用LSI「Tensor 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
設定
まだまだ設定しきれてないが設定したのは下記
$ 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を見て貰えればどういうことかわかると思います。
私は普段、Spotlightから様々なアプリを起動しており、 ちょっとメモが取りたいなーって時とかはターミナルでvimを開かず、ここから起動してました。
なので、neovimもここから起動できるように設定します。
neovimはMacVimのようにアプリケーションとしてMacにインストールされず、GUI版もないのでインストールをしただけだと、Spotlightからは起動できないです。
ではどうするかと言うと、neovimを起動するスクリプトを書いて、それをSpotlightから実行することでSpotlightからneovimを起動するのを実現します。
スクリプトをSpotlightから実行できるようにするには.command拡張子でファイルを書けばいいので、下記のファイルを適当な場所に作成しておきます。
今回はファイル名はneovim_run.commandにしてます。
!#/bin/sh nvim
ファイルをおいたらもうSpotlightから起動できるはずです。
Neovim 補完設定
すでに前回までの設定が終わっている状態で設定を続けていきます。
neovimで補完を有効にするために設定をする。
neovimではvimで使っていた、neocomplete.vimではなくdeoplete.nvimを使用する。
また、スニペットの補完はvimと同じでneosnippet.vimを使用する
deoplete.nvimとneosnippet.vimのインストール
pluginはTOMLで管理しているのでTOMLに以下を追加
[[plugins]] repo = 'Shougo/deoplete.nvim' on_i = 1 [[plugins]] repo = 'Shougo/neosnippet.vim.git' on_i = 1 on_ft = 'snipppet'
追加したら、あとは起動時にダウンロードされる
補完用のポップアップが表示された時の設定
補完用のポップアップが表示されている時に
追加した設定は下記
"補完候補選択時は<TAB>で候補移動snipppet時は<TAB>で次の入力先へ imap <expr><TAB> pumvisible() ? "\<C-N>" : neosnippet#jumpable() ? "\<Plug>(neosnippet_expand_or_jump)" : "\<TAB>" smap <expr><TAB> neosnippet#jumpable() ? "\<Plug>(neosnippet_expand_or_jump)" : "\<TAB>" inoremap <expr><S-TAB> pumvisible() ? "\<C-p>" : "\<S-TAB>"
まとめ
これでneovimでも補完が表示されるようになったのでほぼvimと同じように使えるようになってきた。
deoplete.nvimは言語ごとに保管用のpluginを入れていくようなので、必要になった言語を都度追加していく予定
alacrittyインストール 備忘録
vimとneovimをiTerm2で使用中にスクロールが遅くなることがあり、調べてたらalacrittyというのが良さげだったのでインストールした
基本的にはこの記事を参考にやれば問題はない : http://qiita.com/zebult/items/0047b72916383a5c0acf
ただ、今回はbrewからインストールするとmakeで失敗してインストールできなかった
エラーメッセージ
$brew install --HEAD mscharley/homebrew/alacritty ==> Installing alacritty from mscharley/homebrew ==> Cloning git@github.com:jwilm/alacritty.git Updating ~/Library/Caches/Homebrew/alacritty--git ==> Checking out branch master ==> make app Last 15 lines from ~/Library/Logs/Homebrew/alacritty/01.make: Compiling cgmath v0.7.0 Compiling walkdir v0.1.8 Compiling notify v2.6.3 error: custom derive attribute panicked --> src/ansi.rs:373:62 | 373 | #[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] | ^^^^^^^^^ | = help: message: proc_macro::__internal::with_parse_sess() called before set_parse_sess()! error: Could not compile `alacritty`. To learn more, run the command again with --verbose. make: *** [alacritty] Error 101 If reporting this issue please do so at (not Homebrew/brew or Homebrew/core): https://github.com/mscharley/homebrew-homebrew/issues
おそらくこのissuesと同じような問題だと思われる
https://github.com/jwilm/alacritty/issues/413
alacrittyの問題というかrust周りの問題?
brewで入れるのはとりあえず諦めて自分でbuildすることにする
#rustのインストール #rustはrustupで管理するのがよさげ : http://qiita.com/chikoski/items/b6461367e8c3875bb235 $curl https://sh.rustup.rs -sSf | sh #zshrcにsource ~/.cargo/env を追加 $echo 'source ~/.cargo/env' >> .zshrc #alacrittyのインストール #これは公式の手順を参考に実施 : https://github.com/jwilm/alacritty $git clone https://github.com/jwilm/alacritty.git $cd alacritty $rustup override set stable $rustup update stable $cargo build --release $sudo cp target/release/alacritty /usr/local/bin #alacrittyコマンドでalacrittyが起動する
とりあえず無事インストールできたので使用しながら設定は直していく
2017/04/24 追記
rustupさえ入れておけばbrewでのmakeに失敗しないようでした
https://github.com/cema-sp/homebrew-tap
$curl https://sh.rustup.rs -sSf | sh $echo 'source ~/.cargo/env' >> .zshrc $brew install --HEAD cema-sp/tap/alacritty