OmniAICreator/Qiita-1.07M huggingface dataset:
すごいHaskellたのしく学ぼう！11章のメモ


## 11章：ファンクターからアプリカティブファンクターへ

### Functor

Functorは型クラスであり、前述の通り型クラスはインターフェースのような物。
Functorは全体を写せる(map over)な性質を持つ型クラスを指している。
またインターフェースの観点から見ると、あるクラスがFunctorであるという事はつまりFunctorが実装すべきメソッドを実装しているということになる。

Functorの定義は

```haskell
class Functor (f :: * -> *) where
  fmap :: (a -> b) -> f a -> f b
```

となっており、Functorである為に実装すべきメソッドは`fmap`のみと分かる。
fmapメソッドは「aを引数に取りbを返す関数」と「ファンクターなa」を引数にとって「ファンクターなb」を返す関数である。

実際には「fmapの実装がファンクター則を満たしている」という事ががファンクターとして必要な事になっている。

### ファンクター則

ファンクター則は2つの法則があり、Functorであるにはこのどちらも満たしている必要がある。

#### 第一法則

恒等関数の保存とも言われ、`fmap id (f a) = id (f a)`である事。
これは「引数をそのまま返すidという関数」がある時、「fmapでidをaに適用した値」と「idをaに適用した値」が同じであるという事。

#### 第二法則

合成関数の分配とも言われ、`fmap (g . h) (f a) = fmap g (fmap h (f a))`である事。
これはgとhの関数がある時、「fmapでgとhの合成関数をaに適用した値」と「「fmapでhをaに適用した値」に更にfmapでgを適用させた値」が同じであるという事。
結局分かりづらいがfmapを使って関数を順番に適用した物と合成関数を適用した物が同じであるという事をいっている。

あるクラスがFunctorであると、そのクラスであることを意識せずに中身のaに対しての操作を画一的に行えるのがうれしい(はず)。

### アプリカティブファンクター

Functorの強化版であるApplicativeFunctorは

```haskell
class Functor f => Applicative (f :: * -> *) where
  pure :: a -> f a
  (<*>) :: f (a -> b) -> f a -> f b
```

という定義を持っている。
ApplicativeFunctorはFunctorと同じく型クラスであり、ApplicativeFunctorであるクラスは同時にFunctorとしても扱えることになる。
実装すべきメソッドとして`pure`と`<*>`の2つメソッドを持っている。

pureは「値a」を「アプリカティブな値a」に変換する関数であり、
<*>は「アプリカティブな値としてaをbに変換する関数が入った物」と「アプリカティブな値a」を引数として取り、「アプリカティブな値b」を返す関数である。

値として関数が入ったFunctor `f (a -> b)`を考える。
このファンクターな「`a -> b`」関数を「ファンクターなa」に対してfmapを使って適用しようとしても、fmapで適用する関数は「`a -> b`」であって、「ファンクターな`a -> b`」では無いので、一度中身の関数を取り出さなければならない。
しかしFunctorはfmapつまり「ファンクターな値を画一的に操作する方法」しか保証しないので、クラスによってはFunctorから値を取り出す方法を提供していないかもしれない。
そこでアプリカティブファンクターで、<*>が定義されていると関数がファンクターに包まれている状態でもファンクターな値に対してその値を適用できるようになる。

Functorでは操作対象の値のみがファンクターであったのに対して、ApplicativeFunctorでは操作方法の関数がファンクターであっても操作ができるようになっている。

### アプリカティブ則

アプリカティブにもファンクターと同じく、満たすべき法則がある。

+ `pure id <*> v = v`
+ `pure (.) <*> u <*> v <*> w = u <*> (v <*> w)`
+ `pure f <*> pure x = pure (f x)`
+ `u <*> pure y = ($ y) <*> u`

説明は省略されてる。
find_in_batchesは降順で処理できない

表題の通り。

active_recordにfind_in_batchesという便利なメソッドがある。

通常テーブルのデータを処理する際はeachを使うことが多いと思われるが、そのデータ量が多い場合などはメモリを食ってしまいうまく処理できないことがある。

こういった場合、find_in_batchesを使えば一度にメモリにロードするデータ量を抑えながら同様の処理ができるので大量のレコードを処理する際に便利だ。

ただ、以下のコードを見てほしい。

```rb

Article.where("id < 100000").order(:id).reverse_order.find_in_batches(batch_size: 1000) do |articles|
  // 適当な処理など...
end

```

これはArticleテーブルのidが100000以下のレコードを降順で1000件づつ処理しようとしているコードだ。

一見なにも問題ないように見えるこのコードだが、実際に発行されるSQLは以下のような感じになる。

```
// 1ループ目
SELECT * FROM articles WHERE (id < 100000) AND ORDER BY articles.id DESC LIMIT 1000
// 2ループ目
SELECT * FROM articles WHERE (id < 100000) AND (id > 99000) ORDER BY articles.id ASC LIMIT 1000
// 3ループ目
SELECT * FROM articles WHERE (id < 100000) AND (id > 99001) ORDER BY articles.id ASC LIMIT 1000
...
```

要は1ループ目以降はorder byが無視されている。

そこでドキュメントを見ると、

> NOTE: It's not possible to set the order. That is automatically set to ascending on the primary key (“id ASC”) to make the batch ordering work. This also means that this method only works when the primary key is orderable (e.g. an integer or string).


ということでちゃんとorderが無視されることが書いてある。

したがって、find_in_batchesは降順で処理できないというわけ。

ちゃんと読めということになるが案外見落としがちなので気をつけましょうという話でした。

ちなみにlimitも無視されてbatch_sizeのほうが優先されるので注意。


## 関連リンク

