OmniAICreator/Qiita-1.07M huggingface dataset:
NeovimでC++の環境を整えてみた

## はじめに

研究室に配属されて、とうとう逃げ続けてきたC++を書くことになったので勉強がてら環境設定をしていました。
その環境設定の備忘録として記事を書きます。

### 環境

- OS: MacOS High Sierra
- neovim: v0.2.2

Pluginはdeinを使用しています。

## インストールするもの

- [Shougo/deoplete.nvim](https://github.com/Shougo/deoplete.nvim)
- [zchee/deoplete-clang](https://github.com/zchee/deoplete-clang)
- [rhysd/vim-clang-format](https://github.com/rhysd/vim-clang-format)

上の2つは補完用
一番下のものはlinterみたいなものです。多分。
僕はセーブ時に自動で修正するようにしています。

## インストール

```toml:dein_lazy.toml
[[plugins]]
repo = "Shougo/deoplete.nvim"
on_i = 1
on_event = "InsertCharPre"
hook_source = """
  let g:deoplete#enable_at_startup = 1
  let g:deoplete#auto_complete_delay = 0
  let g:deoplete#auto_complete_start_length = 1
  let g:deoplete#enable_camel_case = 0
  let g:deoplete#enable_ignore_case = 0
  let g:deoplete#enable_refresh_always = 0
  let g:deoplete#enable_smart_case = 1
  let g:deoplete#file#enable_buffer_path = 1
  let g:deoplete#max_list = 10000
  set completeopt-=preview
  " autocmd InsertLeave,CompleteDone * if pumvisible() == 0 | pclose | endif
"""

[[plugins]]
repo = "zchee/deoplete-clang"
on_ft = "cpp"
depends = "deoplete.nvim"
hook_add = """
let g:deoplete#sources#clang#libclang_path='/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/libclang.dylib'
let g:deoplete#sources#clang#clang_header='/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang'
"""

[[plugins]]
repo = "rhysd/vim-clang-format"
on_ft = "cpp"
hook_add = """
function! CPPCodeCleanup()
  let l:lines='all'
  let g:clang_format_fallback_style = 'Google'
  :pyf /usr/local/share/clang/clang-format.py
endfunction
command! CPPCodeCleanup call CPPCodeCleanup()
autocmd BufWrite *.{cpp} :CPPCodeCleanup
"""
```


### Shougo/deoplete.nvim

`Shougo/deoplete.nvim`は言わずとしれた補完用のプラグインですね。
これはneovim使ってる人だったらだいたい知ってるんじゃないかなと思います。

コメントアウトしている`autocmd InsertLeave,CompleteDone * if pumvisible() == 0 | pclose | endif`は `deoplete-clang`の使用時にneovimの上にプレビューウィンドウが出てくるんですが、それを補完終了時に閉じてくれるというものです。
僕はそもそも、プレビューウィンドウいらないなと思って、最初から出ないようにしています。(`set completeopt-=preview`)
特に気にならないと言う人は無くてもいいと思います。

### zchee/deoplete-clang

これはdeoplete.nvimのC, C++用の拡張みたいなものです。
使用するにはClang等のパスを通す必要があります。

パスについては、僕はXCodeのものを使用しました。
適宜パスは変えてもらえるといいかもです。

### rhysd/vim-clang-format

僕は保存時にC++のフォーマットを整理するようにしています。
調べてみたら、コード規約は色々あるみたい。
僕は特にこだわりが無いのでGoogleを使っています。

## 最後に

他に調べてみたら、[thinca/vim-quickrun](https://github.com/thinca/vim-quickrun)を使って自動コンパイルとかも良さげだった。
これはまた必要になったら追加してみようかな。

一応これがスクショです。
deopleteで[clang]が出てきていたら、deoplete-clangの導入は成功していると思います。

<img width="1438" alt="スクリーンショット 2018-04-23 8.31.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/172408/23eae30c-2826-4669-3899-7e50aa5e7fa9.png">
Apache Moduleでcookieの使い方

こっちのAPI使うのが正解っぽい。今私も勉強中...

```
apr_status_t 	ap_cookie_write (request_rec *r, const char *name, const char *val, const char *attrs, long maxage,...) AP_FN_ATTR_SENTINEL
 
apr_status_t 	ap_cookie_write2 (request_rec *r, const char *name2, const char *val, const char *attrs2, long maxage,...) AP_FN_ATTR_SENTINEL
 
apr_status_t 	ap_cookie_remove (request_rec *r, const char *name, const char *attrs,...) AP_FN_ATTR_SENTINEL
 
apr_status_t 	ap_cookie_remove2 (request_rec *r, const char *name2, const char *attrs2,...) AP_FN_ATTR_SENTINEL
 
apr_status_t 	ap_cookie_read (request_rec *r, const char *name, const char **val, int remove)
 
apr_status_t 	ap_cookie_check_string (const char *string)
```


以下ガセネタ注意


cookieの設定

```
apr_table_set(r->headers_out, "Set-Cookie", "hogehoge=0" );
```

cookieの取得

```
// 2回目はhogehoge=0が取れる1回目はNULL(nullptr)
const char* cookie = apr_table_get(r->headers_in, "Cookie"); 
```

知らなかったですけどcookieって文字列だったんですね。
自分でパースしなきゃならないのは面倒ですね…

次はセッション作りたいが考えないといけないですね。
こんなコアな部分今更作りたくない訳だけど...基本機能としてはないんですね。

追記
 これはcookieじゃない…確かに値は保持してたけど、ブラウザ閉じても残ってる。
 再調査します。
ターミナル（Mac）でSDカードなどのメモリーに移動

Linuxで外部記憶装置（=volumeと言うらしい。それすら知らなかった。）に移動するやり方を知らなかったのでメモ。

ターミナルで以下を実行すればよい。
`cd /volumes
cd [移動したいメモリー]`

正確には外部記憶装置=volumeではないらしい。
MACのデフォルトのテキストのエディタではsudoが効かない

こんなことで困ってるマヌケは私だけかもしれませんが。

`` sudo open -t 開くファイル ``
これではroot権限で開けず、ファイルを書き換えられないようです。

権限解放して、どうしようもなくなってosインストールしなおした事は秘密

どうやら権限が管理できるテキストエディタを使う必要があるとのことです。
めんどくさかったので私はviに逃げました。 

`` sudo vi 開くファイル ``
Apache ModuleをC++でビルドできるようにする

アパッチモジュールをC++でビルドできるようにしました。

ネット上を探したけど、日本語サイトでよいのがなく、試してもダメなものばかり。
結局githubで公開されていたコードから拝借したものが良かったので紹介しておきます

結論から言えばこの方のmakeファイルを参考にさせて頂きました。まじ感謝。
https://gist.github.com/jainvishal/64efa5534fd93fad504495304168ffd3

引用
Makefile

```
##
##  Makefile -- Build procedure for sample foo Apache module
##  Autogenerated via ``apxs -n foo -g''.
##
builddir=.
top_srcdir=/home/vishalj/www
top_builddir=/home/vishalj/www
include /home/vishalj/www/build/special.mk

CXX=g++
CXXFLAGS=-std=c++14

#   the used tools
APACHECTL=~/www/bin/apachectl

#   additional defines, includes and libraries
#DEFS=-Dmy_define=my_value
#INCLUDES=-Imy/include/dir
#LIBS=-Lmy/lib/dir -lmylib

#   the default target
all: local-shared-build

#   install the shared object file into Apache 
install: install-modules-yes
#   cleanup
clean:
    -rm -f mod_foo.o mod_foo.lo mod_foo.slo mod_foo.la

#   simple test
test: reload
    lynx -mime_header http://localhost/foo

#   install and activate shared object by reloading Apache to
#   force a reload of the shared object file
reload: install restart

#   the general Apache start/restart/stop
#   procedures
start:
    $(APACHECTL) start
restart:
    $(APACHECTL) restart
stop:
    $(APACHECTL) stop
```

あとはreload叩くだけ。
`` sudo make reload ``

あと環境によってはパスが違うのでご注意ください。
私はmacなので、以下の部分を書き換えてます。

```
top_srcdir=/usr/share/httpd
top_builddir=/usr/share/httpd

APACHECTL=apachectl
```
Exiftoolで写真にGPSデータを埋め込んで撮影地点のポイントデータを取得する。

![DSC_2654.JPG](https://qiita-image-store.s3.amazonaws.com/0/60438/495cda89-8bb2-53b9-5e26-2ec5859c06bd.jpeg)


[埋蔵文化財所在確認調査報告書をQGISで作成する作業フロー](https://qiita.com/ishiijunpei/items/ca5dda0ae0953a418d92)の記事ではGPSログと写真をマッチングさせるためにGPSpruneを使用し、写真に埋め込まれたジオタグデータからポイントデータを生成するためにphoto2kmzを使用しました。
しかし、手順が複雑で長いのでコマンドラインで同じ作業を**簡潔**に行います。

## [Exiftool](http://owl.phy.queensu.ca/~phil/exiftool/)

Debian Linuxのリポジトリにはデフォルトで入っていました。

```shell

sudo apt install libimage-exiftool-perl

```


## 準備

同じディレクトリに画像とGPXデータを置いておく。

![01.png](https://qiita-image-store.s3.amazonaws.com/0/60438/771e6c23-523f-811e-35b6-d458372225ff.png)


## 手順

```shell


#1 写真のExifデータをxmpファイルに書き出す
exiftool *.JPG -k -o %d%f.xmp

#2 GPSデータをxmpファイルへ書き込む
exiftool -geotag 180420.gpx '-xmp:geotime<DateTimeOriginal' *xmp

#3 （GPSデータの入った）xmpファイルのデータをのExifに書き込む
##写真のあるディレクトリは絶対パスで指定
exiftool -k -tagsfromfile '%f.xmp' -r -ext JPG '/home/hoge/TestPhoto'

#4 ジオタグ付き画像から位置情報付きのcsvファイルを生成
exiftool -csv -GPSLongitude -GPSLatitude -n  *.JPG >exif.csv

```

画像ファイル名と緯度、経度が書き込まれたcsvファイルが作成されます。
![02.png](https://qiita-image-store.s3.amazonaws.com/0/60438/ef79e4f4-bdd2-7a90-a289-bffa2eb239d4.png)


## csvファイルをQGISで開く

作成したexif.csvをQGISで開くと撮影地点がマッピングされています。
GPSpruneとphoto2kmzを使うよりも圧倒的に**時間短縮**になるのと、**手順を覚えなくても良い**（再現性が高い）ことが利点です。
![03.png](https://qiita-image-store.s3.amazonaws.com/0/60438/6e99e99e-68e1-d78f-d593-ab236d0bef27.png)


### 参考にしたサイト

[exiftoolでジオタグ追加](http://d.hatena.ne.jp/haru-kichi/20101104/p1)
[QGISのPhoto2Shapeプラグインのエラー対処法](http://koutochas.seesaa.net/article/417307012.html)
インタラクティブフィルターの表示と最終的なstdoutを別にしてみた

# TL;DR

- fzf等のインタラクティブフィルターで絞り込み対象とstdoutへ渡す絞り込み結果を分けたいときがある
- 絞り込み対象の表示を加工するオプションは調べたけどないっぽい
- とりあえずやってみたけどスマートじゃない感が半端ないので知ってる人教えてください

## なにがしたいか

CLIにこもって生活を送る私にとって
fzfやpecoといったインタラクティブフィルターは私の生活に欠かせないものになっています。
しかし最近になって、この手のツールの絞り込みの表示と最終的なstdoutは必ずしも同じでなくて良いのではないか
と思うようになりました。

## なぜやりたいか

最近、OSSに貢献したいなーと思って、他の人が作成したGitHubリポジトリに対してプルリクを送ることが何回かあったのですが、
その際の手順として

1. 対象リポジトリをフォーク
1. フォークしたリポジトリをクローン(ghq使用)
1. `ghq list -p` を `fzf` でフィルタした結果で `cd`

ということをするんですが、その際にフィルタリングがめんどいなと思うことがありました。

私の場合、`手順3`の実行時に下記の通り `ghq list -p` の結果が表示されているわけなんですが、
このとき自分がフォークしたリポジトリに移動したいから
fzfのファジー検索を活かして `lighttiger2505` を雑にタイプして、そっからまた `go-gitlab` と打ちます。

```
> go-gitlab
  1/2
> /home/lighttiger2505/dev/src/github.com/xanzy/go-gitlab
  /home/lighttiger2505/dev/src/github.com/lighttiger2505/go-gitlab
```

ところがここで先頭にある `/home/lighttiger2505/dev/src/` が邪魔してくるんですよ。
上記２つの候補にどちらも自分のユーザ名があるせいでどっちも対象になってしまう。

というわけで、fzf上では以下のように表示させておいて、

```
> go-gitlab
  2/69
> github.com/xanzy/go-gitlab
  github.com/lighttiger2505/go-gitlab
```

最終的にstdoutに渡してくれるのは、フルパスの
`/home/lighttiger2505/dev/src/github.com/lighttiger2505/go-gitlab`
になったら素敵だなーと思ったわけです。

## どうしたか

あるオプションを指定したら、そのスクリプトを実行して加工した結果をディスプレイ出力して、
最終的にstdoutに渡してくる結果は、加工前の情報というのが理想だったのですが、
私がヘルプとにらめっこした感じなさそうでした。

なので結果として表示時の加工と処理実行前の復元を自前でやることで解決しました。
あっても良さそうな気がするけど、これをやるとシンプルさがなくなる気もするし、難しい。

というわけで最後に作ったスクリプトおいておきます。

```zsh
function fzf-ghq=repository() {
    local GHQ_ROOT=`ghq root`
    local REPO=`ghq list -p | sed -e 's;'${GHQ_ROOT}/';;g' |fzf +m`
    if [ -n "${REPO}" ]; then
        BUFFER="cd ${GHQ_ROOT}/${REPO}"
    fi
    zle accept-line
}
zle -N fzf-ghq=repository
```
Ajax, JavaScript関連の参考ページまとめ

参考ページまとめ
大変勉強になります。

img src="" で無駄リクエストが飛ぶ問題
https://lealog.hateblo.jp/entry/2014/03/27/224121

非同期処理中の Now Loading を jQuery で表示させる方法 ※ロード中のくるくる表示
https://webllica.com/jquery-now-loading/

くるくる画像作成 ※これは感動しました。
http://loadergenerator.com

XMLHttpRequest
http://webos-goodies.jp/archives/50548720.html

バイナリデータの表示
https://qiita.com/Yarimizu14/items/f56123c738f12ad1844a

jQueryのajaxだとバイナリ関係がうまくいかなかった。
XMLHttpRequestでformデータを作成しblobで取り出して表示が正解ぽい。

今後もやりそうなので、メモ

```html
<script type="text/javascript">
    $("#process").click(function(){
        var form = $('#my_form').get()[0]
        var formData = new FormData( form );

        var request = new XMLHttpRequest();
        request.responseType = 'blob';
        request.onreadystatechange = function()
        {
          if( request.readyState == 4 && request.status == 200 )
          {
              var image = document.getElementById("image");
              var url = window.URL || window.webkitURL;
              image.src = url.createObjectURL(request.response);
            }
          }
        }
        request.open("POST", "sample/"); //POST先
        request.send(formData);
    });
	});
</script>

  <form id="my_form" method="post" action="sample/" enctype="multipart/form-data">
    <input type="file" name="image" size="30">
    <input id="process" type="button" value="実行" />
  </form>
  <img id="image" src="about:blank">

```
Microsoft Visual Studio2012の簡単な使い方

##今回はMicrosoft Visual Studioの簡単な使い方をメモしていきます。
####　＊初期設定に関しては[前回](https://qiita.com/masahiko11210/items/8343a7b59c32ed54311a)をご覧ください。
###今回は1、2、3の順番でメモしていきます。
![タイトルなし1.png](https://qiita-image-store.s3.amazonaws.com/0/249333/43f5d43a-347d-2d26-335b-1a500a121a37.png)
####まずは１のツールボックスの使い方から。
・ツールボックスをクリックします。
*ここにツールボックスがない場合はCtrl+Alt+xキーを押してください
![タイトルなし3.png](https://qiita-image-store.s3.amazonaws.com/0/249333/be700ddf-0760-9e95-8075-11ea318e9a46.png)
・クリックすると次の画像ようになります。
![タイトルなし2.png](https://qiita-image-store.s3.amazonaws.com/0/249333/14c87c43-b928-7450-ef7a-d8301781618c.png)
・この中から自分が作りたいものにあったものを白いところにD&D（ドラッグ＆ドロップ）します。
今回は試しにButtonにカーソルを合わせてD&Dしていきます。![タイトルなし4.png](https://qiita-image-store.s3.amazonaws.com/0/249333/1c087abb-26dc-8e5e-7c14-bac58ec9bbd1.png)
・D&Dをすると上のような感じになります。
・ツールボックスの基本的な使い方は以上です。
どんなものがあるかはご自身でいろいろ試してみてください。
###次にプロパティの簡単な使い方についてです。
ここではいろいろな値や設定を変えることができます。
・まずはプロパティをクリックします。
![タイトルなし.png](https://qiita-image-store.s3.amazonaws.com/0/249333/930e2826-7919-5b15-b5c2-b40323c4bee0.png)
・そうしたら次のようなものが出ます。![タイトルなし1.png](https://qiita-image-store.s3.amazonaws.com/0/249333/d2922cde-9a88-ac4c-432e-3f3097fc3896.png)
・今のままでは何も表示されていないので先ほどD＆Dしてきたボタンを1クリックします。
![タイトルなし2.png](https://qiita-image-store.s3.amazonaws.com/0/249333/fb11ee6d-122d-e1f5-d60f-7c2fb928b6a9.png)
・するとプロパティに今のボタンのプロパティが表示されます。
自分が今何のプロパティを見ているのか確認するときは名前の下の種類を確認すればわかります。
今回はボタンをクリックしたので種類はButtonと表示されています。
ここはさっきも言った通り値や設定の変更ができる場所です。
今回は試しにContentの中の文字をボタン変更してみます。
![タイトルなし3.png](https://qiita-image-store.s3.amazonaws.com/0/249333/9ddf7643-5e04-2f11-cb56-081a06dbc27d.png)
↓
![タイトルなし4.png](https://qiita-image-store.s3.amazonaws.com/0/249333/081cf42e-de01-67b1-06ad-beebf90d2835.png)
・変更するとButtonがボタンというカタカナになります。
ツールボックスからD&Dしてくるものによってプロパティに表示されるものが変わってくるのでこちらもまた各々確認しておくといいと思います。
###最後に開始ボタンについてです。
![タイトルなし5.png](https://qiita-image-store.s3.amazonaws.com/0/249333/98a3e8f3-a672-83b9-9898-72b06aa89304.png)
#####・このボタンを押すとデバックが始まります。
さっそく押してみます。
![無題.png](https://qiita-image-store.s3.amazonaws.com/0/249333/dd9ed9ef-04b7-b638-4e85-741e33f981c1.png)
実行ボタンを押すと上のような状態になります。
この状態でボタンを押しても何も命令文が書かれていないので何も実行されません。
では一度囲んでいるところを押してデバッグを終了します。![無題1.png](https://qiita-image-store.s3.amazonaws.com/0/249333/f57a177b-8d2b-d4b9-adcc-fcaeb5f56696.png)
次にボタンをダブルクリックします。
![無題２.png](https://qiita-image-store.s3.amazonaws.com/0/249333/c96eb674-addb-44bd-acfb-ce7a623ee267.png)
すると次のような画面が出ます。
![無題４.png](https://qiita-image-store.s3.amazonaws.com/0/249333/3976e926-7f22-d37f-d91a-28d8f403bc4a.png)
上で赤で囲っている部分はVisualstudioが環境に応じて作成してくれている部分なので必要な時以外は触らないようにします。
今回はボタンに機能を持たせたいので下のところに命令文を書いていきます。![無題５.png](https://qiita-image-store.s3.amazonaws.com/0/249333/aafe8b80-9878-8efc-d09e-a1e027c3c11a.png)
ではわかりやすいようにボタンを押したらこのウィンドウを閉じるというソースを書き入れます。
![無題６.png](https://qiita-image-store.s3.amazonaws.com/0/249333/0739163f-b8cf-ce6b-a7f1-8082e11ff0d7.png)
これがかけたら再度開始ボタンを押して出てきたウィンドウのボタンを押してみてください。
勝手に開始ボタンを押して出てきたウィンドウが閉じると思います。
###・以上がVisualstudioの基本的な使い方となっています。
Visualstudioには様々な機能があるので今回は必要最低限のことしか紹介していないので是非もっと知りたいという方はいろいろ調べてみてください。
以上、閲覧ありがとうございました。
Atomパッケージ"script"のPythonのバージョンを変更する方法

# Python2or3.x.xで動かしたい
確認Version: Atom`1.25.0` script`3.17.3`

初投稿です。
CoffeeScriptに詳しくないので...うまくやる人はもっとうまくやるはず...。
とりあえず動けばいい人向けです。

1. パッケージ"script"をインストール
2. コンフィグフォルダを開く
　Settings -> OpenConfigFolder

3. "python.coffee"を開く
　script -> lib -> grammars -> python.coffee

4. 以下を修正する

```
exports.Python =
  'Selection Based':
    command: 'python'
    args: (context) -> ['-u', '-c', context.getCode()]

  'File Based':
    command: 'python'
    args: ({filepath}) -> ['-u', filepath]
```

python2.x.xを使用するなら`command: 'python'`
python3.x.xを使用するなら`command: 'python3'`



以上...他に根本的な解決の仕方がある気がする...。
M5stackで遊んでみる(Wi-Fi接続〜M5Cloudに登録まで)

先の投稿でファームの更新までやったので今回はM5Cloud登録までやろうと思います。

# M5stack自身のWi-Fiへ繋げる

ファームを書き換えて再起動すると、このSSIDに繋げという指示がディスプレイに表示されているので、
MacをそのWi-Fiに繋ぎます。特にパスワードとかは必要ないので、
ただ単純に接続するWi-Fiを切り替えるだけで済みます。

# 接続するWi-Fi情報の登録

M5stackのWi-Fiに繋いだらブラウザを開いて http://192.168.4.1 にアクセスします。
他の個体を持っていないのでもしかしたらこのURLは変わるかもしれません。

アクセスするとM5stackが繋ぎに行くWi-Fiの設定画面になります。
ここでM5stackが繋ぎに行くWi-FiのSSIDを選択し、パスワードを入力してやります。
うまく繋がるとM5stackが再起動してディスプレイにCheck Codeが表示されます。
Macが繋いでいたM5stackのWi-Fiへの接続はこの段階で切れて元のWi-Fiへ勝手に繋ぎ直されます。
（スクリーンショット撮り忘れました。。。）


# M5Cloudへのアカウント登録

http://io.m5stack.com へアクセスします。
すると以下のよう画面が出るのでregisterボタンを押します。

<img width="344" alt="スクリーンショット 2018-04-23 1.34.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/12695/9f0d0178-dd47-a6df-779b-f35b3c6ca551.png">

メールアドレスとパスワードの入力画面が出るので入力してregisterボタンを押してあげます。
これで登録終了っぽいです。メールアドレスに登録ようURLが送られてくると思いきや、
何も送られて来ずにすぐにログインできました。

<img width="342" alt="スクリーンショット 2018-04-23 1.35.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/12695/75481690-7afa-dcef-7d9d-89e4ed65f591.png">

# M5Cloudへのデバイス登録

io.m5stack.com にログインするとデバイス管理画面が出てくるのでここでAddボタンを押します。

<img width="530" alt="スクリーンショット 2018-04-23 1.36.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/12695/832481fd-f175-5a4a-40b3-654cf7c8d968.png">

Addボタンを押すとダイアログが出てくるので、ここにM5stackのディスプレイに表示されているチェックコードを入力します。

<img width="644" alt="スクリーンショット 2018-04-23 1.37.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/12695/4a3dc749-d86a-d08b-4602-61212d7fa101.png">

登録が終わるとディスプレイの一番下に　 `You device is registered.` と出てきます。
Yourじゃねーのかなこれ。

<img width="320" alt="registered" src="https://qiita-image-store.s3.amazonaws.com/0/12695/eeaf0a31-d4d1-fc06-6536-d76e68aa5bea.jpeg">

先ほどのデバイス管理画面に一つデバイス情報が出てきたので
これでデバイスの登録はできたっぽいです。
次あたりはMicroPythonでHello World的なことやりたいですね。
Vue.jsをシンプルに理解しよう

##Vue.jsって聞いたことあるよね？
最近ホットみたいですねVue.js、今更ですが入門者向けにVue.jsを紹介したいと思います。
誰でもわかるように書きますので多少間違っていても許してください!何でもしますから!


続きを書きました。
[Vue.jsをシンプルに理解しよう その2](https://qiita.com/yusuke_ten/items/3c5ae79da459fb566fbd)


##双方向データバインディング？
Vue.jsのインスタンスの作り方とかは他にもいろんな方が紹介していると思うのでそちらを参照してください。
まず一番基本的で便利なやつを紹介します。

![スクリーンショット 2018-04-22 23.01.47.png](https://qiita-image-store.s3.amazonaws.com/0/251548/f3a46a80-f35b-1500-972e-d43fea297aea.png)

Vueインスタンス内のdataというオブジェクト内の変数がhtmlと連動します。
かっっこいい言い方すると双方向データバインディングとか言います。
分かりにくいからhtmlとjsが同じ値になるって覚えたらいいよ!

[jsfiddleで確認してください。](https://jsfiddle.net/yusuke_ten/2s9emen9/5/)

dataの中にさらにオブジェクトを入れることもできます。
　![スクリーンショット 2018-04-22 23.08.18.png](https://qiita-image-store.s3.amazonaws.com/0/251548/7fa0ea94-690e-6f7e-d58b-e8c2bb8af6d8.png)

便利だ...

ちなみに{{  }}って書く書き方のことをMustache構文と言います。読み方はマスタッシュ？

##htmlの属性もバインドしたいって？

さきほど使った{{ }}みたいな記法は*htmlのタグの中に書くことはできません。（大事）*
なのでこんな風に書きます。

![スクリーンショット_2018-04-22_23_57_40.png](https://qiita-image-store.s3.amazonaws.com/0/251548/30eedade-149f-e6d7-4f22-8bd6a0365145.png)

この辺からややこしいので[jsfiddleで確認してください。](https://jsfiddle.net/yusuke_ten/vc5k8jfx/)

##用語を覚えましょう。
いきなりv-bindとかわけのわからんやつが出てきましたね。
今更ですが用語を覚えちゃいましょう。

###ディレクティブ
v-bindとかv-forとかのhtmlのタグの中に書くやつ。
「v-ほにゃらら」と出てきたらディレクティブのことを言っているんだと思いましょう。
[公式リファレンスのディレクティブ一覧を貼っておきます。](https://jp.vuejs.org/v2/api/#%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%86%E3%82%A3%E3%83%96)

###コンポーネントオプション
Vueインスタンス内のオブジェクトたちの名前です、dataとかmethodsとかpropsとかです。
僕はオプションって呼んでます、どうでもいい話ですがいつもmethodsを単数形のmethodって書き間違えます。
[公式リファレンスのコンポーネントオプション一覧を貼っておきます。](https://jp.vuejs.org/v2/api/#%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3-%E3%83%87%E3%83%BC%E3%82%BF)

04/23 追記）古い公式ドキュメントを参照していました。新しいもの差し替えておきました。

**この２つを覚えたらあとは覚えなくてもいいです。**

##ディレクティブの中に式が書けるって？

>ディレクティブ属性値は、単一の JavaScript 式を期待します

と公式は言っています、しかしどこまでJavaScriptを書けるかはいまいち分かりません。
今回は簡単にv-forを使ってループを書きましょう。

![スクリーンショット_2018-04-23_0_59_57.png](https://qiita-image-store.s3.amazonaws.com/0/251548/b2c8872e-9ff8-2adc-c841-7a138970a43b.png)

ディレクティブの中に式っぽいことを書いたらそれっぽいことをやってくれます、ふわふわすぎてディレクティブ内にどこまで記述できるか分かりません。だれか詳しく教えてください！
jsfiddleの保存を忘れてました、許してください!何でもしますから!。

04/23 追記）公式によればv-forのみ固有の構文になっているようです。
v-for以外のディレクティブ(v-ifとか)は単独の式として正しければ大体何でも書けるみたいです。

##methodsを使う
methodsというオプションを使ったら「ボタンを押したらこの処理を実行」的なことを簡単に実装できます。
今回はv-onというディレクティブを使います。

![スクリーンショット_2018-04-23_1_12_12.png](https://qiita-image-store.s3.amazonaws.com/0/251548/1b2f06a3-f498-321b-514e-4fa414b3d002.png)

methodsの関数内では変数の参照にthis.を忘れないようにしましょう。

[jsfiddleで確認してください。](https://jsfiddle.net/yusuke_ten/19xyw1xm/)

##おわりに
今回はここまで。
みなさんふわふわな紹介でしたがVue.jsというものを何となく分かっていただけたでしょうか？
次はtemplateを紹介したいです（次があれば）。
Bash on Ubuntu on WindowsでReact.js

#はじめに
Bash on WindowsでReact.jsを入れるとこまで備忘録も兼ねて書きました


#手順
1. Bash on Windowsのインストール
2. nodejsのインストール
3. [Yarn](https://yarnpkg.com/lang/en/docs/install/#debian-stable)のインストール
4. create-react-appのインストール
5. パスを通す
6. tmuxのインストール


##Bash on Windowsのインストール
Microsoft store->検索->ubuntu->インストール
どっかでしくじったりしたらアンインストールして再インストールすればまっさらな環境から再スタートできます

タイトルバー（ウインドウの一番上のやつ）を右クリック->プロパティ からフォントや不透明度などを設定できます。


##nodejsのインストール
[[最先端から] WindowsでRuby/node環境 [逃げない]](https://qiita.com/kuboon/items/6d7447b7c9a359971e42)
を参考に

```
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt install nodejs
node -v
v8.11.1
```


##[Yarn](https://yarnpkg.com/lang/en/docs/install/#debian-stable)のインストール
[Yarn公式](https://yarnpkg.com/lang/en/docs/install/#debian-stable)の手順に従う

```
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get update && sudo apt-get install yarn
yarn -v
1.6.0
```


##create-react-appのインストール

```
yarn global add create-react-app
```

##パスを通す
上記のみだとパスが通らなかったので、

```
create-react-app:command not found
```
と出た。

- [Bash on Ubuntu on Windowsで~/.profileが読み込まれない件の対応](http://pachicoma.hateblo.jp/entry/2016/09/19/Bash_on_Ubuntu_on_Windows%E3%81%A7~/.profile%E3%81%8C%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%81%BE%E3%82%8C%E3%81%AA%E3%81%84%E4%BB%B6%E3%81%AE%E5%AF%BE%E5%BF%9C)
- [yarn global addしたパッケージのパスを通す](https://qiita.com/t-hiroyoshi/items/49c03456e991594c3dc0)

を参考に、`~/.profile`に

```
PATH="$PATH:`yarn global bin`"
```
を追加して

```
source ~/.profile
```

[2018/12/16追記]
bash on ubuntu on windows起動時に`~/.profile`が読み込まれない問題
[ここ](http://pachicoma.hateblo.jp/entry/2016/09/19/Bash_on_Ubuntu_on_Windows%E3%81%A7~/.profile%E3%81%8C%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%81%BE%E3%82%8C%E3%81%AA%E3%81%84%E4%BB%B6%E3%81%AE%E5%AF%BE%E5%BF%9C)を参考に、
bash on ubuntu on windowsのアイコンを右クリック-> プロパティ -> 「ショートカット」タブの「リンク先」の欄に`--login`を追記して適用
すると起動時に`~/.profile`を読み込んでくれる


#tmuxのインストール
ローカルサーバー起動しつつファイル編集するために複数窓を扱えるtmuxを入れます。

```
sudo apt install tmux
```

##開発開始!!

```
create-react-app my-app
cd my-app
yarn start
```

#最後に
tmux入れると複数窓扱えて便利です


#参考にしたとこ
- [yarn global addしたパッケージのパスを通す](https://qiita.com/t-hiroyoshi/items/49c03456e991594c3dc0)
- [[最先端から] WindowsでRuby/node環境 [逃げない]](https://qiita.com/kuboon/items/6d7447b7c9a359971e42)
- [Yarn公式](https://yarnpkg.com/lang/en/docs/install/#debian-stable)
- [Bash on Ubuntu on Windowsで~/.profileが読み込まれない件の対応](http://pachicoma.hateblo.jp/entry/2016/09/19/Bash_on_Ubuntu_on_Windows%E3%81%A7~/.profile%E3%81%8C%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%81%BE%E3%82%8C%E3%81%AA%E3%81%84%E4%BB%B6%E3%81%AE%E5%AF%BE%E5%BF%9C)
嘗試啟動 Office App 時出現「發生錯誤」錯誤

このまえ知り合いから聞かれた件。

https://support.office.microsoft.com/ja-jp/article/%E5%98%97%E8%A9%A6%E5%95%9F%E5%8B%95-office-app-%E6%99%82%E5%87%BA%E7%8F%BE%E3%80%8C%E7%99%BC%E7%94%9F%E9%8C%AF%E8%AA%A4%E3%80%8D%E9%8C%AF%E8%AA%A4-4b4471dd-cf86-4a37-910d-35a01a6c7d17?NS=OCSAC2RCLICKTORUN&Version=16&SysLcid=1028&UiLcid=1028&AppVer=CCL160&HelpId=%220x426-0x0-%22&ui=zh-TW&rs=zh-TW&ad=TW


台湾語のエラーメッセージ
そこであてにならないGoogle翻訳に入れたところ珍しく翻訳された。
技術系ならGoogle先生は中国語でも強いのかもしれない。

Windows10版の対応方法
デバイスを再起動する
数分待ってからデバイスを再起動し、再度ログインしてアプリケーションを再起動してください。
コンソールからOfficeを修復する

修復ツールを入手する方法は、オペレーティングシステムによって異なります。下記のドロップダウンリストからオペレーティングシステムを選択してください。

    Windows 8およびWindows 10の[スタート]ボタンでWindowsの[スタート]ボタン（左下）を右クリックし、[コンソール]ポップアップメニューを選択します。
    オプションとコマンドのリストを表示するには、Windowsロゴのキー+ Xを押します。

    [カテゴリ]ビューの[プログラム]で、[アンインストーラ]を選択します。

    修復するOffice製品を右クリックし、[変更]を選択します。

    注：Office 365 Home EditionやOffice Home Edition 2013または2016などのスイートを使用している場合は、WordやExcelなどの特定のアプリケーションのみを修復したい場合でもスイート名を検索してください。スタンドアロンアプリケーション（WordやExcelなど）を使用している場合は、アプリケーション名を検索します。

    「どのようにOfficeプログラムを修正しますか？」画面で、「オンラインで修正する」を選択してすべての項目が修正されていることを確認し、「修復」を選択します。クイックフィックスを選択することができます。クイックフィックスは、より高速に実行できますが、破損したファイルの検出と置き換えのみが可能です[オンライン修復]修復をアンインストールして完了することは可能ですが、時間がかかります。

    画面の指示に従います。

Officeのアンインストールと再インストール

Easy Fixerを使用してOfficeをアンインストールする

    Officeをアンインストールするには、この簡単な修正ボタンをクリックします。
末尾最適化の練習メモ

# 末尾最適化の練習メモ

@pizyumiさんの以下の記事で実装している再帰処理を末尾最適化に書き直しながら練習した記事です。

https://qiita.com/pizyumi/items/f08d4a0ef337658cec77

##  列の要素の総和を返す`sum`メソッド。
* ふつうの再帰

  ```scala
  def sum(xs: List[Int]): Int = xs match {
      case Nil => 0
      case x :: xs1 => x + sum(xs1)
    }
  ```
* 末尾最適化

  ```scala
  def sum(xs: List[Int]): Int = {
    def sum(xs: List[Int], z: Int): Int = xs match {
      case Nil => z
      case x :: xs1 => sum(xs1, z + x)
    }

    sum(xs, 0)
  }
  ```

## 列の要素の数を返す`length`メソッド。
* ふつうの再帰

  ```scala
  def length[T](xs: List[T]): Int = xs match {
      case Nil => 0
      case x :: xs => 1 + length(xs)
  }
  ```

* 末尾最適化

  ```scala
  def length[T](xs: List[T]): Int = {
    def length[T](xs: List[T], z: Int): Int = xs match {
      case Nil => z
      case _ :: xs1 => length(xs1, z + 1)
    }

    length(xs, 0)
  }
  ```

## 列の最大の要素を返す`max`メソッド。

* ふつうの再帰

  ```scala
  def max(xs: List[Int]): Int = xs match {
    case List(x) => x
    case x :: xs => { val m = max(xs); if (m > x) m else x }
  }
  ```

* 末尾最適化

  ```scala
  def max(xs: List[Int]): Int = {
    def max(xs: List[Int], z: Int): Int = xs match {
      case Nil => z
      case x :: xs1 if x > z => max(xs1, x)
      case x :: xs1 => max(xs1, z)
    }
    max(xs, xs.head)
  }
  ```

## 列の全ての要素が述語を充足するかを返す`forall`メソッド。

* 末尾最適化

  ```scala
  def forall[T](f: T => Boolean)(xs: List[T]): Boolean = xs match {
    case Nil => true
    case x :: xs1 if !f(x) => false
    case x :: xs1 => forall1(f)(xs1)
  }
  ```

## 列のある要素が述語を充足するかを返す`exists`メソッド

* 末尾最適化

  ```scala
  def exists[T](f: T => Boolean)(xs: List[T]): Boolean = xs match {
    case Nil => false
    case x :: _ if f(x) => true
    case _ :: xs1 => exists(f)(xs1)
  }
  ```

## 列の中で述語を充足する最初の要素を返す`find`メソッド。

* 末尾最適化

  ```scala
  def find[T](f: T => Boolean)(xs: List[T]): Option[T] = xs match {
    case Nil => None
    case x :: _ if f(x) => Some(x)
    case _ :: xs1 => find(f)(xs1)
  }
  ```
neural network consoleのデータを表示(jupyter)

```
import os

import numpy as np
from pandas import Series,DataFrame
import pandas as pd

import matplotlib.pyplot as plt
%matplotlib inline

input_dir = 'XXX'
input_file = os.path.join(input_dir, "iris_flower_dataset_training_delo.csv")

data = pd.read_csv(input_file,delimiter=",")
data[:4]

x1 = data[data["y:label"] == 0]["x__3:Petal width"]
x2 = data[data["y:label"] == 2]["x__3:Petal width"]
plt.hist([x1, x2], stacked=False, label=["true", "false"])
    
plt.title("Petal width")
plt.ylabel("Petal width")
plt.legend(loc="upper right")
x1 = data[data["y:label"] == 0]["x__3:Petal width"]
y1 = data[data["y:label"] == 0]["x__0:Sepal length"]
x2 = data[data["y:label"] == 2]["x__3:Petal width"]
y2 = data[data["y:label"] == 2]["x__0:Sepal length"]

plt.title("Sepal length/Petal width")
plt.plot(x1, y1, "o", label="true")
plt.plot(x2, y2, "x", label="false")
plt.ylim([0, 10])
plt.xlabel("Petal width")
plt.ylabel("Sepal length")
plt.legend(loc="lower right")
```
Virtual Box の選択肢に 64bit のものがない時の対処法

参考サイト:http://did2memo.net/2015/07/10/virtualbox-64-bit-os/

原因は、BIOS設定にありました。

現在利用中のCPUは Intel Core i7-4770K、マザーボードは ASUS Z87-PROです。

普通にIntel Core i7-4770Kは、仮想化支援機能を搭載しているのですが、その設定がBIOS上でオフになっていました。

起動時のASUSロゴ画面でF2キーもしくはDeleteキーでBIOS設定に入り、「Advanced」にある「CPU Configuration」を確認しました。

すると、「Intel Virtualization Technology」が「Disable」になっていました。

Intel Virtualization Technologyの説明には、「When enabled, a VMM can utilize the additional hardware capabilities provided by Vanderpool Technology」とあります。

というわけで、これを「Enable」に変更して保存し、Windowsを起動しました。
インタフェース分離の原則(ISP: The Interface Segregation Principle)

## インタフェース分離の原則
- クライアントに、クライアントが利用しないメソッドへの依存を強制してはならない
 - 利用しないメソッドに依存してしまうとクライアントはそういったメソッドへの変更の影響を受けやすくなる
 - メソッドを利用しないのであれば、クライアントは本来その変更に無関係なはずだが、それに依存していると不用意に影響を受けてしまう
 - 利用していないメソッドに依存していると、他のクライアントがクラスに強いる変更によって、そのクラスに依存している自分まで巻き込まれてしまう
 - 不本意な結び付きをできるだけ避けるために、インタフェースを分離する


## インタフェースを分離する
- それぞれのクライアントが実際に利用するメソッドだけに依存する
- 関連性のあるインタフェースはグループ化
- 利用しないメソッドとの依存を断つ
- インタフェースにあれもこれも詰め込みすぎない

## 結論
- 「太った」クラスは、それを利用するクライアント同士が有害な関連性を持つ原因となる
- あるクライアントが「太った」クラスに変更を強いると、他の全てのクライアントに影響が及んでしまう
- 有害な関連性を断ち切るには、各クライアントは実際に自分が利用するメソッドだけに依存する
- 「太った」クラスのインタフェースを各クライアントのニーズに合うようにインタフェースを細かくグループ化すれば可能
- クライアント毎に特化したインタフェースには、それを利用するクライアントやクライアントグループだけが利用するメソッドだけを宣言
- 後で「太った」クラスを構築したければ、クライアント毎に特化したインタフェースを全て継承し、必要なインタフェースを実装
- このような方針をとることで、クライアントは自分が利用しないメソッドとの依存関係を断ち切り、クライアント同士の同士の独立性を保てる
CV勉強会＠関東メモ、特にポーズ推定

第45回　コンピュータビジョン勉強会＠関東ではやはり深層学習によるポーズ推定に関する発表が多く、今回は三件の発表があった。うち一件は会社には知らせていないとのことなので、次の二件についてのメモ。

一件はドワンゴのOpenPoseを使って2Dでのポーズ推定ののち、GANによって3Dへの逆投影を行うというもの。実演では会場が暗いためポーズ推定がうまくいかず、アリシアちゃんのモデルがたびたびパンツ丸見えになっていた。後で聞いたところ元々COCOデータセットを使って学習したポーズ推定の精度があまり高くないようで、3Dへの逆投影自体はうまくいってるとのこと。

ただ、MicrosoftのCOCOデータセットでは人物が写ってるものの、豆粒みたいに小さかったり、keypointのうち一部しかアノーテーションされていなかったりでポーズ推定を目的とした学習には向いていないと思う。むしろDeepPoseなどで使用したLSP(スポーツ画像で全身）やFLIC(映画で上半身）データセットのほうが学習効率は良いはず。

もう一件がチームラボで暗い会場の展示に使用するためRGB画像ではなくデプス情報からのポーズ推定。こちらはChainerCVでの実装とのことで、デプス情報の精度もありあまりkeypointの精度は高くなかった。ただ、これは来場者とのインタラクションが目的なのでこれで十分だと思う。

詳細は明かせないものの、残りの一件は元々社内で蓄積された映像があり、ここから1000件程度についてkeypointを手作業で収集、元の学習データとして理想的なためポーズ推定の精度も高かった。

一件目が商用利用についての制限があるOpenPoseを使用しており、精度の問題もあるため別のポーズ推定に切り替えるのではないかと思われる。（ドワンゴのVRM使用を想定）

ポーズ推定はインスタンス・セグメンテーションとの併用で様々な応用が考えられるため、学習データについても要検討項目
EV3RTのプログラム転送を行うTeraTermマクロ

**EV3RT**でプログラムを書き込む手順として最もオススメしたいBluetooth転送、
その作業手順を簡略化するTeraTermマクロを紹介します。

Bluetooth転送で書き込みが行えると様々なメリットがあります。
- microSDのスロットを傷めないのでインテリジェントユニットに優しい
- USBコネクターを傷めないのでインテリジェントユニットに優しい
- USB接続でたまに起こるハングアップが無い

# 開発環境の他に用意するもの
- [TeraTerm](https://ja.osdn.net/projects/ttssh2/)

セットアップのオプションで**.ttlファイルをttpmacro.exeに関連付ける**をチェックしてください。
<img width="374" alt="tt.png" src="https://qiita-image-store.s3.amazonaws.com/0/123504/ce70619e-deb8-98d9-df66-a8ffb109bcd3.png">

#TeraTermマクロの作成
テキストファイルで次のマクロを作成します。

```zmodem.ttl
messagebox "EV3の電源を入れてください" "起動"
connect '/C=4'
messagebox "load=>Bluetooth SPPにしてください" "転送"
zmodemsend 'C:\cygwin64\home\pulma\hrp2\sdk\workspace\app' 1
disconnect
closett
end
```


COMポート番号の指定は `connect` コマンドの引数で指定します。
COM4 を使用する場合は、`'/C=4'`と指定します。

```
connect '/C=4'
```

ZMODEMプロトコルで転送するファイル名を**絶対パス**で指定します。
相対パスでは動作しません。ドライブ名、フォルダ階層を含めた**絶対パス**を指定してください。

```
zmodemsend 'C:\cygwin64\home\pulma\hrp2\sdk\workspace\app' 1
```
#使い方

|PC |EV3 |
|:--|:---|
|マクロファイルをダブルクリックして起動します。||
|次のメッセージが表示されるので、EV3の電源を入れてからOKボタンを押下します。<img width="175" alt="pon.png" src="https://qiita-image-store.s3.amazonaws.com/0/123504/9259bee9-2dda-8fa2-1e45-e5a7196d5ec1.png">|<img width="196" alt="2018_04_21 22_44 Office Lens.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/123504/19066c04-e87a-a640-f353-f2df406a687f.jpeg">|
|EV3でBluetooth SPPを選択してからOKボタンを押下します。<img width="195" alt="spp.png" src="https://qiita-image-store.s3.amazonaws.com/0/123504/015cd4b6-c295-f528-4dd7-3ee36e504044.png">|<img width="249" alt="2018_04_21 22_46 Office Lens.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/123504/92f12c2e-59b3-10e7-ea56-b37e564ecd45.jpeg">|
|転送状況が表示されます。|<img width="202" alt="2018_04_21 22_49 Office Lens.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/123504/a18964ca-7d90-babf-54f9-5e68d0ec74b7.jpeg">|
|転送が終了するとマクロとTeraTerm本体が終了します。|<img width="182" alt="2018_04_21 22_49 Office Lens (1).jpg" src="https://qiita-image-store.s3.amazonaws.com/0/123504/239022e6-21e0-cbee-c18f-f332e76b9f3f.jpeg">Centerボタンを押下するとプログラムが実行されます。|
node.jsで分割代入 (Destructuring assignment)が使えない

# node.jsで分割代入を使用した時にエラーが発生

私の場合は以下のようなコードでエラーが発生しました。

```javascript
const hoge = {fuga: {aho: 1}};
const { aho } = hoge.fuga; // ← エラー！！
```

# 原因
私の使用していた`Node`のバージョンが古かったせいです。
使用していたバージョンは `v5.11.1`です。

以下のコマンドを打つと対応してない旨が確認できました。

`node --v8-options | grep harmony`

`--harmony_destructuring (enable "harmony destructuring" (in progress))`が表示の中に含まれています。

`Node`のリリース履歴確認してインストールしなおしても良かったんですが、めんどくさかったので適当に`v7.0.0`をインストールしてみたら使えるようになっていました。

以上です。

# ちなみに・・・
以下のコメントを参照するに、バージョン6から使用できるみたいですね:relaxed:
https://github.com/nodejs/node/issues/6183#issuecomment-209669719
M5stackで遊んでみる(買ってからファーム更新まで)

動画で見たリップシンクが面白そうだったので秋葉原に行って買ってみました。
リップシンクができるまで、ここにメモを残していこうと思います。

動作させている環境は以下になります。

* Macbook Pro 2015
* macOS High Sierra バージョン10.13.4


# /dev/tty. SLAB_USBtoUARTが無いのをどうにかする

本体に説明書は付属していませんでしたが、ファームの更新を説明してくれてるサイトがたくさんあったので、ファームの更新作業自体は全然ハマらなかったんですが、唯一、　`/dev/tty.SLAB_USBtoUART` が無かったので、これをドライバをインストールして出てくるようにするというという部分に少し手こずりました。

[ここ](https://jp.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers)からMac用のドライバをダウンロードしてインストールするだけなんですが、
このサイト[(M5Stackであそぼう)](http://mag.switch-science.com/2018/02/28/getting-started-with-m5stack/)の使い方のセクションにある
「設定画面からロックを外す」ことに気づかなかったのでそこそこ時間を持って行かれました。
ちゃんと一次情報に当たるのは大事ですね。

# ファーム更新
なんでも、買った状態で入っているMicroPythonではいろんなことが出来ないらしいので、
更新しておきます。たまたまPythonで別の開発してたってのもあって、
淡々とコマンドを叩くだけでした。楽チン楽チン。

```
$ pip install esptool
$ cd /tmp
$ wget https://github.com/m5stack/M5Cloud/raw/master/firmwares/m5cloud-psram-20180419-v0.3.9.bin
$ wget https://github.com/m5stack/M5Cloud/raw/master/firmwares/m5cloud-20180419-v0.3.9.bin
$ esptool.py --chip esp32 --port /dev/tty.SLAB_USBtoUART erase_flash
$ esptool.py --chip esp32 --port /dev/tty.SLAB_USBtoUART write_flash --flash_mode dio -z 0x1000 m5cloud-20180419-v0.3.9.bin
```

ファームの更新が終わると再起動して、M5stackの画面にWi-FiでこのSSIDに繋いでブラウザで `http://192.168.4.1` にアクセスせぇよ的なメッセージが出てきます。これで次のステップに進めそうです。
【Swift4】 ArrayをShuffleする

Swift4で配列をシャッフルする簡単なサンプルを提示します。
"阿部","伊東","佐藤","鈴木","田中","中村","藤井","松井","村田","吉田"
と五十音順に並んだ人名の配列(anArray)をシャッフルします。

```swift
var anArray = ["阿部","伊東","佐藤","鈴木","田中","中村","藤井","松井","村田","吉田"]
        //shuffle前print
        print("shuffle前")
        for i in anArray{
            print("\(i)")
        }
        //shuffleする
        for i in 0 ..< anArray.count{
            let r = Int(arc4random_uniform(UInt32(anArray.count)))
            anArray.swapAt(i, r)
        }
        //shuffle後print
        print("shuffle後")
        for i in anArray{
            print("\(i)")
        }
```
print結果は以下のようになります。

shuffle前
阿部
伊東
佐藤
鈴木
田中
中村
藤井
松井
村田
吉田
shuffle後
佐藤
村田
田中
阿部
鈴木
藤井
伊東
中村
吉田
松井

※※追記※※
上記のコードでは結果に偏りが生じるという御指摘を、[@t-ae](https://qiita.com/t-ae) 様より頂きました。そこで以下の新スレで検証してみました。
[たかがシャッフル、されどシャッフル 〜"permute-with-all" order biasの検証〜](https://qiita.com/BMJr/items/c2c45d7d98bc4472fd30#_reference-06c83eadd173493bd4e8)
結論をいいますと、上記コードで生じる偏りは「かなり大きい」です。
従いまして、上記コードは使わない方がよいです:sweat::sweat:。

解決策

```swift
let r = Int(arc4random_uniform(UInt32(anArray.count)))
```
を以下のように変更します。

```swift
let r = Int(arc4random_uniform(UInt32(anArray.count - i))) + i
```
これにより、結果の偏りは無くなります。
以下のようにextensionにする方法もあります。

```swift
extension Array{
    mutating func shuffle(){
        let n = self.count
        for i in 0 ..< n{
            let r = Int(arc4random_uniform(UInt32(n - i))) + i
            self.swapAt(i, r)
        }
    }
}
```

別解

```swift
for i in 0 ..< anArray.count{
            let r = Int(arc4random_uniform(UInt32(anArray.count)))
            anArray.swapAt(i, r)
        }
```
のプロセスを以下のように2回繰り返すだけでも偏りがなくなります。

```swift
for _ in 0 ... 1{
        for i in 0 ..< anArray.count{
            let r = Int(arc4random_uniform(UInt32(anArray.count)))
            anArray.swapAt(i, r)
        }
}
```
【5行くらいで書ける】keras.wrappers.scikit_learnにおけるResourceExhaustedError対策

# 概要
Kerasのモデルをscikit-learnライクに扱える[keras.wrappers.scikit_learn](https://keras.io/ja/scikit-learn-api/)を使うことで、`GridSearchCV`などでハイパーパラメータサーチが簡単にできるようになります（[ハイパーパラメータサーチを高度化・簡略化するこんなクラス](https://qiita.com/gen_fifth/items/42667bbe1180660823fe)も作ってみました）。

一方、ハイパーパラメータサーチのようにモデル構築を繰り返す場合、ResourceExhaustedErrorが発生することがあります。

ResourceExhaustedErrorの対策の1つとして、ことあるごとに`clear_session`を実行するというものがありますが、度々サーチが停止しては面倒です。なのでシンプルに__fit前に毎回`clear_session`を実行する__ことにします。

※ ここではgpu環境、バックエンドをtensorflowの想定です。

# 実装
まずは必要モジュールをインポート。

```python
import tensorflow as tf
import keras.backend.tensorflow_backend as KTF
from keras.wrappers.scikit_learn import KerasClassifier
```

次に`KerasClassifier`を継承し、クラスを1つ定義。

```python
class MyKerasClassifier(KerasClassifier):
    def fit(self, *args, **kwargs):
        KTF.clear_session()
        session = tf.Session("")
        KTF.set_session(session)
        super().fit(*args, **kwargs)
```

これで対策はOK。このクラスでモデルを定義すれば、ResourceExhaustedErrorの発生を抑えられます。

```python
n_classes = 10
def mk_nw(activation, lr, out_dim):
    model = Sequential()
    model.add(Conv2D(20, kernel_size=5, strides=1, 
                     activation=activation, input_shape=Xtrain.shape[1:]))
    model.add(MaxPool2D(2, strides=2))

    model.add(Conv2D(50, kernel_size=5, strides=1, activation=activation))
    model.add(MaxPool2D(2, strides=2))

    model.add(Flatten())
    model.add(Dense(out_dim, activation=activation))
    model.add(Dense(n_classes, activation="softmax"))

    model.compile(loss="categorical_crossentropy", optimizer=optimizers.SGD(lr=lr))
    return model

estimator = MyKerasClassifier(mk_nw, activation="linear", 
                              lr=0.01, out_dim=256, epochs=16, verbose=0)
```


# 注意
`MyKerasClassifier`をfitする（=`clear_session`を実行する）と、`clear_session`の実装に書いてある通り、グラフ上のモデルがすべて__Destroy__されます。必要なモデルがグラフ上に乗っている場合は事前に退避させてください。

## `clear_session`の実装
https://github.com/keras-team/keras/blob/master/keras/backend/tensorflow_backend.py

```python
def clear_session():
    """Destroys the current TF graph and creates a new one.

    Useful to avoid clutter from old models / layers.
    """
    global _SESSION
    global _GRAPH_LEARNING_PHASES
    tf.reset_default_graph()
    reset_uids()
    _SESSION = None
    phase = tf.placeholder_with_default(False,
                                        shape=(),
                                        name='keras_learning_phase')
    _GRAPH_LEARNING_PHASES = {}
    _GRAPH_LEARNING_PHASES[tf.get_default_graph()] = phase
```
Rails チュートリアル メモ 第3章

# 暗記事項

## コントローラーの作成

```bash
# rails generate controller コントローラ名(キャメルケース,複数形) メソッド名(小文字) メソッド名(小文字) ...
rails generate controller StaticPages home help
```

コントローラ名をキャメルケースで指定すると、それをスネークケースにした名前で実ファイルが作成される（今回だと static_pages_controller.rb）。もともと ruby コミュニティではキャメルケースが好んで使われていたが、ことファイル名は OS によってケースセンシティブだったりそうでなかったりするので、ややこしくならないようにスネークケースを使うようにした ... というのは今考えた **でっち上げ** だが、そう覚えると覚えやすいかもしれない。

## generate の取り消し

destroy を使うだけ。参考のために、作成メソッドと並べてメモ。

```bash
# コントローラーの作成と取り消し。メソッド名が必要。
rails generate controller StaticPages home help
rails destroy  controller StaticPages home help

# モデルの作成と取り消し。こちらはなぜかカラム名が不要（理由は6章）。
rails generate model User name:string
rails destroy  model User

# マイグレーションの実行と取り消し。詳しくは6章。
rails db:migrate
rails db:rollback
```

## コントローラーのテストでよく使いそうな minitest のメソッド

* `get`
* `assert_response`
* `assert_select`

# メモ

## layouts

特に何も指定しなかった場合、layouts/application.html.erb が大枠として使われ、`yield` 部分に各アクションに対応した erb ファイル（例: home.html.erb）が埋め込まれる。逆に言うと、layouts ファイルには既に html タグや head タグ等が記述されているため、home.html.erb 側に head タグを書いてはならない。試しにやってみると、body タグ内に title タグが出現したり、なんだか変なことになった。

# 気になること

## GET リクエストに対するルーティング

```ruby
get 'static_pages/home'
```

これだけのコードで、

* StaticPages コントローラの home メソッドが実行される
* （home メソッドが空にも関わらず）views/static_pages/home.html.erb が描画される

という挙動をする。これはいわゆる「規約」によるものなのだろうか？

また、その後のテストコードで `static_pages_home_url` というヘルパーを使用している。こんなヘルパーが定義される効果もあるらしい。確か名前付きルートというやつだったか。
WinDBG

#WinDBGについての忘備録

#WinDBGとは？
MSのDebugツール
https://docs.microsoft.com/ja-jp/windows-hardware/drivers/debugger/debugger-download-tools

#デバッグに必要なもの
・PDB
https://msdn.microsoft.com/ja-jp/library/ee416588(v=vs.85).aspx#ID4EUD

dllのPDBファイルが必要

#どうやってやるの？
! analyze -v 
https://blogs.msdn.microsoft.com/jpwdkblog/2009/06/11/analyze-v/

#他　参考
https://blogs.technet.microsoft.com/jpilmblg/2009/06/10/debugging-debugdiag-windbg-2/

#古いけど参考書籍
https://www.amazon.co.jp/Windows%E3%83%87%E3%83%90%E3%83%83%E3%82%B0%E3%81%AE%E6%A5%B5%E6%84%8F-%E3%83%84%E3%83%BC%E3%83%AB%E3%82%92%E4%BD%BF%E3%81%84%E3%81%93%E3%81%AA%E3%81%97%E3%81%A6%E3%80%81%E3%83%90%E3%82%B0%E3%83%8F%E3%83%B3%E3%83%88-Mario-Hewardt/dp/4048676083
JavaFX - fxml に Controller を動的に割り当てる

fxml は共通にしつつ、コントローラ処理（イベントハンドリングとか）を動的に切り替えたいみたいなことが、まれにあったりなかったりしたときの話。

# 実装
**common.fxml**

![javafx.jpg](https://qiita-image-store.s3.amazonaws.com/0/28302/542b1524-8e26-c6fa-b228-0f5618fcb93a.jpeg)

- fxml ではコントローラを割り当てないようにしておく

```java:HogeController
package sample.javafx;

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;

import java.net.URL;
import java.util.ResourceBundle;

public class HogeController implements Initializable {
    @FXML
    private Label label;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        this.label.setText("Hoge");
    }
}
```

```java:Main.java
package sample.javafx;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {
    public static void main(String[] args) {
        Application.launch(args);
    }
    
    @Override
    public void start(Stage primaryStage) throws Exception {
        FXMLLoader loader = new FXMLLoader(this.getClass().getResource("/common.fxml"));
        
        loader.setController(new HogeController());
        
        Parent root = loader.load();
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}
```

**実行結果**
![javafx.jpg](https://qiita-image-store.s3.amazonaws.com/0/28302/489e507f-55a8-50e5-f834-0e7fd700cefc.jpeg)

# 実装２
```java:FugaController.java
package sample.javafx;

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;

import java.net.URL;
import java.util.ResourceBundle;

public class FugaController implements Initializable {
    @FXML
    private Label label;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        this.label.setText("Fuga");
    }
}
```

```java:Main.java
package sample.javafx;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {
    public static void main(String[] args) {
        Application.launch(args);
    }
    
    @Override
    public void start(Stage primaryStage) throws Exception {
        FXMLLoader loader = new FXMLLoader(this.getClass().getResource("/common.fxml"));
        
        loader.setController(new FugaController()); // ★コントローラを変更
        
        Parent root = loader.load();
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}
```

**実行結果**

![javafx.jpg](https://qiita-image-store.s3.amazonaws.com/0/28302/cbd30e40-5cfb-1268-9737-d606ebec9fd5.jpeg)

# 説明
```java:Main.java
        FXMLLoader loader = new FXMLLoader(this.getClass().getResource("/common.fxml"));
        
        loader.setController(new FugaController()); // ★コントローラを変更
        
        Parent root = loader.load();
```

- `FXMLLoader` を `new` でインスタンス生成して、**`load()` する前**に `setController()` で任意のコントローラインスタンスを割り当てる
rubocop設定を共有するためのgemの作り方

よく `開発チームで横断的にrubocopを共有してルールを統一化した！` というのを見かけて
自分でもやってみたいなと思い、普段gemを作ったことがない人でも作れるように
メモがてら手順を起こしました。

## 作り方

### gemの雛形作成

rubocopを管理するgemを作る。
今回は `moshi2police` [^1]という名前のGEMを想定してサンプルを作る

[^1]: [githubにサンプルもアップしてある。](https://github.com/shinkufencer/moshi2police)もしもしポリスメン。



```sh
bundle gem moshi2police --test=rspec
```
※テストはrspecを指定したがminitestがいい場合は書き換える

### gemspecの書き換え

以下2点を行う

* gemの詳細の書き換え
* rubocopの追記

```rb:gem名.gemspec
# 前略

Gem::Specification.new do |spec|
  # ここらへんの情報はローカルgemなのでご自由に
  spec.name          = "moshi2police"
  spec.version       = Moshi2police::VERSION
  spec.authors       = ["Sample Taro"]
  spec.email         = ["sample@sample.com"]

  spec.summary       = "rubocop conifg file to team"
  spec.description   = "rubocop conifg file to team"
  spec.homepage      = "https://sample.com"
  spec.license       = "MIT"

  spec.files         = `git ls-files -z`.split("\x0").reject do |f|
    f.match(%r{^(test|spec|features)/})
  end
  spec.bindir        = "exe"
  spec.executables   = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
  spec.require_paths = ["lib"]

  # rubocopのバージョンはここでコントロールする
  spec.add_dependency 'rubocop', '~> 0.53.0'
  (略)
end

```

### rubocop.ymlの配置

configディレクトリを作成して、共有したい `rubocop.yml` を配置

```sh:作る場合の例
$ mkdir config
$ cd config 
$ vi rubocop.yml
```

## 使い方

### Gemの追加

gemファイルに作ったgemファイルのgit情報を記述する。
httpsで取得できるURL記述すれば良い

```ruby:/.Gemfile
group :development, :test do
   gem 'moshi2police' , :git => 'https://github.com/{該当するジェムのパス}'
end
```

なお、privateリポジトリを指定すると
CI環境等でbundle installの度に
IDとパスワードの入力要求を求められてしまいます。
そのため、環境変数でgithub関係の情報を記述しておくと良いです。

```sh
$ export BUNDLE_GITHUB__COM={githubのユーザ名}:{パーソナルアクセストークン}
```

### rubocopへの追加

利用したいプログラムのrubocop.ymlに
以下のように記述する

```yml:/.rubocop.yml
# inherit_gem で gem名:gem内の配置場所 で記述
inherit_gem:
  moshi2police: "config/rubocop.yml"
```


## 参考にしたもの

* [ESM 内の Ruby style guide を rubocop の設定として公開しました \- 株式会社永和システムマネジメント アジャイル事業部](https://agile.esm.co.jp/news/2016-04-01-open-esm-ruby-code-convention.html)
* [共通\.rubocop\.ymlの管理 \- rochefort's blog](http://rochefort.hatenablog.com/entry/2016/09/06/180000)
* [プライベートgemの作り方 \- Qiita](https://qiita.com/nysalor/items/c626e893f6a0d2d3782e)
* [GitHubのプライベートリポジトリのgemをbundle installする \- Qiita](https://qiita.com/minamijoyo/items/820c219ca8ffdcad917a)
chrome.identity を使ってChrome拡張でもOAuthのAPIを使う

例としてQiitaのAPIを使う。

まずはOAuthのリダイレクト先のURLの項目を`https://{拡張機能のID}.chromiumapp.org`で登録しておく。
IDは拡張機能の画面で確認することができる。

![extension.png](https://qiita-image-store.s3.amazonaws.com/0/94929/a9d2d07d-1a7b-e471-5f84-c3731aa80af1.png)

![extension_qiita.png](https://qiita-image-store.s3.amazonaws.com/0/94929/5694ac2d-50e3-d4cb-9db6-ffa3c931a692.png)

次にOAuthの認可画面を表示するコードを書く。

```js
chrome.launchWebAuthFlow({
  url: `https://qiita.com/api/v2/oauth/authorize?client_id=${clientId}&scopes=read_qiita&state=${適当な文字列}`,
  interactive: true
}, responseUrl => {
  // 後述
})
```

`chrome.launchWebAuthFlow`でユーザーを認可用のページにアクセスさせることができる。

`interactive`を`true`にするとユーザーから認可を取得していない場合は認可用のページを表示、取得済みの場合はなにもせずコールバックを呼ぶという処理になる。

次にコールバック内の処理。

```js
chrome.identity.launchWebAuthFlow({
  // 省略
}, responseUrl => {
  let url = new URL(responseUrl)
  let code = url.searchParams.get("code")

  fetch("https://qiita.com/api/v2/access_tokens", {
    method: "post",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      client_id: clientId,
      client_secret: clientSecret,
      code: code
    })
  }).then(res => res.json())
    .then(json => {
      let token = json["token"] // アクセストークン取得
    })
})
```

`responseURL`のGETパラメーターに`code`が入っている。

それをアクセストークン取得のAPIにClientIdとClientSecretと一緒に送るとアクセストークンが取得できる。
技術書典4 買った本レビュー

技術書典で購入した本の紹介と簡単なレビュー

# 技術書典概要

技術書オンリーイベント。今回で4回目となるが今回が初参加。12時前に会場に到着したが、整理券は2700番台で実際に入場できたのは14時ごろ。会場内もごった返していて大変だった。

- 開催日 **2018/04/22**
- 開催場所 **秋葉原UDX**
- 開催時間 **11:00-16:00**
- 参加費 **無料**
- H.P. <https://techbookfest.org/event/tbf04>

# 買った本レビュー

サークル紹介と本の簡単なレビュー。タイトルとクリックすると技術書典のサークルページに飛ぶ。

## [マンガでわかるDocker](https://techbookfest.org/event/tbf04/circle/16430001)

- サークル名 **マンガでわかるWebデザイン＋Git（マンガデワカルウェブデザインプラスギット）**
- 配置 **い05**
- ペンネーム **湊川あい**
- Webサイト <http://webdesign-manga.com/>
- ジャンル **ソフトウェア全般**

「Docker便利だよ？」という先輩からのアドバイスでDockerを始めたいとは思っていた。本も探していたけどレビューがどれもイマイチで迷っていた、というタイミングだったので購入。インターネット上の記事でも同様の効果は得られそうだが、マンガ形式だし700円だったので満足度は高い。まだざっと目を通しただけなので、後日これに従って手を動かしてDockerに慣れてみたい。

## [ざっクリわかる Ubuntu18.04LTS](https://techbookfest.org/event/tbf04/circle/18370001)

- サークル名 **Team ZPN（チーム ザッパーン）**
- 配置 **く40**
- ペンネーム **Team ZPN**
- Webサイト <http://zapppaaan.freepub.jp/>
- ジャンル **ソフトウェア全般**

18.04の新機能や、Ubuntuの歴史・派生の紹介など。個人的にはSnaps等の新機能に関する記事が欲しかったので購入。歴史・派生の方も丁寧に書かれていて復習にちょうどいい。巻末のバックナンバーも面白そうな記事がいくつかあったので、今度買ってみようかと思う。

## [Markdownライディング入門](<https://techbookfest.org/event/tbf04/circle/19220001>)

- サークル名 **SOLARSOLFA（ソラソルファ）**
- 配置 **い12**
- ペンネーム **藤原惟**
- Webサイト <https://note.solarsolfa.net/m/m0ee0e40a1c72>
- ジャンル **ソフトウェア全般**

Markdownの概要、歴史、おすすめエディタから記法の解説など幅広くまとまっていてかつちょうどいい分量。この本もMarkdownで作成されているらしい。QiitaやGithubでMarkdownをよく使うようになったので、復習もかねて購入。

## [テスターちゃん①②](https://techbookfest.org/event/tbf04/circle/10880005)

- サークル名 **テスターちゃん（テスターチャン）**
- 配置 **え07**
- ペンネーム **まつ**
- Webサイト <http://testerchan.hatenadiary.com/>
- ジャンル **その他**

J〇Joネタが面白かったので半分勢いで購入。

①はテストの基本用語解説など。テストは会社で渡されたテキストを読んだ程度の前知識だったけど、4コマ形式で気軽に読めるから復習にちょうどいい。テストラジオは知らなかったので今度聞いてみたい。障害票のところはぜひうちの会社の品質保証部の人たち全員に読んでほしい。

②は探索的テストとかKPTとか。SNSサービスを例に具体的な探索テストの例を挙げて、それに対してのKPTという流れがわかりやすい。


## 技術季報 2018SPRING

技術書典のパンフレット。技術書典3のレポートなどもあって面白い。特別寄稿がなかなか豪華。
C++ の小さな技術を紹介するシリーズ【小技C++ 全９回】＃２＜型エイリアスと関数宣言＞

#準備

c++ の型エイリアスには、using キーワードを使用する。

##size_tの型エイリアス

```
using Count = std::size_t;
```

##functionの型エイリアス

```
using Callback = std::function<void()>;
```

##vectorの型エイリアス
また、エイリアス対象の型がテンプレートの場合、エイリアステンプレートを使用する。

```
template< typename T >
using MyVector = std::vector<T>;
```

#型エイリアスと関数宣言

簡潔な関数宣言について考える。

```cpp
uint32_t attack( const uint8_t& strength, const uint8_t& rate );
```

この関数は 2つの uint8_t を引数として、uint32_t の値を返す。引数には strength と rate という名前が付けられている。

関数宣言において、引数はその型情報さえあればよい。先の関数宣言を簡潔な形にすると、次のようになる。

```cpp
uint32_t attack( const uint8_t&, const uint8_t& );
```

引数の型名によって、この関数が返す値の意味（ダメージ値か何かだろうか？）をなんとなく推測できていたが、こうなってしまっては推測はおろか、最早何をしたいのかわからない。

そこで、型エイリアスを使って、この関数宣言の真意を伝えよう。

```cpp
using Damage   = uint32_t;
using Strength = uint8_t;
using Rate     = uint8_t;
```

関数宣言を見直す。

```cpp
Damage attack( const Strength&, const Rate& );
```

引数名を添える必要なく、必要な全ての引数情報を詰め込んだ。また、返値の意味もわかりやすくなっている。関数宣言が簡潔となれば、誤った順で引数を与えてしまうことや、違う型で返値を受けてしまうミスを減らせるため、caller にとっても有益となる。

#関数宣言はメッセージ
規模が小さく、自分ひとりで設計が完結するプログラムの場合には、あまり気にすることはないかもしれない。しかし、幾度も説明や修正が必要なモジュール設計、特にAPI であればクリティカルな問題となり得るだろう。今回は型エイリアスを活用することで、プログラムコードが曖昧になりがちな部分の対策を紹介した。コメントがなくともすらすらと理解のできるプログラムコードほど、プログラマにとって優しいメッセージはないと思う。