- [find_in_batches](http://api.rubyonrails.org/classes/ActiveRecord/Batches.html#method-i-find_in_batches)
開発プロセスについて

齢四十を超えて、ようやくチームリーダーとして一つのプロダクトをチームで開発する機会に恵まれています。それにあたって、開発プロセスをどうするかについて考えなおしてみたので、それで自分なりに出した結論について書いてみます。

# 開発プロセスの種類

いわゆる開発プロセスは、つまるところ次の３つに大きく分類されます。

* ウォーターフォール型
* 反復型
* アジャイル型

## ウォーターフォール型開発プロセス

ウォーターフォール型開発プロセスは、開発成果物が事前に把握できていて、かつ開発を阻害するリスク（技術的なもの、組織的なものなど）がないという前提で使うことのできる開発プロセスです。
ウォーターフォール型開発プロセスの最大の利点は、いつまでに何ができるのかを確実に定義できることです。あと異論はあるかもしれませんが、前提が満たされている場合、最終的な成果物の出来上がる期間は最も短くなるはずです（他の開発プロセスは、まとまった作業が終わった時点でその作業の評価をしなければならないため）。欠点は、仕様変更や技術的課題の発生による手戻りが大きいことです。あと、「とりあえず動作するアプリ」が出来上がる期間は最も長くなります。

## 反復型開発プロセス

アジャイルとウォーターフォールの間に挟まれて影が薄いですが、反復型開発プロセスというものも存在します。反復型開発プロセスは、開発成果物は事前に把握できているが、開発を阻害するリスク（技術的なもの、組織的なもの）などがあるという前提で使うことのできる開発プロセスです。
反復型開発プロセスでは、アジャイルと同じく一つの開発期間の中で複数のイテレーション（反復）を回すことが特徴になります。しかしイテレーションの目的は異なります。アジャイルのイテレーションは、完全に動作する機能を作成してユーザーからのフィードバックを得るのが目的です。しかし反復型開発のイテレーションは、開発にあたってリスクとなっている技術を使ったプロトタイプを作成してリスクを削減することを目的としています。そのため、反復型開発プロセスのイテレーションは、必ずしも動作するアプリを生み出さないこともあります。
反復型開発プロセスの利点は、ウォーターフォール型に比べて未知の技術を採用しても手戻りが少なくなります。リリースする成果物のスコープやリリース日の変更が管理されている状態で少し変動することになります。欠点としては、作ったものが実は役に立たなかったということが、アジャイルに比べると発生しやすいです。

## アジャイル開発

アジャイル開発では、そもそも開発成果物が最終的に何になるのかがわからない前提で使うことのできる開発プロセスです。
１〜２週間（あるいは数日）という短い期間で完全に動作する機能をリリースして、利用者のフィードバックを得ながら順次開発をしていくのが特徴になります。
アジャイル開発の利点は、無駄なものは作らないので手戻りがほとんど発生しないということです。しかし欠点としては、プロジェクトを始めるときにはいつまでに何ができるのか、誰もわかりません。本当に優秀なアジャイルチームであっても「期間はお約束できませんが、必ずや役に立つ物が出来上がります。トラストミー！」というのが精一杯でしょう。

# どの開発プロセスを選ぶべきか

これらの３つの開発プロセスには、それぞれメリット・デメリットがありますが優劣はありません。プロジェクトの特性に合わせて選ぶべきです。

例えば、新規のゲームエンジンを使った新しいゲーム開発では、反復型開発プロセスが適しているでしょう。とにかく会社を作ってしまったベンチャー企業は、アジャイル開発以外の開発手法には無理があります。すでに作成されたゲームの運営をしている場合は、ウォーターフォールが合うかもしれません。

自分たちの場合、iOS(Swift), Android(Java), サーバー(Ruby on Rails)の組み合わせでアプリ開発を継続して行っています。iOSには１週間位かかる申請が存在するため、アジャイル開発は向かないなーと感じています（最近は１〜２日に短縮されたようですが、それでも向かない）。ちなみに今はプロジェクトメンバー４人で、ウォーターフォール型開発を行っています。つまりリリース機能をスコープとして定義して、WBSで工数を見積もり、ガントチャートを使って予実管理を行っています。プロジェクトの期間は２ヶ月と短いので、いわゆるマイクロウォーターフォールの部類に入るかもしれません。

IT技術にも通じるところはありますが、「○○なんて使っているようでは時代に遅れている」と頭ごなしに非難するのではなく、どれでも使えるようにしておいたうえで状況に応じて適切なものを使い分けられる技術者になるのが、吉かなと思います。開発プロセスに関するフレーム合戦は、端から見ているのは面白いかもしれませんが、当事者になったら得るものはほぼ何もなさそうです。
RxJavaがもうすぐ2.0になる話


昨年RxJava Adavent Calendarというものをやっていて、その中で[RxJava 2.x系の開発](http://qiita.com/kazy/items/8b1e0bcc5cd9638876d4)についてすこし紹介しました。 昨年末では、まだまだ実用段階という雰囲気ではなかった2.xブランチですが、先程レポジトリ覗いたらかなり状況が変わっていたので少しだけまとめました。

https://github.com/ReactiveX/RxJava/tree/2.x

### 2.xの特徴

* continued support for Java 6+ & Android 2.3+
* Reactive Streams compatibility
* performance gains through design changes learned through the 1.x cycle

Reactive Streamsの仕様に準拠したというのが一番大きいですね。Reactive Streamsについては、冒頭でリンクした[エントリ](http://qiita.com/kazy/items/8b1e0bcc5cd9638876d4)をご参照下さい。

### リリーススケジュール

* 2016/08/26: Release Candidate 1
* 2016/09/23: Release Candidate 2
* 2016/10/21: Release Candidate 3
* 2016/10/29: Stable Release: General availability

RC-1のリリースがあと1ヶ月ほどなのを考えると勢いを感じますね。

### なぜ急激に物事が進んだのか

僕はRxJavaのレポジトリを常にウォッチしてたわけではないので正確なことは言えないですが、リードコントリビュータが [Ben Christensen](https://github.com/benjchristensen)から[David Karnok](https://github.com/akarnokd)に変わったことなのかなという雰囲気を感じます。(Davidさんといえばageraのissueで[マジレス](https://github.com/google/agera/issues/20#issuecomment-212007539)されてたのも記憶に新しいですね)
あと当初2.x系はJava 8以上のサポートだったんですが、Java 6+ & Android 2.3+の方針に変更されたのはひとえにJake神による働きかけですね。 Jakeさんは本当に尊い 
[Support API compatibility with Java 6 in 2.x](https://github.com/ReactiveX/RxJava/issues/3450)
2つのファイルにある文を1行ずつ並べて頭に連番を付けたい

# やりたいこと
1.txtには英語、2.txtには日本語が書いてあるんですが、1.txtの1行目と2.txtの1行目を並べたいんです。
こんな大したことないことでアプリをインストールしたりとかしたくないです。

```1.txt
ichiban
niban
sanban
```

```2.txt
いちばん
にばん
さんばん
```

望んでいる結果

```
1. ichiban いちばん
２. niban にばん
3. sanban さんばん
```

ファイル名はこういうかんじに頭に数字がついてたり、名前で並べたとき順に、左から順番につける感じが楽かと思います。

# 解決法

`paste *.txt | cat -n | sed 's/^ *\([0-9]*\)/\1\./' | tr '\t' ' '`

これで出てきた結果をコピペして使うなり、ファイルに書きだすなりします。

コメントで教えてもらいました。@Takeruさんありがとうございました。


## コメントもらうまで試していたちょっと回り道なやつ

連番のデータを別ファイルに用意して単純にくっつける方法
これはこれで後々応用が効きそうなので消さないでおきます。読みにくければ別の記事に分けるかも。

`vim 0.txt` して、`30i.(改行)`して、Escキーをおすと.が30回入力される

*30o.でもいいかなって思ったけど、1行目に余計な改行が入るのが今回まずいのでiにしました

```0.txt
.
.
.
（30行つづく）
```

さいごにいっこ余計な改行をBackspace。

`:%s/^/\=line('.') . ''/`すると、連番になる

```0.txt
1.
2.
3.
（30行つづく）
```

*C-aのインクリメントでもっとお手軽にできそうだったんですがなんかうまく動きませんでした。

`:wq`でvimを保存して終了

あとは以下のコマンドでスペースで句切られて出力されます。
-d オプションを設定しないとタブで区切られます。

`paste -d " " *.txt`


---

参考にしました

[複数ファイルの列データを１ファイルにまとめる - 生物物理計算化学者の雛](http://masa-cbl.hatenadiary.jp/entry/20121202/1354456802)
vimで矩形選択の形状を再利用する

#はじめに
vimの矩形選択で再選択というと大抵`gv`が紹介されますが、これは前回の矩形選択と同じ位置を再選択するコマンドです。
そうではなくて現在のカーソル位置から前回の矩形選択と同じ形で選択したい場合はどうすればいいでしょうか？
検索してもいまいち見つからず、プラグイン作るか、とまで思ったところで[doc](http://vim-jp.org/vimdoc-ja/visual.html#visual-start)を見ると普通に標準で実装されてました…

#やり方
矩形選択モードは`CTRL-V`で入れますが、正確には`[count]CTRL-V`らしいです。ここで`[count]`を省略すると普通の矩形選択モードに、省略せず数値を入れると、「現在のカーソル位置から、前回の矩形選択形状を縦横`count`倍した範囲を選択」となります。
つまり`1CTRL-v`で「現在のカーソル位置から前回の矩形選択形状で選択」ができるということです。
個人的には`gv`はいまいち使わないので

```vim
nnoremap gv 1<C-v>
```

としてしまいました。

#まとめ
vimでやりたいことをがあるとついプラグインとか探してしまいますが、まずdocを読めって話でした。
（しかしこれcount=1以外って使い道有るんですかね？）
【oracle】LISTAGGの代わりにXMLAGGを使う

oracleでは複数レコードの値を1レコードにまとめる際に
LISTAGG関数という便利なものがあります

```
SQL>SELECT * FROM table;

col1  col2
----- --------
key1  val1-1
key1  val1-2
key1  val1-3

SQL>
SELECT col1, 
LISTAGG(col2, '|') WITH IN GROUP(order by col2) list
FROM table
GROUP BY col1;

col1   list
----- ---------
key1   val1-1|val1-2|val1-3

```

ただし、集計するレコード対象が多く、結合結果が4000バイトを超えると
以下のエラーとなってしまいます。

```
ORA-01489: result of string concatenation is too long
```

このためLISTAGG関数を用いる際に4000バイト文字を超える恐れがある場合は
XMLAGG関数を用いた方がいいみたいです。

```
SQL>
SELECT col1,
RTRIM(XMLAGG(XMLELEMENT(e,col2,'|').EXTRACT('//text()')).GetClobVal(),'|') AS list
FROM table
GROUP BY 
col1;

col1    list
-----  -----
key1   val1-1|val1-2|val1-3
```

参考:http://stackoverflow.com/questions/13795220/listagg-function-result-of-string-concatenation-is-too-long
Bundlerについて

Bundlerについて

* 沢山のgemを使うRubyスクリプトを作るときや、使用するgemのバージョンを管理したいとき、Bundlerを使うと便利です。


1. bundlerをインストールします。

    ```rb
    gem install bundler
    ```

2. インストール出来たら、Gemfileのひな型を作成します。

    ```
    bundle init
    ```

1. 実行したディレクトリにGemfileが作成されます。こんな感じで使うgemを列挙します。

    ```rb
    # frozen_string_literal: true
    # ZeroSimAlert Gemfile
    source "https://rubygems.org"
      
    gem "mechanize"
    gem "nokogiri"
    gem "sqlite3"
    gem "mail"
    gem "activesupport"
    ```

1.  列挙したら、インストールしてみます。

    ```rb
    bundle install
    ```
SwiftからObjective-Cのenum型を使うときの注意メモ

SwiftからObjective-CのEnumを利用することはできますが、
微妙にObjective-Cの頃とは使い方が変わっているのでそのままでは使えません。

例えばこんな適当なEnum型をObjective-C側に書きます。

```objc:objective-C
typedef NS_ENUM(NSInteger, APIState) {
    APIStateSuccess = 0,
    APIStateFailure = 1,
    APIStateUnknown = 0xff
};
```

それをSwift側でそのままSwitch文に使おうとこんな感じに書いてしまうと・・・

```swift:swift-error
let state = 1;
switch state {
case APIState.Success:
    break
case APIState.Failure:
    break;
default:
    break;
}
```

以下のどちらかのようなエラーが出てくると思います。

```
Enum case 'APIState' is not a member of type 'Int'

Cannot convert value of type 'APIState' to expected argument type 'Int'
```

Int値を使うときは、rawValueプロパティを利用しましょう。

```swift:swift-error
let state = 1;
switch state {
case APIState.Success.rawValue:
    break
case APIState.Failure.rawValue:
    break;
default:
    break;
}
```

この場合、逆にInt値からEnum型に変換することもできます。

```
var type1 = APIState(rawValue: 0)
var type2 = APIState(rawValue: 1)
var type3 = APIState(rawValue: 2) // 変換できなければnil
```
Debian系のディストリビューションでパッケージがインストールされているか調べたい

### 目視確認の場合

人間がコンソールで目視確認する場合、普通は以下の通りにdpkg-queryコマンドを使うと思います。

```
dpkg-query -l パッケージ名
```

例えばこんな感じ。

```
 % dpkg-query -l git
要望=(U)不明/(I)インストール/(R)削除/(P)完全削除/(H)保持
| 状態=(N)無/(I)インストール済/(C)設定/(U)展開/(F)設定失敗/(H)半インストール/(W)トリガ待ち/(T)トリガ保留
|/ エラー?=(空欄)無/(R)要再インストール (状態,エラーの大文字=異常)
||/ 名前           バージョン   アーキテクチ 説明
+++-==============-============-============-=================================
ii  git            1:1.9.1-1ubu amd64        fast, scalable, distributed revis
```

パッケージ名の左側に書かれた文字「ii」は、ヘッダ部の説明の通り「インストール要求されて、無事にインストールが終わっている」という意味です。

### スクリプトから使いたい場合
でも、シェルスクリプトで上記の表示結果をそのまま扱うのはいささか面倒です。表示されるパッケージが1種類ならtailコマンドで切り出すことは容易ですが、複数行あると意外と面倒です。

こんなときは、以下のdpkg-queryコマンドを試してみましょう。

```
dpkg -W -f='表示フォーマット' パッケージ名
```

「表示フォーマット」で表示できる情報については、man dpkg-query見ると載っていますので割愛します。
この表示フォーマットのおかげで、文字列加工が大変楽です。

例えば、あるパッケージがインストールされているかどうか確認したい場合、以下のようにすれば良いと思われます。
なお、${Status}はシェル変数でなく、表示フォーマットの一つで「パッケージの状態」を示します。


```
% dpkg-query -W -f='${Status}\n' chromium-browser | awk '{print $3}'
not-installed

% dpkg-query -W -f='${Status}\n' git | awk '{print $3}'
installed
```
これで、スクリプト書くのが楽になります。
Raspberry Pi 3 のインストール メモ

#Raspberry Pi 3 のインストール メモ

初カキコ...ども。
ラスパイ買ったのでその環境構築メモ

準備作業はMacOSX(El Capitan)環境で行った。
オフライン環境でRasbianだけインストールする。

##用意するもの
　・Raspberry Pi 3
　・SDカード(64G)
　・ACアダプタ(5V、2.5A)
　・HDMIケーブル
　・マウス、キーボード

##手順
###1. Noobsの取得:
　https://www.raspberrypi.org/downloads/noobs/
　[Download Zip] よりZipファイルをダウンロード

###2. SDカードフォーマッターの取得：
　https://www.sdcard.org/jp/downloads/formatter_4/
　私の場合は[Mac用]を選択して[同意します]でダウンロード

###3. SDカードフォーマッターをインストール・起動
　SDカードを挿入すると自動で選択される（はず）。
　対象SDを確認した上で[上書きフォーマット]でフォーマット。
　名前はなんでもOKかと。

###4. ダウンロードしたNoobsフォルダの中身をコピー
　「〜.dtb」のある階層からフォーマットしたSDカードへコピーする。


###5. RaspberryPiに色々接続
　SDカード、HDMIケーブル、マウス、キーボードを差して最後にACアダプタを電源へ接続！
　あとは出力先ディスプレイにNoobsインストーラが起動する。

###6. Rasbianインストール
　[Rasbian]にチェックを入れて[install]すれば終わり。
　あとは必要に応じてネットワークの設定や言語（日本語は文字化けするとの噂があるのでEnglishで）、キーボード(私は「jp」を選択)を設定する。

　最後に「OS(es) Installed Successfully」が表示されればOK。
　再起動されてGUIが起動する。

初期ユーザ名は「pi」、パスワードは「raspberry」。

おわり。
PHP7.0+mecabでハマった事

**PHP7.0でmecabを動かそうとすると以下エラーが出る。**
> PHP Fatal error:  Uncaught Error: Call to undefined function mecab_split()

と出てくる。

PHP7で使う場合は

mecab_split() ではなく \MeCab\split() に変更されている

そして、MeCab_Taggerも変更が必要だったりもする。

> Fatal error: Uncaught Error: Class 'MeCab_Tagger' not found
// $mecab = new MeCab_Tagger(); // php5.6
$mecab = new \MeCab\Tagger(); // php7

他にも細かな部分があるので、まとめていきたいと思います。
PHPでオブジェクト指向　用語と使い方


# インスタンス
1. インスタンス生成は**new**
2. **メンバ** = フィールド＋メソッド
3. インスタンスは**独立**
4. ~~メソッドは**参照渡し**~~
5. メソッドには参照渡し、値渡しがある[[詳細](http://qiita.com/mpyw/items/bd38da57837d35214aae)]
※mpywさんありがとうございます！

ざっくりまとめ

|引数の型|渡し方|メソッド内：値変更可否|メソッド内：参照変更可否|
|:----:|:----:|:----:|:----:|
|変数|値渡し|x|x|
|変数|参照渡し（&）|x|x|
|array|値渡し|x|x|
|array|参照渡し（&）|x|o|
|Object|値渡し|o|o|
|Object|参照渡し（&）|o|x|


```
class Product
{
    // フィールド
    private $hoge

    // メソッド
    public function bizz()
    {
        return $this->hoge;
    }
}

$product = new Product();
$product->bizz();
```

# コンストラクタ
1. **インスタンス生成時**に実行
2. 基本は**public**

```
class Product
{
    public function __construct()
    {
    }
}
```

# カプセル化
1. **private**で宣言
2. 外部との結びつきを**弱める**リファクタリングを容易化
3. 外部からの改悪に対して必要最低限の公開が目的

# 継承
1. クラスの**フィールドとメソッド**を引き継ぐ
2. **private**は引き継がれない
3. **protected**は継承先のクラスでのみ参照可能
4. 継承は**extends**
5. 類似クラスはコピペではなく、**保守**を考えて継承

```
class ParentProduct
{
    protected $hoge
    private function $bizz()
    {
    }
}

class Product extends ParentProduct
{
    private function $bizzbizz()
    {
    }
}
```

# オーバーライド
1. 親クラスと同一名でメソッドの**上書き**
2. 親クラスのメソッド呼び出しには**parent::メソッド名**

# 静的メンバ
1. スタティック（静的）メンバ
2. 「public **static** メソッド/フィールド」で宣言
3. 呼び出しは「クラス名::メソッド/$フィールド」
4. インスタンス化**不可**
5. **シングルトン**はコンストラクタをprivateとして自己呼び出し
6. 自己呼び出しには「self()/self::$フィールド名」

# 定数
1. 定数「define(定数名、値)」
2. クラス定数「const 定数名=値」
3. 他クラスよりクラス定数参照「クラス名::定数名」
4. クラス内参照「self::定数名」

# 抽象クラス
1. 継承しないと**使用不可**
2. 抽象メソッドは必ず**オーバーラード**する
3. 生成は**abstract**（クラス/メソッド）
4. 継承は**extends**
5. **多重実装不可**

# インターフェース
1. 定義は抽象メソッドのみ = 全て**オーバーライド**
2. 抽象クラスの定義にabstractは不要だが必ず**public**
3. 生成は**interface(クラスのみ)
4. 継承は***implements*
5. **多重実装可**

# ポリモーフィズム
1. 同一名のメソッドによる処理
2. 型の曖昧さをなくすのが**タイプヒンティング**
3. 条件分岐をクラス名で変えてしまう
4. インターフェースの多重実装と同等の意

```
// タイプヒンティング例
//  Bizzクラスしか処理しない
public function hoge(Bizz $bizzbizz)
{
    $product->bizz()
    $this->products[] = $product;
}
```

# 例外処理
1. PHPは自動で例外を投げない
2. throw new Exception()で投げる

```
try{
    throw new Exception();
} catch(Exception $e) {
}
CentOS7.xにyumでNginx(安定版)を導入する

yumのレポジトリーを登録する

```vim:/etc/yum.repos.d/nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1
```

後はyumでinstall

```bash
sudo yum -y install nginx
```

以上！
JavaScriptはhead内で読み込みたい

JavaScriptの読み込み位置に関する考察。
他にも幾つか似たような記事はあるが、自分なりにまとめてみます。

#基本構造
読み込み位置には下記の2つの位置があります。

- bodyタグの最後
- headタグ内

#最近のスタンダード
最近のスタンダードはbody末尾での読み込みらしいです。
理由は以下の様な感じ。

**1. Webページの表示速度を早くするため**
JavaScriptの最初に読み込むと並列読み込みの妨げになり読み込み速度が遅くなる。

**2. DOMの読み込み待ちたい**
DOMreadyを前提にしている処理がある場合、DOMの読み込みが完了してから実行したい。

#head内で読み込みたい
僕はスタンダードを盲信していました。
しかし、最近僕の周辺で「JavaScriptはhead内で読み込もう」という声をよく聞くようになりました。

そこで自分でもいろいろ考えてみた結果、「head内で読み込みたい」と思うようになりました。

理由は下記の通り。

**1. スクロールイベントなどがあるとガクつく**
DOMを読み込んでからJavaScriptを読み込むので、表示が完了してからJavaScriptが実行されるまでラグがあります。
その間にスクロールなどのイベントが作動すると、読み込みが完了していないのでアニメーションなどがうまく表示されません（メニューの固定とか）。

**2. DOMreadyが必要じゃない処理もある**
全ての処理でDOMreadyが必要ではないはずで、DOMが読み込まれる前に読み込みたいJavaScriptもあるはずです。
そんな時、そういうJavaScriptだけhead内で読み込むようにすると、scriptタグが分散してしまいメンテしにくくなります。

ちなみにDOMreadyが必要な処理も下記のように書くことで.readyを省略しhead内で読み込むことができます。

```js
(function($, undefined){
//処理
}(jQuery);
```

第二引数にundefinedを指定することで、DOMが読み込まれていない時もエラーになりません。

**3. async属性使える**
HTML5ではasync属性が使えるので、簡単にスクリプトを非同期で読み込むことが出来ます。
これでレンダリング速度の問題は解決します。

#結論
head内で読み込もう。
Vimの組み込み関数一覧をソースコードから取得するまでの過程

組み込み関数の一覧をソースコードから抽出するまでの過程を記します。
Vimのソースコードから組み込み関数を取得するサンプルコードを最後に載せてます。
サンプルコードだけ確認したい場合は[その他](#その他)だけ読んでください。



## 過程

Vimのソースコードをgitで取得します。

```bash
git clone --depth 1 https://github.com/vim/vim.git
```

カレントディレクトリに**vim**というディレクトリが出来ました。
ソースコードのディレクトリに移動します。

```
cd vim
```

次に、組み込み関数がどこのファイルに書かれているのか調べます。
VimはC言語で書かれているので拡張子cに絞って探してみます。
組み込み関数の**hasmapto**をキーワードにしてヒットするファイルを探してみます。

```bash
find -type f -name "*.c" | xargs grep "hasmapto"
```

4件ヒットしました。
**src/eval.c**に**hasmapto**が載っていることが分かりました。(Vim 7.4.2031の場合)

```bash:結果
./src/eval.c:static void f_hasmapto(typval_T *argvars, typval_T *rettv);
./src/eval.c:    {"hasmapto",   1, 3, f_hasmapto},
./src/eval.c: * "hasmapto()" function
./src/eval.c:f_hasmapto(typval_T *argvars, typval_T *rettv)
```

**src/eval.c**をvimで開いて確認してみます。

```bash
vim src/eval.c
```

**hasmapto**を検索してみます。
ノーマルモードで次の通りにキーを入力します。

```
/hasmapto
```

**hasmapto**という文字列がある行にカーソルが移動しました。

```
static void f_hasmapto(typval_T *argvars, typval_T *rettv);
```

カーソル行の前後も似たような形式で書かれていました。
もしかしたら**static void f_**がある行を抽出したら組み込み関数が取れるのではないかと推測しました。

一旦、Vimを閉じます。

```vim
:q
```

grepで**src/eval.c**から**static void f_**が書かれている行を抽出してみます。


```bash
grep "static void f_" src/eval.c
```

ターミナル上に大量の文字列が流れてきました。
目視で数えるには量が多いです。
次のコマンドを実行して件数を調べたら334件でした。(Vim 7.4.2031の場合)

```bash
grep -c "static void f_" src/eval.c
```

英語が苦手なのでいつもVim日本語ドキュメントを辞書代わりに確認してました。
今回ソースコードから抽出することによってsetfperm()とかwin_id2win()とかwin_gotoid()とかtest_settime()とか他にも初見の組み込み関数に巡り会えた事に喜びを感じました。


## その他

eval.cから抽出した内容を加工して、関数名のみ並べるVim scriptのサンプルです。

```vim:sample.vim
:%!grep "static void f_" src/eval.c
:%s/^.\+f_\(.\+\)(.*/\1/g
```

引数-S sample.vimを付けてVimを起動します。
-Sは大文字のSです。

```vim -S sample.vim```
goでmicroserviceをつくる


# はじめに
最近、microserviceを作ったのだが、
microserviceならgolangがいいよね、
みたいな風潮があるので、流れに乗っかってgolangで書き直している。

メイン業務ではないので、手が空いたときに少しづつ進めている感じ。
現在変換している部分は、各アカウントが持っているリソースを取得する部分。

# プロジェクト概要

大体やりたいこととしては、以下のように簡単な処理
1. 既存のアカウント管理APIに接続し、認証
2. 認証が通れば、セッションを付与
3. セッションを元に、そのアカウントの権限の範囲でリソース情報を取得する
4. リソース情報がなければ、デフォルトのリソースを作成

# レポジトリ
https://github.com/tomoyamachi/platform_points
※ privateにする可能性あり

# 現在できているところ
- MySQLへの入出力
- セッションの保存
- 既存のAPIに接続して、ログイン情報を取得
- セッションから、そのユーザの情報を取得する
- 以上の部分までの、結合テスト

# ミドルウェアとかパッケージ

- FRAMEWORK :  echo
- DB : MySQL
- キャッシュ(セッション管理で利用) : redis
- 構成管理 : glide
- 単体テスト : unittest (まだ導入できていない)
- 統合テスト : cucumber

# ディレクトリ構成

```
$GOPATH/src/project
|--apps
|  |--v1     <- リソース名 ※ この階層ごとにパッケージを作成する
|     |--main.go
|     |--resource          <- MVCでいうところのController
|     |--route             <- Router
|--conf                    <- 設定ファイル(DBの向き先など)
|--db                      <- DBへの接続
|--features                <- 結合テストファイル
|--glide.yaml              <- 構成管理ファイル
|--middleware              <- ラッパーファイル置き場
|--model                   <- MVCでいうところのmodel
|--sql                     <- テーブル作成SQL (migration未導入)
|--vendor                  <- glideでインストールされたファイルが入る場所
```


# 自動ビルド設定
ファイルの更新があれば、自動的にビルドされてほしかった。
現状、fswatchを利用している。

```
$ brew install fswatch
$ cd <projectpath>
$ fswatch -o . | xargs -n1 -I{} go run apps/v1/main.go
```

# 今後やること
- コード規約チェック
- migrationの導入
- 単体テストの作成
- 結合テストの追加
- docker環境での稼働
- そもそもこのプロジェクト構成でいいのかを確認

※ 進捗があれば、この記事を更新していく
haproxyをコマンドラインで操作



## socatのインストール(debian)

```
apt-get install socat
```

socat = ソケット関連の操作を行うことができるようになるコマンド

## haproxyの設定

※ 現状のlilimoの設定だと、変更する必要ありません

https://worklog.be/archives/2300#i-14


## コマンド

### ステータスの確認

```
$ echo "show stat" | socat stdio /run/haproxy/admin.sock | grep web001
```


#### 正常時

```
www-backend,web001,0,0,0,1,8192,49,46158,13083,,0,,0,0,0,0,UP,1,1,0,1,1,165,2731,,1,3,1,,49,,2,0,,6,L7OK,200,4,0,49,0,0,0,0,0,,,,0,0,,,,,3123,OK ,,0,1,1,79,
```

#### 異常時

```
www-backend,web001,0,0,0,1,8192,49,46158,13083,,0,,0,0,0,0,DOWN,1,1,0,2,2,2,2733,,1,3,1,,49,,2,0,,6,L7STS,502,2,0,49,0,0,0,0,0,,,,0,0,,,,,3180,Bad Gateway,,0,1,1,79,
```


### メンテナンスモード

メンテナンスモードにすることによって、haproxy側で特定のサーバを切り離すことができる
片方のサーバで見れないなどのダウンタイムがなくなる

#### 実行

```
$ echo "disable server www-backend/web002" | socat stdio /run/haproxy/admin.sock
```

#### 解除

```
$ echo "enable server www-backend/web002" | socat stdio /run/haproxy/admin.sock
```

## メンテナンスモード時の画面表示


### 正常時

[![](https://image.docbase.io/uploads/88a8905a-71b0-4b12-b5bb-f7c1ecd405f2.png)](https://image.docbase.io/uploads/88a8905a-71b0-4b12-b5bb-f7c1ecd405f2.png)

### メンテナンスモード時

表示の色が茶色になる

[![](https://image.docbase.io/uploads/fdc55938-2d6e-46b3-a42f-7579a153650b.png)](https://image.docbase.io/uploads/fdc55938-2d6e-46b3-a42f-7579a153650b.png)


## デプロイ時の流れ


1. メンテナンスモードにする
1. haproxyとサーバが切り離されたことを確認する
1. webサーバなどを再起動する
1. メンテナンスモードを解除する
1. メンテナンスモードが終り、haproxyとサーバが疎通したら次のサーバへ
git コマンド tips


# reset

わかりやすい参考記事
resetを使う前に目を通しておくとわかりやすい
http://qiita.com/shuntaro_tamura/items/db1aef9cf9d78db50ffe


##### ※`git reset`コマンドは、他の人のソースを破壊するおそれがあるので、使い方に非常に気をつけてください

`git reset`したあとはpushすると危険なので、気をつける


## 間違えてaddしたとき

addされていない状態になります
ファイルは変更されたままです

```git
git reset
```


## ローカルで間違えてcommitした場合

※対象のcommitをpushした場合は、下記のコマンドは使用すると危険な場合があります


```
git reset --soft HEAD^
```




## 過去の状態に戻す（障害発生時や、過去の状態での確認など）

hash値は`git log`などで確認します
下記に説明があります


```git
git reset hash値
```


#### git logでコミットのハッシュ値を取得する

`git log`を入力する
`--oneline`を入力するとコメントと英数字（SHA-1）のみが表示される

```
// 下記のいずれかを入力する

$ git log
$ git log --oneline
```

下記のように表示される
戻りたい地点の英数字をコピーする
コメントを見ながら戻りたい地点を探す

##### git log

`commit`の横の数字と英字の羅列をコピーする（下の例だと`0e76c1d24ba7458a8d69eb58c1c5729cb6c94e40`）

```
commit 0e76c1d24ba7458a8d69eb58c1c5729cb6c94e40
Merge: 04efb38 55c2e8b
Author: Kunio Takahashi <Ducks@Kunio-no-MacBook-Pro.local>
Date:   Mon Nov 30 18:14:05 2015 +0900

    Merge branch 'master' into dev-check

```

##### git log --oneline

数字と英字の羅列をコピーする（下の例だと`0e76c1d`）

```
0e76c1d Merge branch 'master' into dev-check
```


下記のコマンドで戻る

```
// git reset hash値
$ git reset 0e76c1d24ba7458a8d69eb58c1c5729cb6c94e40
```

ログを再び見ると、そのcommitまで戻り、ファイルがその時の状態にもどっている

#### resetしたファイルを最新の状態にもどす

自分が使っているブランチが`master`の場合は下記のようにする
`master`の部分は自分が使用しているブランチ名に変更する

下記のコマンドは`git pull`でも大丈夫だが、その場合は他の人が`push`したリモートのファイルも含まれるので注意する

```
$ git merge origin/master
```
RでAM変調、復調

#概要
RでAM変調、復調やってみた。
復調は、直交復調です。
#写真
![iq.png](https://qiita-image-store.s3.amazonaws.com/0/18104/5be9e644-c682-b3be-a50a-d230e29426b1.png)

#サンプルコード
```
par(mfrow = c(3, 1))
lpf <- function(i, samplerate, freq, x) {
	o <- (sin(2 * pi * 110 * x) + 0.5 * sin(2 * pi * 440 * x)) / 2
	q <- 1
	omega <- 2 * pi * freq / samplerate
	alpha <- sin(omega) / (2 * q)
	a0 <-  1 + alpha
	a1 <- -2 * cos(omega)
	a2 <-  1 - alpha
	b0 <- (1 - cos(omega)) / 2
	b1 <-  1 - cos(omega)
	b2 <- (1 - cos(omega)) / 2
	in2 <- 0
	in1 <- 0
	out2 <- 0
	out1 <- 0
	for (j in seq(length(i)))
	{
		o[j] <- b0 / a0 * i[j] + b1 / a0 * in1 + b2 / a0 * in2 - a1 / a0 * out1 - a2 / a0 * out2
		in2 <- in1;
		in1 <- i[j];
		out2 <- out1;
		out1 <- o[j];
	}
	return(o)
}
N <- 10000
t <- 1:N / N
C <- 1
fc <- 30
A <- 0.7
fs <- 3
fl <- 20
cutoff <- 15
Vin <- sin(2 * pi * fs * t)
plot(Vin)
Vam <- (A * sin(2 * pi * fs * t) + C) * sin(2 * pi * fc * t)
plot(Vam)
Q <- Vam * cos(2 * pi * fl * t)
I <- Vam * sin(2 * pi * fl * t)
Q2 <- lpf(Q, N, cutoff, t)
I2 <- lpf(I, N, cutoff, t)
Vdm <- sqrt(Q2 * Q2 + I2 * I2)
Vout <- lpf(Vdm, N, 10, t)
plot(Vout)

```
MacでEmscripten導入


## この記事は?
MacでEmscriptenを使えるところまでを紹介します。個人的なメモ用にも。

## Emscriptenとは？
EmscriptenはC/C++言語からLLVMを生成し、それをJavaScriptに変換するコンパイラのことらしいです。qiitaの中でも[ちらほら記事](https://qiita.com/tags/emscripten)があります。

## 実装環境
Mac OS 10.10.5で導入しました。Yosemiteの最新版です。


## インストール
環境構築はいくつかやり方があるようですが、僕が試したのは下記の方法です。

### Portable Emscripten SDK for Linux and OS Xをダウンロード
[Portable Emscripten SDK for Linux and OS X](https://kripken.github.io/emscripten-site/docs/getting_started/downloads.html)を公式サイトからダウンロードします。

解凍後、お好きな場所に移動します。

### ターミナルでコマンドを実行
ターミナルを開き、先ほど解凍したディレクトリに移動します。
以下のコマンドを順番に実行します。ここは若干時間がかかります。

```bash
/emsdk update
```

ここでpythonのエラーが起きる場合があります。以前Canopyを試されたりしていると起きる人が多いようです。
解決方法はネット状にたくさんあるのでそちらを参考してください。僕の場合はCanopyを再インストールで解決しました。

```bash
./emsdk install latest
```

```bash
./emsdk activate latest
```

これで完了です。

### コンパイルを試す
emsdk_portableディレクトリ内でmain.cかmain.cppのファイルを用意します。

適当なコードを記入してもらいます。
ファイル作成が完了後、Emscriptenでコンパイルします。
今回はmain.cppで試しました。
コードはシンプルに、hello worldです。

```cpp
#include <iostream>
using namespace std;

int main() {
    cout << "Hello World" << endl;
    return 0;
}
```


それでは、Emscrptenを実行します。

```bash
emcc main.cpp -o index.html
```

これでディレクトリ内にindex.htmlが作成されます。またindex.jsもあります。


### index.htmlを確認する。
以下の画像のように、hello worldが出力されるのが確認できると思います。

![スクリーンショット 2016-07-13 20.34.08.png](https://qiita-image-store.s3.amazonaws.com/0/15535/7d4722e8-b13c-cdff-e987-37372aa8c1ec.png "スクリーンショット 2016-07-13 20.34.08.png")


できました。まずはここまでです。
SlackのAPI、webhookをgolangで試した

## Slack API、webhook使い方
####　API TOKEN 取得方法
 
　https://api.slack.com/docs/oauth-test-tokens
　でトークンを取得する。

---

####　Webhook TOKEN 取得方法

　https://api.slack.com/incoming-webhooks
　でトークンを取得する

---

##### curl でsend message できる
```curlで実行の例
curl -XPOST "https://slack.com/api/chat.postMessage?token=<TOKEN>&channel=%23general&text=Hello%20@bot_server&username=test_bot"

curl -XPOST -d "token=<TOKEN>" -d "channel=#general" -d "text=Hello @bot_server" -d "username=test_bot" "https://slack.com/api/chat.postMessage"

```

---

#### いろんなAPI
 https://api.slack.com/methods
 使いきれない。。。

---

## golangで試す
1. API

---

```slack_api.go
package main

import (
        "bytes"
        "net/http"
        "net/url"
        "fmt"
        "os"
)

var(
        token  string = "tokenxxxx-xxxxxxxxxxxx" // change token 
        apiUrl string = "https://slack.com/api/chat.postMessage"
)


func main() {
        arg := os.Args[1:]
        data := url.Values{}
        data.Set("token",token)
        data.Add("channel","#general")  // change channel
        data.Add("username","testBot")
        data.Add("text", fmt.Sprintf("%s",arg))

        client := &http.Client{}
        r, _ := http.NewRequest("POST",  fmt.Sprintf("%s",apiUrl), bytes.NewBufferString(data.Encode()))
        r.Header.Add("Content-Type", "application/x-www-form-urlencoded")

        resp, _ := client.Do(r)
        fmt.Println(resp.Status)
}

```
**実行**
> ./slack_api this is test!
> 200

---

```slack_webhook.go
package main

import (
    "encoding/json"
    "io/ioutil"
    "net/http"
    "net/url"
    "os"
    "fmt"
)

var(
     // change token 
    IncomingUrl string = "https://hooks.slack.com/services/xxxxxxxxxxxx/xxxxxxxxxxxx/xxxxxxxxx"
)

type Slack struct {
    Text        string `json:"text"`
    Username    string `json:"username"`
    Icon_emoji  string `json:"icon_emoji"`
    Icon_url    string `json:"icon_url"`
    Channel     string `json:"channel"`
}

func main() {
    arg := os.Args[1:]
    params, _ := json.Marshal(Slack{
        fmt.Sprintf("%s",arg),
        "MyBot",
        "",
        "http://www.icons101.com/icons/66/NuoveXT_by_Alexandre_Moore/128/slackware.png",
        "#general"})

    resp, _ := http.PostForm(
        IncomingUrl,
        url.Values{"payload": {string(params)}},
    )

    body, _ := ioutil.ReadAll(resp.Body)
    defer resp.Body.Close()

    println(string(body))
}

```
**実行**
> ./slack_webhook this is test!
> 200 ok
Elasticsearchで、正規表現での検索結果が思い通りにならなかったことへの対応


Elasticsearch、とても良いですね。
実際に使ってみて、思いついた条件でログをすぐに分析できる素晴らしさを知りました。


以下本題。

# 前提環境
- Elasticsearch 2.3.4
- Kibana 4.5.2
- Fluentd 2.3.1
- nginx 

nginxのLTSVなログをFluentdでElasticsearchに流し込み、
Kibanaで見るという、よくありそうな構成です。

# UAが思い通りに検索できない！
Kibana上で、特定のUAを持ったログを検索したいとおもい、下記のようなクエリを投げました。

- 検索したいログの例

```js:見つけたいログ(少し改変しています）
ua:PlayStation Vita Dummy Dummy (PS Vita)
```

- 検索クエリ

```perl:クエリ（NG）
 ua:/.*Vita.*/
```

しかし***検索結果が出ない！おかしい！***
そこで、下記のように少しクエリを変えました。

```perl:クエリ（OK）
 ua:/.*ita.*/
```

これだと検索結果に正常に出てきます。
正規表現的には、どちらでも見つかるはずですが・・・。


# Elasticsearchの設定
下記のようなindex templateを登録しています。

```json:index_template
{
  "order": 0,
  "template": "*",
  "settings": {},
  "mappings": {
    "_default_": {
      "_source": {
        "enabled": true
      },
      "dynamic_templates": [
        {
          "string_template": {
            "mapping": {
              "index": "not_analyzed",
              "type": "string"
            },
            "match_mapping_type": "string",
            "match": "*"
          }
        }
      ],
      "properties": {
        "@timestamp": {
          "index": "not_analyzed",
          "type": "date"
        }
      }
    }
  },
  "aliases": {}
}
```

文字列の検索時にうまいこと検索できると思い、indexにはnot_analyzedを指定していました。

# 変更後
調べてみると、検索時のanalyzerが影響をしていそうでした。
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-analyzer.html

そこで、今回は、下記のようなsettingをテンプレートに追加し、

```json:index_template(settings)
{
  "order": 0,
  "template": "*",
  "settings": {
    "index": {
      "analysis": {
        "analyzer": {
          "tabAnalyzer": {
            "type": "pattern",
            "pattern": "\t"
          }
        }
      }
    }
  }
```

mappingsのテンプレートを下記のように変更しました

- not_analyzedをanalyzedに変更
- analyzerを、settingsで定義した「tabAnalyzer」に変更

```json:index_template(mappings)
{
  "order": 0,
  "template": "*",
  "settings": {},
  "mappings": {
    "_default_": {
      "_source": {
        "enabled": true
      },
      "dynamic_templates": [
        {
          "string_template": {
            "mapping": {
              "index": "analyzed",
              "analyzer": "tabAnalyzer", 
              "type": "string"
            },
            "match_mapping_type": "string",
            "match": "*"
          }
        }
      ],
      "properties": {
        "@timestamp": {
          "index": "not_analyzed",
          "type": "date"
        }
      }
    }
  }
}
```

# 変更後の検索結果
先ほどと同じ、下記クエリを投げると・・・

```perl:クエリ
 ua:/.*Vita.*/
```

今度は予想通りの検索結果が帰ってきました！


# その他
[検索時に、analyzerを指定出来る](http://qiita.com/yamadagenki/items/15cd190dc4e0f1b3e3fa#%E6%A4%9C%E7%B4%A2%E5%81%B4%E3%81%AE%E3%82%AF%E3%82%A8%E3%83%AA%E3%81%ABanalyzer%E3%82%92%E6%8C%87%E5%AE%9A%E3%81%99%E3%82%8B)のですが、それでも解決できた問題なのかもしれません（未調査）。
Ruby | ハッシュの中のハッシュの中に配列を作る

# 問題

ネストしたハッシュの中で配列を扱いたい
なおかつその配列に、いきなり .push とかしたい。

こんな感じで。

```rb
nested = {}

nested[:a][:b].push :c
nested[:a][:b].push :d

puts nested # => {:a=>{:b=>[:c, :d]}}
```

# 解決

```rb
nested = Hash.new do |h1,k1|
  h1[k1] = Hash.new do |h2,k2|
    h2[k2] = []
  end
end
```

```rb
nested[:a][:b].push(:c)
nested[:a][:b].push(:d)

puts nested # => {:a=>{:b=>[:c, :d]}}
```

# 環境

- ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15]

# 参考

- http://stackoverflow.com/questions/5544858/accessing-elements-of-nested-hashes-in-ruby








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
kinesis-agentを使って、Kinesis Streamsにデータを送る

Kinesisを使おうとして、Producerにfluentd以外に
最近「Kinesis エージェント」というものがある事を知ったので試してみる。

## エージェントインストール

http://docs.aws.amazon.com/ja_jp/kinesis/latest/dev/writing-with-agents.html
こちらを参考にして進めたが、若干分かりづらい所もあったのでメモする。

アプリケーションサーバ(EC2)に、エージェントをインストールする。

```
sudo yum install –y aws-kinesis-agent
```

## エージェント設定

/etc/aws-kinesis/agent.json
を編集する。

```
{
  "cloudwatch.emitMetrics": true,
  "cloudwatch.endpoint": "monitoring.ap-northeast-1.amazonaws.com",
  "kinesis.endpoint": "https://kinesis.ap-northeast-1.amazonaws.com",
  "awsAccessKeyId": "ACCESSKEY",
  "awsSecretAccessKey": "SECRETKEY",
  "flows": [
    {
      "filePattern": "/tmp/app.log*",
      "kinesisStream": "yourkinesisstream"
    }
  ]
}
```


- `kinesis.endpoint` を設定していないと、ログに下記の内容が出力されてパースまでは行うが送信しないで終わる。  

    ```
    XXX records parsed (XXX bytes), and 0 records sent successfully to destinations
    ```

- `cloudwatch.emitMetrics` `cloudwatch.endpoint` を設定しておけば
    CloudWatchのカスタムメトリクスという所に、AWSKinesisAgentという項目が選択出来るようになって
    BytesSent、RecordSendAttempts、RecordSendErrors、ServiceErrorsなどのメトリクスが取れる。
    http://docs.aws.amazon.com/ja_jp/kinesis/latest/dev/agent-health.html

- awsAccessKeyIdで設定したユーザには、AmazonKinesisFullAccessのようなポリシー権限が必要。

## エージェント実行

/etc/aws-kinesis/agent.json
のケツカンマに注意して、編集が終わったらサービスを起動する。

```
sudo service aws-kinesis-agent start
```

/var/log/aws-kinesis-agent/aws-kinesis-agent.log
ここにログが出力される。

Kinesis Streamsの設定は省略したけど
ストリーム名と、シャード数の設定だけなので、そんなにハマるポイントはない。

Happy Kinesising!!
【Windows7】ハイバネーション機能の無効化

# **ハイバネーション？？**
- ハイバネーションファイル(hiberfil.sys)とは、パソコンを休止状態にする際、メモリー内のデータを一時的にハードディスクドライブへ保存するための予約領域
- 休止状態を使わない場合、ハイバネーション機能を無効に設定することでディスク領域が増える

# **手順**
## **`hiberfil.sys`の確認**
### フォルダーオプションの「保護されたオペレーティングシステムファイルを表示しない」のチェックを外す
![WS000416.png](https://qiita-image-store.s3.amazonaws.com/0/79134/d46a835f-84be-ad12-7d3d-923cdb32a333.png)

### Cドライブ直下の`hiberfil.sys`ファイルの容量を確認
![WS000417.png](https://qiita-image-store.s3.amazonaws.com/0/79134/6cc2621e-8941-565b-323c-860f9fa13b47.png)


**約6GB**

## **コマンドプロンプトでハイバネーション機能をOFFにする**
```text
C:\Users\admin>powercfg.exe /hibernate off
```

## **ディスク容量の確認**
### 設定前
![WS000418.png](https://qiita-image-store.s3.amazonaws.com/0/79134/018e1b50-c1a8-ddc5-28df-77e7ff40e895.png)


### 設定後
![WS000419.png](https://qiita-image-store.s3.amazonaws.com/0/79134/a57f4aff-61fa-658b-1047-f203f76ddd63.png)


# **おわりに**
実はこの機能自体知らなかったのですが、丁度SSDへ換装していたら上司からそういうことができるということでやってみた次第でありんす！
Chainer v1.11.0にTrainer追加

#Chainer v1.11.0の追加
Chainer v1.10.0 ⇒ v1.11.0にて公式twitter では

```
データセットと訓練ループの抽象化 (Trainer) をサポートしました。
多くのケースで自分でfor文を回さなくても訓練・テストができるようになりました。
```
とあり、mnistのサンプルも短くなったようです。


2016/07/02に行われたChainer meetup #3ではPFNの開発者の方より
Trainerについて説明[(スライドp11～)](http://www.slideshare.net/beam2d/chainer-update-v180-v1100)がありました。

ざっくり言えば、例えばmnist中で訓練ループを回すときにデータをシャッフルしてミニバッチを作って流して
オプティマイザをアップデートする部分のコードは長いのでそれをTrainer（トレーナー）にお任せする
という感じでした。

また、Trainerは新しい機能なので今までのコードが動かなくなるわけではなく
今までどおり自分でforループを回して使っても問題はないとのことでした。


まだアップデートしただけなので、とりあえずこれから試していきたいと思います。
Python3.5 + NumPy + SciPy をWindows10にインストールして動かす

#はじめに
Pythonを全く触ったことがない初心者がPython + SciPyをインストールして動かそうとしたところ、いろいろとハマったので、備忘録もかねてインストールして動かすまでの過程を記事にまとめてみました。

# 1. Pythonのインストール
<a href ="https://www.python.org/">Python公式サイト</a> からPython3.5のインストーラーをダウンロード。
![image](https://qiita-image-store.s3.amazonaws.com/0/44288/fd77952d-7df2-887c-7880-ef36519b9350.png)

筆者はWindows10(64bit)を使っているので Windows x86-64 executable installer をダウンロードしました。
![image](https://qiita-image-store.s3.amazonaws.com/0/44288/f9286eb0-def0-015e-aa0c-293f76f9b0be.png)


実行すると以下のようなウィンドウが出るのでAdd Python 3.5 to PATH にチェックを入れて Install Now をクリック 
![image](https://qiita-image-store.s3.amazonaws.com/0/44288/f7db3bd4-cb49-1f3b-d7a9-004523d7d063.png)

インストールが完了すると以下のような画面が出るのでCloseをクリックしてインストーラを閉じます。
![image](https://qiita-image-store.s3.amazonaws.com/0/44288/4c1ad6be-1503-366d-361b-7bf649cb4f3f.png)

##インストール確認
コマンドプロンプトで python と入れてEnter。
Pythonが起動すればPythonのインストールは成功です。
![image](https://qiita-image-store.s3.amazonaws.com/0/44288/74a52b68-23c7-0f65-9084-f794499c48f4.png)

# 2. NumPy+MKLをインストール
SciPyを動かすためにはNumPyとMKLが必要らしいので、下記URLからNumPy+MKLのWHLファイルをダウンロードしてきます。
http://www.lfd.uci.edu/~gohlke/pythonlibs/#numpy

筆者はWindows10(64bit), Python3.5系なので numpy-1.11.1+mkl-cp35-cp35m-win_amd64.whl をダウンロードしました。
![image](https://qiita-image-store.s3.amazonaws.com/0/44288/e4e91593-888d-257d-25b4-cb10ab4bc615.png)

次にコマンドプロンプトを開いて　```pip install (WHLファイルパス)```　を実行し、ダウンロードしてきたWHLファイルをインストールします。
![image](https://qiita-image-store.s3.amazonaws.com/0/44288/9442117f-2743-3a35-6d81-376e51a70be8.png)
コマンドプロンプトに Sucessfully... と表示されればNumPy+MKLのインストールの完了です。

# 3. SciPyをインストール
下記URLからSciPyのWHLをダウンロードしてきます。
http://www.lfd.uci.edu/~gohlke/pythonlibs/#scipy

筆者はWindows10(64bit), Python3.5系なので scipy-0.18.0rc2-cp35-cp35m-win_amd64.whl をダウンロードしました。
<img height = 280 src = "https://qiita-image-store.s3.amazonaws.com/0/44288/916dd713-96fe-0f21-a9b2-9dc9032c8208.png">

```pip install```してインストールします。
![image](https://qiita-image-store.s3.amazonaws.com/0/44288/e68a7e34-ba66-b603-7e52-c07c7485c17a.png)

#インストール確認
コマンドプロンプトで```pip freeze```を実行するとインストールされているパッケージを確認することができます.
![image](https://qiita-image-store.s3.amazonaws.com/0/44288/c500a906-5ab3-01fa-738d-321ffe68da6e.png)
NumPy + MKL と SciPyがインストールされていることが確認できました。

#NumPy + SciPyの動作確認
正しくインストールされていることを確認するために以下のpyファイルを実行してみます

```test.py
import numpy as np
from scipy import integrate

def computePi(x):
    return 4/(1+x**2)

print (integrate.quad(computePi, 0, 1))
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/44288/323dd881-6d69-fb8c-1c69-5e50b9993281.png)
正しく動くことが確認できました。

#余談
余談ですが、 Atomエディターを使うとエディター上でpyファイルを実行することができるのでオススメです。 
![image.png](https://qiita-image-store.s3.amazonaws.com/0/44288/14bb81c1-3d62-f37f-724e-5e61df598902.png)

atom-runnerをインストールすればエディター上でpyが実行できるようになります
![image.png](https://qiita-image-store.s3.amazonaws.com/0/44288/4a6fbf14-58a6-420f-9760-d6496c81aeb7.png)
Selenium WebDriver でMacとWindows共通に動く環境を作る（ChromeDriverをServerで）

MacとWindows両方で、同じコードが通るSelenium WebDriverの動作環境を作る。
WindowsだけだとServer立てたりしなくても、chromedriver.exeダウンロードしてきてコード置いてるのと同じフォルダに置いてるだけでよかったんだけど、Macだと面倒っぽいので、どちらもServer立てて。

他所から内容もらってきてるだけなんだけど、両方まとめてるところがないので。

## Macの場合

[こちら](https://gist.github.com/stoshiya/3dc36187ede3e6eee3e4)の通り。

### サーバ、chromedriverのインストール

```shell-session
$ brew update
$ brew install selenium-server-standalone
$ brew install chromedriver
```

### サーバ起動

```shell-session
$ /usr/local/bin/selenium-server -Dwebdriver.chrome.bin="/Applications/Google Chrome.app" -Dwebdriver.chrome.driver=/usr/local/bin/chromedriver
```

shファイルにするなら、

```shell-session:selenium_server.sh
#!/bin/sh

/usr/local/bin/selenium-server -Dwebdriver.chrome.bin="/Applications/Google Chrome.app" -Dwebdriver.chrome.driver=/usr/local/bin/chromedriver &
```

## Windowsの場合

[こちら](http://d.hatena.ne.jp/online106/20140513/1399975549)の通り。

### サーバ、chromedriverのインストール

1. [DLページ](http://www.seleniumhq.org/download/)でダウンロード
2. DLした「selenium-server-standalone-X.XX.X.jar」をCドライブ直下に配置
3. [ここ](http://chromedriver.storage.googleapis.com/index.html)から最新バージョンのchromedriver_win32.zipをダウンロード（win64はない）。
4. Cドライブ直下に"chromedriver"フォルダを作り、解凍したchromedriver.exeを設置

### サーバ起動

```shell-session
C:\XX\XX> java -jar C:\selenium-server-standalone-X.XX.X.jar -Dwebdriver.chrome.driver=C:\chromedriver\chromedriver.exe
```

batファイルにするなら、

```shell-session:selenium_server.bat
start java -jar C:\selenium-server-standalone-X.XX.X.jar -Dwebdriver.chrome.driver=C:\chromedriver\chromedriver.exe
```

## Web Driverにつなぐコード

コードをおいたフォルダかグローバル（`-g`オプションをつける）に

```
$npm install selenium-webdriver
```

でnodeのモジュールインストールして、

```js:selenium-test.js
var webdriver = require('selenium-webdriver'),
    By = webdriver.By,
    until = webdriver.until;

var driver = new webdriver.Builder()
    .forBrowser('chrome')
    .usingServer('http://localhost:4444/wd/hub')
    .build();

//後はむにゃむにゃ...他の記事など参考に
```

これで同じコードがWindows/Mac両方で動きます。
Angular1.5でMultipleTransclusionが使えたよ


いまさら感ありますが、最近まで全く知らなかった上に日本語情報がほぼ無さそうなのでこれはまとめるしかない。

【参考】
http://blog.thoughtram.io/angular/2015/11/16/multiple-transclusion-and-named-slots.html


## そもそもTransclusionってなぁに

`Transclusion`自体は概念的なものの名前。
`AngularJS`においては`ng-transclude`というディレクティブを用いて`directive`や`component`に指定のDOMを含まさせることを意味します。（のはず）

こんな`component`を定義して

```typescript
class Container {
    static $inject = ['$scope', '$element']
    constructor(
        private scope: ng.IScope,
        private element: ng.IRootElementService) {
    }
}

angular.module('App').component('container', {
    controller: Container,
    transclude: true,
    bindings: {},
    template:
        `
    <div class="container">
      <div ng-transclude></div>
    </div>
    `
})
```

こう呼び出すと

```html
<container>
    <div>Hello World!</div>
</container>

```

こうなる。

```html
<div class="container">
    <div ng-transclude="">
		<div class="ng-scope">Hello World!</div>
	</div>
</div>
```

とっても便利ではあるのが、1.5以前は単一での指定しかできなかったため幾度か殺意が湧いたりもした。
これがMultiple対応されたということで心踊った。

## Multipleになると

名前の通り、複数の指定DOM要素を含ませることができるようになる。

こんな`component`を定義して

```typescript
class Container {
    static $inject = ['$scope', '$element']
    constructor(
        private scope: ng.IScope,
        private element: ng.IRootElementService) {
    }
}

app.component('container', {
    controller: Container,
    transclude: {
        content1: 'content1',
        content2: 'content2'
    },
    bindings: {},
    template:
        `
    <div class="container">
      <div ng-transclude="content1"></div>
      <hr/>
      <div ng-transclude="content2"></div>
    </div>
    `
})
```

こう呼び出すと

```
<container>
	<content1>Hello</content1>
	<content2>World</content2>
</container>
```

こうなる。

```
<container class="ng-isolate-scope">
    <div class="container">
      <div ng-transclude="content1">
          <content1 class="ng-scope">Hello</content1>
      </div>
      <hr>
      <div ng-transclude="content2">
          <content2 class="ng-scope">World</content2>
      </div>
    </div>
</container>
```

言うまでもなくこの2ヶ所が肝。

```
transclude: {
    content1: 'content1',
    content2: 'content2'
},
```


```
ng-transclude="content1"
```


## 注意点

こう呼び出すと

```
<container>
	<content1>Hello</content1>
</container>
```


`Error: [$compile:reqslot] Required transclusion slot 'content2' was not filled.`というスクリプトエラーが発生して描画されない。
もし必須なDOM要素でない場合はこのように`?content2`のように頭に`?`を付与する必要がある。注意されたし。

```
transclude: {
    content1: 'content1',
    content2: '?content2'
},
```

個人的には`<div ng-transclude="content1">`のような`div`が勝手に差し込まれさえしなければものすごく嬉しい。
でもとてつもなく可能性の幅が広がった気がした。
Monacaで起動時の処理をプレビューでも行いたい

# 通常のMonaca/Cordovaの起動時の処理

通常、アプリ起動時の処理はcordovaが利用可能になるdevicereadyイベント発火によって行います。

    document.addEventListener('deviceready',function() {
      // 起動時の処理
    }, false );

ところが、これだとMonaca IDE等のプレビューでは動作しません。プレビューは、wwwをマウントしている
だけなので、cordova.jsを持っていないからです。以後、cordova.jsを持っていないアプリを、「非Cordovaアプリ」と呼ぶことにします。

なるべくプレビューでテストをしたい場合、起動時の処理もプレビューで行いたいものです。

# Onsen UIを使っている場合

もしOnsenUIを使っているならば、非常に簡単で

    ons.ready( function() {
      // 起動時の処理
    } );

が使えます。ons.readyで指定した関数は、cordovaが組み込まれている時は、devicereadyイベントが発火後にしか呼ばれないからです。(cordovaが組み込まれていない時は、単にonsen UIが利用可能になった時点で呼ばれる）

# Onsen UIを使っていない場合

少し面倒ですが、readystatechangeイベントの発火を待ちます。このイベント後、readyStateがcompleteになっていれば、少なくともcordova.jsの読み込みは（もしあれば）終わっているはずです。そこで、window.cordovaが定義されていればcordova、そうでなければ非cordovaとして、初期処理を行うことができます。
ただし、cordovaだったとしても、まだdevicereadyが呼ばれているかは分からないので、ここでさらにdevicereadyのイベントの発火を待ちます。

結局コードは次のようになります。

        document.addEventListener('readystatechange',function() {
            if (document.readyState === "complete") {
                if (window.cordova) {
                    document.addEventListener('deviceready',function() { 
                        // Cordovaアプリの時の初期化処理
                        alert("This is Cordova");
                    } , false );
                } else {
                    // 非Cordovaアプリの時の初期化処理
                    alert("This is not Cordova");
                }
            }
        } , false);
jOOQをGradleで設定する

JavaのORMであるjOOQをGradleで設定する方法の説明。参考に上げてあるQiitaの記事もあるし元のマニュアルも丁寧ではあるがMavenベースで書かれている。Gradleもマニュアルにはあるがプラグインのことなどはあまり詳細が書いてない。

# チュートリアルのサンプル

付属のマニュアルのチュートリアルで書かれているサンプルを元に作成する。なおデータベースはチュートリアルにあるMySQLではなくSQLiteを使った。

## Step 1 準備
必要なライブラリを設定する。

```build.gradle
apply plugin: 'java'
// jooqのGradleプラグインと
apply plugin: 'nu.studer.jooq'

repositories {
    mavenCentral()
}

buildscript {
    repositories {
        jcenter()
        mavenCentral()
    }

    dependencies {
        // jooqのGradleプラグイン
        classpath 'nu.studer:gradle-jooq-plugin:1.0.5'
        // SQLiteを使う
        classpath group: 'org.xerial', name: 'sqlite-jdbc', version: '3.8.11.2'
    }
}

dependencies {
    compile group: 'org.jooq', name:'jooq', version: '3.8.3'
    compile group: 'org.jooq', name:'jooq-meta', version: '3.8.3'
    runtime group: 'org.xerial', name: 'sqlite-jdbc', version: '3.8.11.2'
}
```

## ステップ 2 データベース
データベースを作成

```
$ sqlite library.db
sqlite> CREATE TABLE `author` (
  `id` int NOT NULL,
  `first_name` varchar(255) DEFAULT NULL,
  `last_name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
);
sqlite> INSERT INTO "author" VALUES(1,'Hoge','Foo');
sqlite> INSERT INTO "author" VALUES(2,'Bar','Baz');
```
こんな感じでデータも入れておく。

## ステップ 3 コード生成
次の設定を追加。この書式はGradleプラグインのおかげである。プラグイン無しだとちょっと設定が面倒。

```build.gradle

jooq {
    library (sourceSets.main) {
        jdbc {
            driver = "org.sqlite.JDBC"
            url = 'jdbc:sqlite:./library.db'
        }
        generator {
            target {
                packageName = 'example.jooq'
            }
        }
    }
}
```

```
$ gradle  generateLibraryJooqSchemaSource
```

gradleのターゲットの名前は設定(library)によって変わってくる。

## ステップ 4,5,6 
ここは同じなのでまとめた。

```Main.java
import org.jooq.DSLContext;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.SQLDialect;
import org.jooq.impl.DSL;

import java.sql.Connection;
import java.sql.DriverManager;

import static example.jooq.Tables.AUTHOR;


public class Main {
    public static void main(final String[] args) {
        final String userName = "";
        final String password = "";
        final String url = "jdbc:sqlite:library.db";

        try (Connection conn = DriverManager
                .getConnection(url, userName, password);
             final DSLContext create = DSL.using(conn, SQLDialect.MYSQL)) {
            final Result<Record> result = create.select().from(AUTHOR).fetch();

            for (final Record r : result) {
                final Integer id = r.getValue(AUTHOR.ID);
                final String firstName = r.getValue(AUTHOR.FIRST_NAME);
                final String lastName = r.getValue(AUTHOR.LAST_NAME);

                System.out.println(
                        "ID: " + id + " first name: " + firstName + " last name: " + lastName);
            }
        } catch (final Exception e) {
            e.printStackTrace();
        }
    }
}
```

SQLiteのファイルパスが違うとテーブルが見つからないという一見分かりにくいエラーを出すので注意。



# 参考
* http://qiita.com/rubytomato@github/items/93ed18b30605f4491086
* http://www.jooq.org/doc/3.8/manual-single-page/#tutorials
* https://github.com/etiennestuder/gradle-jooq-plugin - このプラグインを使った
IntelliJですばやくPHP開発環境を構築する


前提
-----
Mac OSX 10.11.1
Intellij IDEA ULTIMATE 2016.1.3
PHPプラグインをインストール済

PHPをインストール
-----

```
brew install php56
```

※バージョンは適宜読み替えてください

PHPプロジェクト作成
-----

Create New Project -> PHP -> PHP Empty Project
Nextボタンを押す

![Screen Shot 2016-07-13 at 17.59.46.png](https://qiita-image-store.s3.amazonaws.com/0/10058/77d7fb9e-a159-2097-4cbf-7c735616dcbf.png "Screen Shot 2016-07-13 at 17.59.46.png")


プロジェクト名を入れる
`PHP Langage Level`と`Interpriter`のバージョンとインタプリタを選択する

![Screen Shot 2016-07-13 at 18.00.39.png](https://qiita-image-store.s3.amazonaws.com/0/10058/e8264b88-4ee0-c46a-b024-b59970e012ed.png "Screen Shot 2016-07-13 at 18.00.39.png")

インタプリタがない場合、ドロップダウンの横のボタンを押すと以下のような画面が出るのでインストールした場所を指定する
OKを押すと先ほどのドロップダウンに候補が追加されているはず

![Screen Shot 2016-07-13 at 18.00.24.png](https://qiita-image-store.s3.amazonaws.com/0/10058/93055a33-7d08-2aaf-2d11-337061916dcf.png "Screen Shot 2016-07-13 at 18.00.24.png")

起動設定する
-----
Run -> Edit Configurations
左上の＋ボタンを押して`PHP Built-in Web Server`を選択

![Screen Shot 2016-07-13 at 18.08.36.png](https://qiita-image-store.s3.amazonaws.com/0/10058/81e351e8-41a1-84d4-19d2-e582a415fc89.png "Screen Shot 2016-07-13 at 18.08.36.png")

適当な名前をいれる
Portは`80`だと色々まずいので`8000`とかに変える
`Document root`にプロジェクトのルートを指定してOK
![Screen Shot 2016-07-13 at 18.09.41.png](https://qiita-image-store.s3.amazonaws.com/0/10058/87a9917c-ece3-d1ae-ad7f-dc2a502b3fdf.png "Screen Shot 2016-07-13 at 18.09.41.png")

すると右上の実行ボタン横に候補が出る
![Screen Shot 2016-07-13 at 18.09.59.png](https://qiita-image-store.s3.amazonaws.com/0/10058/728acc33-0923-2d0f-4200-5f2016f8673a.png "Screen Shot 2016-07-13 at 18.09.59.png")


起動確認する
-----

おもむろに実行ボタンを押すと起動する。
`http://localhost:8000/`
にアクセス

![Screen Shot 2016-07-13 at 18.14.38.png](https://qiita-image-store.s3.amazonaws.com/0/10058/07642f8f-85de-9e82-f926-c4376cac5be0.png "Screen Shot 2016-07-13 at 18.14.38.png")

Not Found
そりゃそうだ。でもなにかが起動している。
ファイルを置いてみる

```index.php
<h1>Hello PHP</h1>
```

もう一度アクセスする

![Screen Shot 2016-07-13 at 18.17.22.png](https://qiita-image-store.s3.amazonaws.com/0/10058/03951436-29c9-a01f-96a6-5b9281341cc2.png "Screen Shot 2016-07-13 at 18.17.22.png")

成功。Apacheやらなんやらを入れずに実行できるのはステキ。

以上