OmniAICreator/Qiita-1.07M huggingface dataset:
パッケージのインストールURLを取得する方法

めちゃくちゃ基本的ですが念のため、、、

# やりたいこと
パッケージやツールの公式HPなどから自分が取得したいバージョンのDLURLを手に入れる。

# やること
このボタンを押したらダウンロードできるってところまでいったうえで、
リンクを右クリック。
リンクのアドレスをコピーでコピーする。

その後curlなどでCLIからインストール。


これで古い記事をそのままコピペが減らせるはず。
【メモ】Flutter runでError connecting to the service protocol: HttpException: , uri = http://127.0.0.1:1027/wsというエラーが出る。

```
Error connecting to the service protocol: HttpException: , uri = http://127.0.0.1:1027/xxxx=/ws
```

iOS実機でflutter runすると、こんな感じのエラーが出ました。
これでは実行はできてもホットリロードできなくなるので開発効率がグンと落ちます。
## 解決法
**実機iPhoneのWi-FiをOffにする**ことで解決しました。
しらみつぶしにテストして分かったので、なぜ解決するのかは詳しくないのでわかりません。わかる方、教えてください。
（でも、Wi-Fi切っちゃうと困る人多そう...）

その他にXcodeのWindow -> Devices and Simulatorsでデバイスの設定のConnect via networkというチェックを入れると直るという記事があったのですが、私の場合では治りませんでした。
この問題にはいくつかの解決策があるのかもしれません。

## 謎のエラー②
```
ideviceinfo returned an error:
ERROR: Could not connect to lockdownd, error code -8
```
Wi-Fi切ってrunするとこんなエラーが出るかもしれませんが、めげずに2〜3回runしてください。

##ありがとう、ホットリロード。
ホットリロード最高。
WPF GridのC# Code

# Grid
私のHDDに突っ込んであったWPF Gridの説明。
上のXAML文は下のC#文で表現できる(多分)

## XAML
```xml
<Grid ShowGridLines="True">
    <Grid.RowDefinitions>
        <RowDefinition Height="1*" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="2*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="1*" />
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="2*" />
    </Grid.ColumnDefinitions>
    <!-- 1行1列目に配置 -->
    <Button Content="Button" Grid.Row="1" Grid.Column="1" />
</Grid>
```

## C# Code
```cs
var myGrid = new myGrid();
myGrid.ShowGridLines = "True";

var rd = new RowDefintion();
var rd2 = new RowDefintion();
var rd3 = new RowDefintion();
rd.Height = new GridLength(1.0, GridUnitType.Star);
rd2.Height = GridLength.Auto;
rd3.Height = new GridLength(2.0, GridUnitType.Star);
myGrid.RowDefinitions.Add(rd);
myGrid.RowDefinitions.Add(rd2);
myGrid.RowDefinitions.Add(rd3);

var cd = new ColumnDefinition();
var cd2 = new ColumnDefinition();
var cd3 = new ColumnDefinition();
cd.Width = new GridLength(1.0, GridUnitType.Star);
cd2.Width = GridLength.Auto;
cd3.Height = new GridLength(2.0, GridUnitType.Star);
myGrid.RowDefintions.Add(cd);
myGrid.RowDefintions.Add(cd2);
myGrid.RowDefintions.Add(cd3);

var btn = new Button();
btn.Content = "Button";
Grid.SetRow(btn, 1);
Grid.SetColumn(btn, 1);
```

# 参考
https://blog.okazuki.jp/entry/20130106/1357483477  
https://docs.microsoft.com/ja-jp/dotnet/framework/wpf/controls/how-to-create-a-grid-element  
https://tnakamura.hatenablog.com/entry/20100709/grid_length
Junitのカバレッジを100%にする

そろそろネタがなくなってきた。
今回は特段説明するようなことはないような気もするんですが、とりあえずカバレッジを100%にしてみようかと思います。

1.テスト対象クラスのカバレッジを100%にするようなテストメソッドを作成します。
これまでに作成したテストクラスの中に、下記のメソッドを追加しました。

```ruby:JunitTestClass
	@Test
	public void test_hiru() {
		TestClass testClass = new TestClass();
		String str = "こんにちは";
		String result = testClass.testMethod(str);
		assertEquals(result, "昼");
	}
	@Test
	public void test_yoru() {
		TestClass testClass = new TestClass();
		String str = "こんばんは";
		String result = testClass.testMethod(str);
		assertEquals(result, "夜");
	}
	@Test
	public void test_err() {
		TestClass testClass = new TestClass();
		String str = "あいうえお";
		String result = testClass.testMethod(str);
		assertEquals(result, "エラー");
	}
```

2.カバレッジを取得します。
テスト対象クラスのカバレッジが100%になっていることがわかります。
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306544/cb98ce8d-a5ca-149e-b34c-25e6d2ce5b53.png)

3.テスト対象クラスを見てみると、こんな感じで色が付いています。
オールグリーン。
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306544/dfe9fe9d-3200-8c6e-c649-b65b9b1b46f4.png)

4.取得したカバレッジの中ではテストクラスが100%になっていないのですが、テストメソッドの中に一つでも失敗ケースがあるとこうなります。
テストクラスはこんな感じに色が付いています。
![07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306544/695ac89d-46de-ee8d-81da-c94be0a94b9f.png)

5.テストクラスのカバレッジも100%にしたい場合は、失敗ケースを修正しましょう。
今回は失敗ケースを削除してしまいます。他のメソッドでカバレッジ100%は取れているので大丈夫です。
ちなみに編集すると色が消えます。
![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306544/793ccf01-aa16-b435-5518-54105851fffc.png)

6.この状態で再度カバレッジを取得すると、テストクラスも含めて100%になります。
![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306544/7d4c8a4b-0294-f3d1-4c0a-d2457f260a4f.png)

7.テストクラスもオールグリーンです。綺麗なもんですね。
![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306544/513b6f17-9b12-8247-7264-d56fe1c5e90d.png)
jquery inputmaskとcasperjs

Webフォームのplaceholder的な、フォーマッター的な
[Inputmask](https://github.com/RobinHerbots/Inputmask)
についてはこちら。

普段casperjsなんかでWebフォームのテストを書いていますが、
fillSelectorとinputmaskの相性が悪い、というか、どう書けばすんなりいくかがわからない。

単純なfillSeletorでは、inputmaskをかえたフィールドは空欄で送信されてしまう。

fillSelectorしたあとに、inputmaskをかけているフィールドに

```coffeescript
@evaluate ->
  $(selector).val('aaa')
```

なんてしてみたけど、やっぱり送信すると空欄で送信されている。

とりあえず、casperjsの場合では、フォーム入力直前に

```coffeescript
@evaluate ->
  $(selector).inputmask('remove')
```

として、無効化することにした。
ElixirでJSONPathライクなライブラリを作って初めてHexに登録してみた

# はじめに
Elixirで、階層の深い構造からJSONPathやXPathのように簡単に値を取り出すことを目指して[いろいろ](https://qiita.com/mtannaan/items/ae82c8b459826ba7b5c3)試していました。
結局のところあまりしっくりくるやり方がなく、自分でElixirのデータ構造に合った仕組みをつくってみました。

[Elixpathという名前でHexにアップロード](https://hex.pm/packages/elixpath)しています。初Hexだったので勉強になりました。


# 特長
Elixpathの利点（になるよう意識した点）を挙げていきます。

### 簡潔な記述で幅広い構造から要素を取得できる

生のElixirでも、keyがatomであれば下記のように簡潔に要素が取得できると思います。

```elixir
# nested maps with atom key
iex> deep_map.key1.key2.key3
# nested keyword lists
iex> deep_keyword[:key1][:key2][:key3]
```

ただ、例えばどこかの階層にリストを含む場合は上記のように簡単な書き方はできません。

Elixpathを使うと、そのような場合にもきちんと対応できます。

```elixir
# nested maps and lists
iex> Elixpath.get!(deep_map, ~S/.:atom_key."string_key"[0]/)
iex> Elixpath.get!(deep_map, ~S/.:atom_key."string_key"[-1]/)

# w/o Elixpath
iex> get_in(deep_map, [:atom_key, "string_key", Access.at(0)])
iex> deep_map.atom_key["string_key"] |> List.last
```

### ワイルドカード対応
`*`をワイルドカードとして使えます。

```elixir
iex> users = [
...>   john: %{name: "John", age: 27, languages: ["Erlang", "Ruby", "Elixir"]},
...>   mary: %{name: "Mary", age: 29, languages: ["Elixir", "F#", "Clojure"]}
...> ]

iex> Elixpath.query!(users, ".*.:languages[0]")
["Erlang", "Elixir"]

# w/o Elixpath
iex> Keyword.values(users) |> Enum.map(& (&1.languages |> Enum.at(0))) 
["Erlang", "Elixir"]
```

### 子孫要素の取得
`..子孫要素のkey`でそのkeyにマッチする子要素・子孫要素を取得できます。たとえば、どの階層でもよいのでとにかく`:name`を取得したいときは下記のようにします。

```elixir
iex> Elixpath.query!(users, "..:name")
["John", "Mary"]
```

# 感想
Elixirのライブラリをきちんと作ってHexにアップロードするのは初めてだったので、いろいろと学びがありました。

### ライブラリとしての体裁を整える

きちんとしたライブラリっぽくしてHexにアップロードすることを目標にしていたので、

- きちんとドキュメントを書いて[ExDoc](https://hexdocs.pm/ex_doc/readme.html)で出力してみたり
- テストをきちんと書いて[excoverallsでカバレッジを確認](https://qiita.com/ma2ge/items/8bca27709380f8320d9e)してみたり
- [Shields.ioでバッジを貼り付けて](https://qiita.com/dtan4/items/13b0ea9edf5b99926446)みたり

と頑張ってみました。他のライブラリを参考に見よう見まねでやってしまった部分もあり、要点を押さえきれていないかもしれませんが、経験を積んでいきたいです。



### CIかんたん。べんり。
Elixirの複数バージョン対応の確認にTravis CIを使ってみました。

また、せっかくexcoverallsを入れたのでプルリクエストごとにテストカバレッジの変化を通知してくれる[codecov](https://codecov.io/)も設定してみましたが、これも便利そう。[Coveralls](https://coveralls.io/)も試しましたが、codecovのほうがすっきりしていて使いやすかったです。

どちらも自身で設定するのは未経験でしたが、公式ドキュメントで事足りる簡単さで驚きました。


### パーサコンビネータ
パスの文字列をパースするのに[NimbleParsec](https://github.com/plataformatec/nimble_parsec)を使っています。慣れてからはとても便利だったのですが、きちんとパーサを書くのも初めてだったので慣れるまでは苦戦しました。別途記事にしたいかも。

# まとめ
[Elixpath](https://hex.pm/packages/elixpath)、よかったら使ってみてください。
お気付きの点やアドバイスもお待ちしております！
Herokuでのログ確認方法

# 概要
Heroku createで作成したサイト画面で下記エラーが発生した時のログ確認方法のメモ  

```
We're sorry, but something went wrong.
If you are the application owner check the logs for more information.
```

# ログ確認方法
bash(プロンプト)で`heroku logs --tail`コマンドを打つとログ待機状態にできます。  
ブラウザでエラー表示された画面に遷移すればその時のログが出力されるはずです。  
※備考：`heroku open`でサイトをブラウザ表示できます。
php-master-changes 2019-06-16

今日は Windows 用ビルドシステムのデフォルトバージョン指定修正、テストの修正、ドキュメントの修正、ctype の func_info を arg_info に揃える修正があった！

# 2019-06-16
## weltling: Set correct default version
- https://github.com/php/php-src/commit/5a83bfb37db63eeba2323392630c26679bc9bab2
- [7.4~]
- Windows 用のビルドシステムで、デフォルトバージョンを 7.4.0 に修正

## weltling: Set correct default version
- https://github.com/php/php-src/commit/0da6f73322d0eb64f86f632e92672ab184435551
- Windows 用のビルドシステムで、master のデフォルトバージョンを 8.0.0 に修正

## krakjoe: gettimeofday cannot be used to reliably implement high precision process synchronization
- https://github.com/php/php-src/commit/7e1972796b1706a668643830f3e5aa9960a85a70
- [7.4~]
- [time_sleep_until()](https://www.php.net/manual/ja/function.time-sleep-until.php) のテストをとりあえず XFAIL にマーク
- 内部で [gettimeofday(2)](https://linuxjm.osdn.jp/html/LDP_man-pages/man2/gettimeofday.2.html) が使われており、「[clock_nanosleep(2)](https://linuxjm.osdn.jp/html/LDP_man-pages/man2/clock_nanosleep.2.html) じゃねえのこういうの！」ということらしい

## krakjoe: this mtime comparison makes assumptions that cannot always hold true
- https://github.com/php/php-src/commit/228388447509107d61cb253acb614d8d3e5efabf
- [7.4~]
- ext/phar で、テストの常に真とはならない条件をテストしていた箇所を削除

## TysonAndre: Fix a typo in UPGRADING
- https://github.com/php/php-src/commit/435384127c7d388a5224dff7805c735c57e14165
- UPGRADING で、typo の修正

## TysonAndre: Make opcache zend_func_info consistent with Reflection for ctype
- https://github.com/php/php-src/commit/74589cf6768e5f79f77c123c31e1f119f74a2f44
- ext/opcache で、ctype の func_info を arg_info に揃えた

## cmb69: Prevent parallel test conflict
- https://github.com/php/php-src/commit/11c3215251565166c7d64a84384be75046c19ad8
- [7.4~]
- テストの並列実行対策
GraalVMって...?

# GraalVM

Java仮想マシン(JVM) およびJITコンパイラの技術を利用した多言語対応の汎用仮想マシン。
Twitter社でも取り入れられている。

# 特徴
### 多言語対応
###### JVM

- Scala
- Kotlin
- Groovyなど  

Java以外の言語の実行にも対応している。総称して「JVM言語」。JRubyやJythonといった，既存言語のJVM用実装もJVM言語。

###### GraalVM 
 
- JavaScript
- R言語
- Ruby
- Python
- C/C++  

のようなLLVMベース(?)の言語の実行にも対応。同一の仮想マシンを用いて異なる複数の言語を実行できるだけでなく，複数の言語のコードが混在したプログラムを実行することもできる。

# 機能

### Graal
JVM用の新しいJITコンパイラ。  
JavaのJITコンパイラは，コンパイラが生成したJavaバイトコードを読み込んで機械語を生成する。現在のJVMは，このJITコンパイラのエンジン部分のみを差し替えて実行できる仕組みを備えている。GraalVMは，このJITコンパイラ部分にGraalを採用することで高速化を実現。

### Truffle
自前のプログラミング言語を実装するためのフレームワーク。  
Truffleはプログラムのソースコードを解析してAST（抽象構文木）を生成するためのAPIを提供しています。JVM言語に関してはもともとGraalで実行できるため，TruffleはJavaScriptやRubyなどJVM言語以外の言語のために使われている。

### Javaの実行がめちゃくちゃ早い
- GraalVMに搭載されているGraalはモダン実装を取り入れたコンパイラ。コンパイラエンジンをGraalに置き換えるだけでパフォーマンスが向上するケースも。
- 様々な言語もJavaの実行ファイルに変換され、高パフォーマンスで実行される。

### まとめ
- VMの多言語対応の走り
- Springなどの動的にクラスを作り出すものにはまだ対応していない
- CEがリリースされたらしいので今度試してみたい
- Dockerhubにもあがってた！
シェルスクリプト-引数をリストで与えて直列で回す

```bash:list1.txt
1
2
3
```

```bash:list2.txt
a
b
c
d
```

```bash:sample.sh
#!/bin/bash

crd1=$1
crd2=$2

while read line1
do
  while read line2
  do
    echo subsample.sh ${line1} ${line2}
    ./subsample.sh ${line1} ${line2} &
    wait $!
    status=$?
    echo exit $status
    if [ "$status" != "0" ]; then
      exit 1
    fi
  done < $crd2
done < $crd1
```

```bash:subsample.sh
#!/bin/bash

echo $1 $2
sleep 1
if [ "$1" = "2" ]; then
  exit 1
fi
```
Rubyのメソッドを調べる

## メソッド定義位置を調べたい

```.ruby
objct.method(:method_symbol_name).source_location 
#=> ["/path/to/the/file.rb",34]
```

## オブジェクトのメソッドを調べたい

```.ruby:pry
ls -m object
```

## こんなメソッドないかな？
Rails初心者だった頃は、クラスの定義だけでなく、継承やインクルード、method_missingで自動生成されたメソッドなどを使いたいときに、オブジェクトのメソッド一覧のうち、「これっぽい名前のメソッドないかな？」という感じで調べたいときは、これを使っていました。


```.ruby
object.public_methods.select{|m| m.to_s.include?('user') }

#=> 
[:autosave_associated_records_for_user,
 :build_user,
 :create_user!,
 :reload_user,
 :create_user,
 :user,
 :user=,
 :id_came_from_user?,
 :user_id=,
 :user_id_before_type_cast,
 :user_id_came_from_user?,
 :user_id?,
 :user_id_changed?,
 :user_id_change,
 :user_id_will_change!,
 :user_id_was,
 :user_id_previously_changed?,
 :user_id_previous_change,
 :restore_user_id!,
 :saved_change_to_user_id?,
 :saved_change_to_user_id,
 :user_id_before_last_save,
 :will_save_change_to_user_id?,
 :user_id_change_to_be_saved,
 :user_id_in_database,
 :role_came_from_user?,
 :created_at_came_from_user?,
 :user_id,
 :updated_at_came_from_user?]
```
ナマケモノの僕がよく使うVue.jsの簡単なデバッグ方法4選

Vue.jsで、値をリアルタイムに見ていくのが大変なので、簡単なデバッグ方法について書いていきます。


#### console.logを使う（簡単度☆）
```js

let hoge = 'test'
let fuga = 'test2'

// 何かしらの処理

console.log(hoge);
console.log(fuga);

// 何かしらの処理

hoge = this.getHoge();

console.log(hoge)
console.log(fuga);

```

console.log('hoge')を入れます。

簡単ですが、見たい変数が多いと大変です。

#### debuggerを入れる簡単度☆☆

```js

let hoge = 'test'
let fuga = 'test2'

// 何かしらの処理

debugger;

// 何かしらの処理

hoge = this.getHoge();


```

debuggerをソースに入れて、Chromeディベロッパーツールで、ブレークポイントを貼って、ステップ実行しながら変数の中身をみます。

コンパイルされたVue.jsのファイルはとても長く、見たい場所まで行くのが大変です。
ディベロッパーツール上でブレークポイントを貼るのは、手間です。

ソース上にdebuggerを入れることでブレークポイントを入れて、ディベロッパーツールで、ポチポチと追加ブレークポイントを入れて行くこともできます。

ただ環境によるかもしれませんが、Vue.jsで実行しているとステップ間の時間がかかって大変な場合があります。
f10連打がつらいです。

#### devtoosを使う簡単度☆☆☆
Chrome拡張のVue.js devtoolsを使います。

変数の中身を見るのがとても便利です。
ただ、Componentの親子関係がたくさんあると、ポチポチポチして見たい階層にいくのが、大変なときがあります。

[Vue.js devtools]
(https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd?hl=ja)

#### watchを使う 簡単度☆☆☆☆☆

Vue.jsのwatchを使って、リアルタイムに変数の変化を見ます。


```js
watch: {
 hoge: function () {
   console.log('hoge dump')
   console.log(this.hoge)
 },
  fuga: function () {
   console.log('fuga dump')
   console.log(this.fuga)
  }
}
```

見たい値が決まっていて、操作によっていろいろ変わるならこれが簡単だと思います。

最初書くの大変ですが、リアルタイムに見れるのでものぐさな方にはおすすめです。

#### まとめ
状況に応じて使い分けましょう。
10分でサーバレスだけでできるX-Ray入門

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96286/d9251075-bcc1-8049-ef96-fcae63286aea.png)

API GatewayとLambdaだけで思ったよりもカンタンにできました。

# おさらい: X-rayとは
AWSのマネージド分散とレーシングシステム。サービス間の通信経路の把握、リクエストごとの速度の計測などをカンタンにするサービス。

OSSとしては、クライアント側APIとして OpenTracingAPI、それらを追跡するアプリとしてjeagerなどがある。  

# やってみた
まずはLambda関数を作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96286/8c20ae06-1f6c-da25-a368-4ecbec8cb636.png)

次にAPI Gatewayを作成してデプロイ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96286/0430e9c3-f310-8b56-6fb2-fc5b3a4cac42.png)

X-Rayを有効化。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96286/7ee1775f-7a9b-82a1-9edc-13c818d67b6f.png)

以上。設定完了。

# 使ってみた
これだけで使えます。OpenTracingAPIの設定は、AWS SDKとかマネージドサービスで吸収するっぽい。

```
curl https://******.execute-api.ap-northeast-1.amazonaws.com/v1/hello
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96286/e6dd3e05-2640-43ab-636f-13a4808de5d3.png)

# 考察
* サービス間の通信を可視化する手段が欲しかったのでよい。
* 利用しているリソースを可視化できるのもよい。
* アプリからS3やDynamoDBを呼び出す際にはXRayの設定をすることで可視化可能になるっぽい。
* ↑↑↑ ローカルの検証に影響するのかちょっと気になってる →→→ ローカルルールというのもあるらしい。
技術選定の審美眼

ORACLE CODE TOKYO B-3-1
を拝聴したメモです。
技術の移り変わりがすさまじいこの時期に私たちはどの技術を選べばいいのかというひとつの指標になればと思います。

### 長生きしている技術
- Unix
- REST/Web
- RDBMS

#### 共通点
制約がもたらす共有

- インターフェースが狭く限定的
- 振る舞いの種類が少ない
- 実装に依存しない
- 接続と再利用が時間をまたいでいる

### 決定的な違いをもたらした技術
- Ruby on Rails
- Cloud
- Docker
- React

#### Ruby on Rails/Cloud/Docker
量的（時間的）な変化が大きい
「安い」「うまい」の実現

#### React
サーバーサイドの処理を記述する感覚でフロントエンドのコードが書ける
データ更新の方向が一方通行（混乱しない）（？）
Reactによるて手数は増えたが、心配は減った

### 結局なにを使えばいいの
- Game Changer（大きな変化をもたらすもの）は必ずしも採用する必要はないが、それらが変えた後あとの世界は知っておく必要がある。
- 開発にかかわる労力（コスト、心的コスト）を矢印で表したとき、その長さや構造を圧倒的に変えるもの。
もしくは矢印は折る（ジャンルそのものを不要にする）

ここまでの変化がないものをスルーするかどうかは「お好みで」

「その技術が何のために出てきて、何をどのくらい変化させるのか見切れればスルーできる」
### WorthisBetter
簡潔性、正当性、一貫性、完全性の観点でソフトウェアの設計を行う。
設計も実装もシンプルがベストだがそれができないときになにを重要視するかというもの  

- MIT/Stanfordアプローチ  
コードがいくら複雑になっても正しいことをせよ  
- New Jerseyアプローチ  
ユーザの負担が増えたとしてもコードを単純に保て  

従来のソフトウェア設計観点からいくとMIT/Stanfordが「より良い(Better)」でNew Jerseyが「悪い(Worth)」

しかし、実際は単純なコード単純な実装で50%の正しさをもったものをつくったほうが伝染性がよく、結果的に技術的改善が行われ90%まで実現するだろう

っていう考え
（汚く早く書いたほうがいいという話ではないです）  


### まとめ
- 技術の変化は螺旋状。技術の歴史は同じような周期で回っているが、実は螺旋構造で同じところには返ってこない。
- 変わらない技術には特徴がある。その背景を理解する。
- とりあえず新しい技術が生まれたら触ってみようぜ。
neo4jさわってみた

# グラフ・データベースとは
「ノード」「リレーション」「プロパティ」の三要素を用いて、ノード間の関係性をあらわすデータベース

### ノード
ひとつひとつのエンティティ。人だったり物だったり、とにかくエンティティ。

### リレーション
エッジとも呼ばれる。どのノードがどのノードにどんな関係をもっているかをあらわす

### プロパティ
ノードやリレーションの属性をあらわす。

世界は表構造であらわすことは不可能ではないが、関係性をあらわすことに関してRDBは不向き
グラフ構造であらわすと、それぞれがどのようなもので、どれとどのような関係をもっているのかが明確に

# 二つの処理
### 参照系処理  
あるノードとその周辺のノードの参照
プロパティパスによる参照
などなど演算系処理
### 演算系処理
スコアリングやランキング
コミュニティの検出
経路検索
レコメンド(User2Itemもitem2itemも)

# neo4j試してみました。
```
CREATE (A:Person { name: "Aさん", 出身:"福岡" })
```
一番オーソドックスなクエリです。これで

 name: "Aさん", 出身:"福岡"
という**プロパティ**を持つAという**ノード**ができました。

東京出身のBさんもつくります。

```
CREATE (B:Person { name: "Bさん", 出身:"東京" })
```
つぎにリレーションを追加します。

```
MATCH (A: Person), (B: Person)
WHERE A.name = "Aさん" AND B.name = "Bさん"
CREATE (a_san)-[r:知っている]->(b_san)
RETURN r;
```
AさんがBさんを知っているという**リレーション**が追加されました。

ノードが多くなればなるほどUIはぐちゃぐちゃになりますが、RDBよりも表現できる幅は広くなります。

例として[スレンジャーシングス](https://www.netflix.com/title/80057281)の登場人物の相関図です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420245/70de5d97-14a3-bb31-6a62-5cec011a04f6.png)


# まとめ
関係性が重視されるデータを扱う際にはRDBよりも優れている。(時刻表アプリやマッチングアプリなど)
思ったより参照処理(JOINとかがないから？)
UIがかっこいいので使っていておもしろい
JavaユーザーのDjangoチュートリアル

Web開発はSpringBootしかしたことないエンジニアです。試行錯誤しながら、DjangoでHelloWorldしていきます

condaをインストールしてたらいろいろ楽だよ
> condaは、主にPython用に作られたパッケージ管理システムと環境マネジメントシステムです。 単体ではリリースされておらず、Anaconda、Anacondaサーバー、Minicondaに内包されているものです。機械学習ライブラリのパッケージ等を簡単にインストールできます
Gradleみたいなもんかなーって感じの認識です。  

## セットアップ
djangoインストールしたよ

```
$ django-admin startproject hello
```
でdjangoアプリのひな形ができます

```
hello
  ├ manage.py
  └ hello
      ├─ __init__.py
      ├─ settings.py
      ├─ urls.py
      └─ wsgi.py
```
できました

```
$ python manage.py startapp world
```
で"world"という名前のアプリが追加できます(JavaでいうところのController?)

```
hello
  ├─ manage.py
  ├─ hello
  │    ├─ __init__.py
  │    ├─ settings.py
  │    ├─ urls.py
  │    └─ wsgi.py
  └─ world
       ├─ __init__.py
       ├─ admin.py
       ├─ apps.py
       ├─ models.py
       ├─ tests.py
       ├─ urls.py
       └─ wsgi.py

```

## コーディング
ひな形ができましたので次にコードをいじってHelloWorldしていきます。
最初にsettings.pyを編集してworldアプリケーションを組み込みます。
INSTALLED_APPSタグにworldを入れます。

```python
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'world'
]
```
次に「HelloWorld!」を出力するメソッドをつくります。
world\vies.pyを編集します。

```python
from django.http.response import HttpResponse

# Create your views here.
def helloworld(request):
    return HttpResponse('Hello World!')
```
つづいてプロジェクトのディスパッチャを設定していきます。ディスパッチャには二つの種類があります。

- プロジェクトディスパッチャ
- アプリケーションディスパッチャ

プロジェクトディスパッチャはプロジェクトに来たリクエストをどのアプリケーションで実行するか振り分けるディスパッチャ
アプリケーションディスパッチャはアプリケーションに来たリクエストに対してレスポンスをどのViewで実行するかを振り分けるディスパッチャ

プロジェクトのディスパッチャから行います。
*最新のDjangoではurlディパッチャの記法がかわってるから注意*
hello\urls.pyを編集します。

```python
from django.contrib import admin
from django.conf.urls import include,url

urlpatterns = [
    url(r'^', include(('world.urls', 'world'),)),
    url(r'^admin/', admin.site.urls),
]
```
続いて、アプリケーションディスパッチャを行います。
world直下にurls.pyを作成します。

```python
from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^$', views.helloworld, name='helloworld'),
]
```
パラメータ指定なしのときにviesのhelloworldメソッドを返すという設定ができました。
・・・
プロジェクトディスパッチャでまとめてしたらよくない？って思いますよね。
できないこともないのですがSpringでいうところの

- RequestMapping(プロジェクトディスパッチャ)
- GetMapping(アプリケーションディスパッチャ)
みたいな感じでディレクト構造やコード自体を見やすくするためだと思いましょう。

## 実行
ここまできたら、サーバーを起動してみましょう

```
$ python manage.py runserver 0.0.0.0:8000
```

localhost:8080につなぐと。。。

HelloWorld!
変なjsonを！！pythonで！！！パースしたい！！！！

# https://stackoverflow.com/questions/12511159/how-to-decode-an-invalid-json-string-in-python

**$\huge{demjsonを入れろ！！！！！}$**

keyがクオートされてないのとかもとりあえず雑にparseできます。
Project Euler 53をPythonでやってみる

#問題 53
http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%2053

#解答
組み合わせ${}_n \mathrm{C} _r$は真ん中に行くにつれて大きくなっていくのでそれを利用しすると、各$n$に対して$r$を下から順に確認していき初めて1000000を超える$r$を見つけるとrからn-rまでは全て1000000以上となる。
これを利用して次のようなプログラムを組んだ。

```python:ProjectEuler53.py
def factorial(n):
    if n==0: return 1
    prod = 1
    for i in range(1,n+1):
        prod *= i
    return prod

def check(n):
    for r in range(int(n/2)+1):
        c = factorial(n)/(factorial(r)*factorial(n-r))
        if c > 1000000:
            return n-2*r+1
    return 0


num_sum = 0
for n in range(1,101):
    num_sum += check(n)
print(num_sum)
```

0.088 seconds
配列の中から条件に当てはまる要素をランダムに1つ返す

ランダムな値が入った配列の中から10以下の値のうちどれか一つをランダムで返すような処理をC#で書く。やりかたはいくつかあるので複数パターン列挙する。

```c#
int[] array = { 10, 2, 33, 40, 1, 3, 34, 21, 30, 5, 73, 41, 0 };
```
なお指定の範囲の整数xを返すランダム関数を以下のように定義しておく。(min <= x < max)

```c#
int Rand(int min, int max)
```


## 1.簡潔な方法

フィルタリングした配列からランダムで値を取得する。

```c#
int[] newArray = array.Where(filter).ToArray();
int result = newArray[Rand(0, newArray.Count())];
```

## 2.シャッフルを使う方法

上の方法では `ToArray` したときに新しい配列が生成されてしまうので、もとの配列を書き換えることでメモリが確保されないようにする。
シャッフルして条件に当てはまる最初の要素を返す。C#にはランダムに並べ替えるシャッフル関数がないので、まずはシャッフル関数を定義する。
シャッフル関数は余計なバッファを使わず計算量がO(n)ですむFisher–Yatesのアルゴリズムを使う。

```c#
void Shuffle(int[] array)
{
    for (int i = 0; i < array.Length - 1; i++)
    {
        int j = Rand(i, array.Length);
        int v = array[i];
        array[i] = array[j];
        array[j] = v;
    }
}
```

```c#
int result;
Shuffle(array);
foreach (var v in array)
{
    if (v <= 10)
    {
        result = v;
        break;
    }
}
```

## 3.シャッフルを用いたもう少し効率のいい方法

シャッフルしながら条件に当てはまる要素を探す。

```c#
for (int i = 0; i < array.Length - 1; i++)
{
    int j = Rand(i, array.Length);
    int v = array[j];
    if (v <= 10)
    {
        result = v;
        break;
    }
    array[j] = array[i];
    array[i] = v;
}
```

## 4.もとの配列を変更しない方法

メモリも確保したくないし、もとの配列の順番が変わってしまうのが困る場合の方法。
条件に当てはまる値の総数を数えて、何番目に見つかる値を採用するかランダムに決める。

```c#
int result;
int count = 0;
foreach (int v in array)
{
    if (v <= 10)
    {
        count++;
    }
}
int index = Rand(0, count);
foreach (int v in array)
{
    if (v <= 10)
    {
        index--;
        if (index < 0)
        {
            result = v;
            break;
        }
    }
}
```
API Gateway(SAM API)のステージをCloudFormationで管理するプラクティスについて考える

# はじめに

AWS API Gatewayにはステージ機能があり、/dev, /prod などの複数ステージにデプロイしてURLで切り替えることができます。

ですが、CloudFormationでAWS::Serverless::ApiリソースとしてデプロイしようとするとStageNameがstringしか指定できず、1つのステージしか作成できません。 ([参考:リソースリファレンス](https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapi))

API GatewayではAPIキーや使用量プラン、デプロイもステージに対して紐づくコア機能ですが、SAMでは複数ステージが想定されていないようにみえます。
ということで、SAMにおけるAPI Gatewayのステージの役割とかどう管理していくべきかを考えていきたいと思います。

ちなみにこの件はGitHubリポジトリのIssueがOpenとなっており、議論が進められています。
今回は主にこの議論のまとめ的な要素が多めです。

### 参考URL

- https://github.com/awslabs/serverless-application-model/issues/198
- https://hackernoon.com/managing-multi-environment-serverless-architecture-using-aws-an-investigation-6cd6501d261e

# 環境ごとのリソースを管理する方法

SAMで環境ごとのリソースを管理するアプローチは以下の2パターンが考えられます。

- 1つのスタックで管理する
    - 1つのAPI Gateway内で複数ステージを作成
    - 1つのLambda内で複数エイリアスを作成
    - API Gatewayのステージ変数でエイリアスを指定
- 環境ごとに別スタックで管理する
    - CloudFormationのパラメータを参照して別名のリソースをそれぞれ作成する

現状では、ServerlessのCloudFormationではステージが複数指定できないという課題があるためほぼ後者一択という感じもありますが、前者を選択したい場合は一旦SAMをきれいに使うことを諦めて[AWS::ApiGateway::Stage](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-stage.html)リソースを活用していけば複数ステージ作成も可能です。
その代わりSAMの便利な記法が使えなくなるデメリットが発生しますがそのあたりはトレードオフですね。

## 単独スタックでまとめるべきか分離するべきか

議論としては分離するのがベターという意見が多めです。
さらに可能ならAWSアカウントも分けたほうがよいとも言われています。
デプロイ事故などを防ぐにはやはり分けておいたほうが安全ですね。

ただそうすると、APIステージやLambdaエイリアスはどんな時に使えばよいのかという疑問は残ります。
小規模なリソースについて環境ごとに個別にスタックを作成するとスタックやリソース自体が増えて管理が煩雑になるので1つのスタックにまとめてしまい、スタック自体がある程度の規模になるとテンプレート内での環境管理の方が大変になるので分離する。というのが一つのアプローチかもしれません。

# まとめ

この件は先日のAWS Summit Tokyo 2019の会場でServerlessブースにいた方を捕まえて色々お聞きしてヒントを頂いた話を元にまとめています。
本当にお忙しい中対応いただいてありがたい限りです。

Issue上でのcontributorの発言内容をまとめておくと、

- 複数ステージをデプロイ出来るような機能はいずれリリースするつもりがある
    - Stage変数をArrayで指定する形式が有力？
- とはいえべき論としてはステージごとにスタックを分けるのがよさそう
    - ドキュメントもその方向で修正していく

ということのようで、
IssueがOpenしたのが2017年9月、いずれ対応するよとコメントが出されたのが2018年6月で、その後特に動きなし、という状況ですので、SAMにおいては複数ステージを使うことは考えないほうがよさそうです。
API Gatewayのステージという機能自体が使われない機能感がありますね。
if文とは

##if文とは
プログラムを作っていく中で条件に合わせて実行する処理を変えたいケースがあります。条件を分岐させたい時に使用するのがif文です。

###構文

```javascript

if(条件式１){
//条件式１がtrueの時に実行される処理
}
```
if文は条件式を重ねる（繋げる）ことができる。条件式を重ねたいときは**else if**と書く。
else ifと書くことで条件式１が満たされなかったときの別の処理（条件式２）を作ることができます。else ifを使用することで複数の条件式を作ることができる。

```javascript

if(条件式１){
//条件式１がtrueの時に実行される処理
}else if(条件式２の処理){
//条件式１がfalse,かつ条件式２がtrueの時に実行される処理
}
```

すべての条件式が満たされなかった場合の処理は**else**と書きます。

```javascript

if(条件式１){
//条件式１がtrueの時に実行される処理
}else if(条件式２の処理){
//条件式１がfalse,かつ条件式２がtrueの時に実行される処理
}else{
//すべての条件式がfalseだった時に実行される処理
}
```

##簡略化したif文の書き方

if文を簡略化して書くことができるみたいです。**ショートハンド**とも呼ばれてます。
プロのエンジニアさんはよくショートハンドを使用してプログラムを書いてると聞いたことがあります。
下の例は「値の存在確認」のプログラムをロングハンドとショートハンドで書いてみました。

###ロングハンド①

```javascript

//もし、likeJavaScriptがtrueだった場合、hogeの処理が実行されます。
if (likeJavaScript === true){
    hoge = "hogehoge";
}

```

###ショートハンド①

```javascript

if (likeJavaScript){
    hoge = "hogehoge";
}

```

###ロングハンド②

```javascript

//もし、likeJavaScriptがtrueじゃなかった場合、hogeの処理が実行されます。
if (likeJavaScript != true){
    hoge = "hogehoge";
}

```

###ショートハンド②

```javascript
//hogeがtrueでない処理をしたい場合は、変数の前に「！」をつけます。
if (!likeJavaScript){
    hoge = "hogehoge";
}

```


##参考動画
[テックプレイ　if文とは](https://www.youtube.com/watch?v=xtVaaTfTJkE&list=PLjw-30bsJNVUpFTm9FDof8B91uI3iorDH&index=7)

##参考サイト
[あなたが知らないJavaScriptの便利すぎるショートハンド19選](https://www.webprofessional.jp/shorthand-javascript-techniques/)
python3のPILでexifが読み込めない時

普通にjpgファイルのexifを読み込もうと思うと、検索して真っ先に出てくるのが以下のコード。
ちなみにやろうとしていたのは、Amazon Photosにバックアップしようとして上書きされたタイムスタンプをexifデータで戻す作業。
(気軽にタイムスタンプを書き換えるサービス、ホント良くない！)

ファイル操作のループは省略。`targetfile`にフルパスで入ってると思いねェ。
PILでファイルを開いたままos.utimeで書き換えてるのは気持ち悪いと思うが、exifデータに撮影日時が入っている時だけ処理するのをフラグとか面倒なことしないで書くとこうなった。
気になる人は直して使ってちょ。

```python
from PIL import Image
import time
import datetime
import os

with Image.open(targetfile) as im:
    exifdict = im._getexif()
    if 36867 in exifdict:
        newtime = time.mktime(
            datetime.datetime.strptime(
                exifdict[36867],
                '%Y:%m:%d %H:%M:%S'
            ).timetuple()
        )

        os.utime(targetfile, (newtime,newtime))
```

で、終わりと思いきや、いくつかの写真を読み込もうとしたところ、空の辞書が返却されてしまって困ることがあった。
で、他にexif情報にアクセスする方法を調べてみると、piexifを使う方法が紹介されていて、この場合は全ての写真のexif情報にアクセスできた。
anaconda3で入れてもこいつは入ってこないので、まずインストールから。

```sh
pip install piexif
```

こいつでexif情報にアクセスするとbyte stringで帰ってくるので、デコードすること。
他は同じ。

```python
import piexif
from PIL import Image
import time
import datetime
import os

with Image.open(targetfile) as im:
    exifdict = piexif.load(im.info['exif'])["Exif"]
    if 36867 in exifdict:
        newtime = time.mktime(
            datetime.datetime.strptime(
                exifdict[36867].decode(),
                '%Y:%m:%d %H:%M:%S'
            ).timetuple()
        )

        os.utime(targetfile, (newtime,newtime))
```
Progateで学んだ内容をまとめていく＿JavaScript6学習コースI

Progateの学習コースで学んだ内容を自分用に記事にまとめて記憶の定着と復習の為にQiitaにメモしておこうと思います。参考になるかはわかりませんが、他の学習されている方にもシェア致します。
入力の内容は野球に関するものですが、実際の成績には関係がありません。

###### - 出力 

```
console.log("横浜DeNAベイスターズ");
console.log("4位");
console.log(1+3);
console.log("横浜DeNAベイスターズは"+4+"位です");

//文字列はシングルorダブルクオーテーションで囲む
```
`横浜DeNAベイスターズ`
`4位`
`4`
`横浜DeNAベイスターズは4位です`

###### - 変数と定数

```
let number   = 1;       //変数、変更可能
const team   = 6;       //定数、変更不可
console.log(number);
```
`1`

###### - テンプレートリテラル：文字列の中に定数（変数）を入れる

```
const team = 6;  
console.log(`セ・リーグは${team}チームです`);
//バッククオーテーションで囲む
```
`セ・リーグは6チームです`

###### - 演算子 

`A && B` AかつB
`A || B` AまたはB
`A === B` AとBが等しい 
`A !== B` AとBは等しくない

###### - 条件分岐(if,else,else if)
if(条件式1){
  条件式がtrueのときの処理;
}

```
let ERA = 5.20 　　　　//ERA＝防御率
if(ERA > 5.00){ 　　　　　　　　　　　　　// 防御率が5.00より大きい時
  console.log("最下位です"); 　　　　　　// "最下位です"と出力
} 
```
`最下位です`


if(条件式1){
  条件式がtrueのときの処理;
}else if(条件式2){
  条件式1がfalse,条件式2がtrueのときの処理
}else{
条件2がfalse
}

```
let ERA = 3.61 
if(ERA > 5.00){ 　　　　　　　　　　　　　// 防御率が5.00より大きい
  console.log("最下位です"); 　　　　　　// "最下位です"と出力
} else if {ERA < 3.50　　　　　　　　　　// 防御率が5.00以下　かつ　3.50より小さい
  console.log("1位です");　　　　　　　　// "1位です"と出力
} else {　　　　　　　　　　　　　　　　　// 防御率が5.00以下　かつ　3.50以上
　console.log("打率次第です")　　　　　　// "打率次第です"と出力
} 
```

`打率次第です`



###### - switch文（定数による条件分岐する方法）

switch (条件1の値){
　　case値1 :
  　　　条件1の値とcase値1が等しいときの処理};
　　　break;

```
const city = "広島";

switch (city){
  case "広島" :　　　　　　　　　　　　　//cityが"広島"の時
  　console.log("広島東洋カープ"); 　　 //"広島東洋カープ"と出力
 　 break;
}
```
`広島東洋カープ`

```
const city = "西宮";

switch (city){
  case "広島" :　　　　　　　　　　　　　//cityが"広島"の時
  　console.log("広島東洋カープ"); 　　 //"広島東洋カープ"と出力
 　 break;
  case "名古屋" :　　　　　　　　　　　　//cityが"名古屋"の時
  　console.log("中日ドラゴンズ"); 　　 //"中日ドラゴンズ"と出力
 　 break;
　default :　 //elseと同じ　　　　　　　//cityが"広島","名古屋"以外の時
    console.log("球団はありません");　　//"球団はありません"と出力
　　break;
}
```
`球団はありません`
HTMLの中級編をやってみて

こんにちは。
[未来電子テクノロジー](https://www.miraidenshi-tech.jp/intern-content/program/)でインターンをしているtakumaです。
最近、新たな挑戦として、プログラミングを学び始めました。
プログラミングを始めた理由は、自分で何か新しいものを1から作ってみたかったからです。
今は、progateでプログラミングの基礎を固めています。
そこで今回は、HTML中級編をやってみた感想を書いていこうと思います。

□エラーの原因を突き止めるのが大変
正直、初級編ではあまりエラーが起きなかったため、スムーズに終えられました。
しかし、中級編になると、少しエラーの回数が増えてしまいました。
エラーの例としては、違うコードを使っていたり、コードのスペルが間違っていたりなどがありました。
その際、どこでエラーが起きているのかが分からず、苦労することがありました。
その結果、予定していたより多くの時間がかかってしまいました。
これからは、エラーが起きた際に、より慎重に原因を突き止めようと思います。
また、分からない時は、潔く答えを見ることも大切かなと思っています。

□それでもやっぱり楽しい
まだまだ初心者ですが、少しづつプログラミングが楽しいと思えるようになってきました。
その理由は、前回の記事でも書いた通り、コードが形として反映されるからです。
一見、何を書いているのか分からないですが、書き終えた後に見てみると、ホームページの色が変わっていたり、新しいボタンがついていたりするため、もっとやりたいと思えるようになりました。
なので、今後はもっとインプットの量を増やすことに焦点を置いて、コードの書き方を学んでいこうと思います。

□まとめ
以上、HTML中級編をやってみた感想を書いてみました。
これからは、pHSについて学ぶので、終了次第、記事にしたいと思います。
fluentdでApacheログを監視するためのrotatelogs設定

#fluentdでApacheのログ監視をするよ
監視担当の要望でaccess_logをfluentdで監視するにあたり名前を固定化してほしいとの要望があり対応を入れた。
最初はlogrotationで対応しようとしたのだがaccess_logがでかすぎなのと連携しているTomcatとの切断とかが終わる前にApacheが起動してしまいログがきれいに回らなかったので2.4から入ったオプションで対応した。


###access_logの設定
10分間隔ログ取得
CustomLog "|/usr/sbin/rotatelogs -c -l -L /var/log/httpd/access_log /var/log/httpd/access_log.%Y%m%d%H%M 600" combined

1時間間隔ログ取得
CustomLog "|/usr/sbin/rotatelogs -c -l -L /var/log/httpd/access_log /var/log/httpd/access_log.%Y%m%d%H 3600" combined

1日間隔ログ取得
CustomLog "|/usr/sbin/rotatelogs -c -l -L /var/log/httpd/access_log /var/log/httpd/access_log.%Y%m%d%H 86400" combined

1週間間隔ログ取得
CustomLog "|/usr/sbin/rotatelogs -c -l -L /var/log/httpd/access_log /var/log/httpd/access_log.%Y%m%d 604800" combined

###error_logの設定
10分間隔ログ取得
ErrorLog "|/usr/sbin/rotatelogs -l -c -L /var/log/httpd/error_log  /var/log/httpd/error_log.%Y%m%d%H%M 600"

1時間間隔ログ取得
ErrorLog "|/usr/sbin/rotatelogs -l -c -L /var/log/httpd/error_log  /var/log/httpd/error_log.%Y%m%d%H 3600"

1日間隔ログ取得
ErrorLog "|/usr/sbin/rotatelogs -l -c -L /var/log/httpd/error_log  /var/log/httpd/error_log.%Y%m%d%H 86400"

1週間間隔ログ取得
ErrorLog "|/usr/sbin/rotatelogs -l -c -L /var/log/httpd/error_log  /var/log/httpd/error_log.%Y%m%d 604800"

ハードリンク設定を始めて使ったけどfluentdと併用するなら今後はスタンダードになっていくじゃないだろうか。

##※ただしrotatelogsはログを自動で削除してくれないので削除シェル＋cron対応が必要なので注意。

初期構築前に言ってくれればもうちょう対応早くできたのに・・・と思うこのごろ。

メモ：
LoadModule log_config_module modules/mod_log_config.so
データサイエンスアカデミー無料説明会

##[データサイエンスアカデミー無料説明会](https://data-science-academy.connpass.com/event/133546/)

####HP概要
『データサイエンスアカデミー』では、7月から受講開始する第4期生を募集しております。
当説明会では、設立の背景から実際の受講カリキュラムまで入学に関する詳細をご案内致します。

また参加者の方に『データサイエンティストとは？』から『データサイエンス業界の今の状況』を知って頂く初心者向けプログラムもご用意。

データサイエンティストを目指す方が気軽にご参加頂ける無料セミナーとなります。
質疑応答の時間もございますのでご参加される方は気軽にご質問下さい。

####説明会
#####データサイエンス、データサイエンティストとは
・データに対して多角的な手法を適所に使える、選択でき問題を解決できる（新たな価値を生み出せる）人間→データサイエンティスト
・マーケティングに活用
・データサイエンティストの仕事の流れ
　目的の確認、データの理解→可視化→コンサルティング（ここは業界によってはやらない場合もある）
・必要スキルとしては「コンサルティング（★）」「IT・論理的思考」「数理統計」全てがないとできない。
　★が忘れられがち。かなり重要。
・データサイエンティストとしてのスキルがないと、先のキャリアにはなれない。

#####メモメモ
・受講ができない場合は、動画での受講とSlackでの問い合わせ
・テストも受け忘れは、追試がある。テスト落ちた場合は1回だけ追試あり
・４，７，１０，１月の4回の機会がある。直近7月の締め切りは6/24（月）※ここは意思表示

#####資料
<iframe src="//www.slideshare.net/slideshow/embed_code/key/jhK8o4outmoPE4" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/secret/jhK8o4outmoPE4" title="DataScienceAcademy" target="_blank">![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160422/06f3b3bf-8eb6-cd75-3c52-5089cc3d8bf8.png)</a> </strong>
【SQL】SELECT文の基本的な使い方(ORDER BY~HAVING)

# SELECT文の基本的な使い方 Lv.2

Lv.1がない理由は、
すでに、マーケティングチームの人に教えくれたので、ないです。

SELECT文に対して、
基本的な内容を整理します。

# ORDER BY

テーブルからSELECTでデータを照会する時、
「ORDER BY」を使うと、指定されたカラムを基準に並べ替えることができます。
昇順（ASC）または降順（DESC）二つのソート方法があります。
基本は、昇順（ASC）です。→ 昇順（ASC）は、省略が可能です。

Member Table

|id |name|gender|grade|date|
|:-:|:--:|:----:|:---:|:--:|
|1  |Akagi|female|94|1992-01-15|
|2  |Yamada|male|88|1989-05-05|
|3  |Uchida|female|52|1990-12-09|
|4  |Sakurai|male|99|1985-06-08|
|5  |Midoriya|male|10|1995-11-11|
|6  |Sakura|female|60|1970-04-01|
|7  |Ishihara|female|33|1988-03-15|

```	
SELECT * FROM Member;
SELECT * FROM Member ORDER BY grade ASC;
SELECT * FROM Member ORDER BY grade;
SELECT * FROM Member WHERE gender = "female" ORDER BY grade;
SELECT * FROM Member WHERE gender = "female" ORDER BY grade desc, date;

```

```	
SELECT * FROM Member WHERE gender = "female" ORDER BY grade desc;
```

|id |name|gender|grade|date|
|:-:|:--:|:----:|:---:|:--:|
|1  |Akagi|female|94|1992-01-15|
|6  |Sakura|female|60|1970-04-01|
|3  |Uchida|female|52|1990-12-09|
|7  |Ishihara|female|33|1988-03-15|


# GROUP BY

COUNT関数でデータを照会すると、全ての合計数を計算します。
タイプ別に合計したい時に、「GROUP BY」を使います。

Member2 Table

|id |name|gender|Country|date|
|:-:|:--:|:----:|:---:|:--:|
|1  |Akagi|female|Japan|1992-01-15|
|2  |Yamada|male|Japan|1989-05-05|
|3  |Uchida|female|Korea|1990-12-09|
|4  |Sakurai|male|USA|1985-06-08|
|5  |Midoriya|male|USA|1995-11-11|
|6  |Sakura|female|Japan|1970-04-01|
|7  |Ishihara|female|Korea|1988-03-15|

```	
SELECT COUNT(name), Country FROM Member2 GROUP BY Country;
SELECT COUNT(name), Country FROM Member2 WHERE date > "1970-01-01" GROUP BY Country;
```

```	
SELECT COUNT(name) as cnt, Country FROM Member2 GROUP BY Country;
```

|cnt |Country |
|:-:|:--:|
|3  |Japan|
|2  |Korea|
|2  |USA|

# HAVING

GROUP BYを使う時、特定な条件をかけたい場合があります。
その時、使うのが「HAVING」です。
簡単に言うと、GROUP BYに使うWHERE文です。

```	
SELECT COUNT(name) AS cnt, Country FROM Member2 GROUP BY Country HAVING cnt >= 2;
SELECT COUNT(name) AS cnt, Country FROM Member2 WHERE date > "1970-01-01" GROUP BY Country HAVING cnt >= 2;
SELECT COUNT(name) AS cnt, Country FROM Member2 WHERE date > "1970-01-01" GROUP BY Country HAVING cnt >= 2 ORDER BY cnt desc;
```

```	
SELECT COUNT(name) AS cnt, Country FROM Member2 GROUP BY Country HAVING cnt > 2;
```

|cnt |Country |
|:-:|:--:|
|3  |Japan|


# SELECT文の定義順
①select：照会するカラム名を明示
②from：テーブル名を明示
③where：条件を明示
④group by：グループ化するフィールド名を明示
⑤having：グループ化されたデータに適用する条件を明示
⑥order by：並べ替えの基準となるフィールド名を明示

# SELECT文の実行順
①from：実際の照会データがあるテーブルをまずメモリに認識
②where：条件を検索して照会するデータじゃないものを除く。
③group by：レコードを指定したフィールドごとに、重複したものを一つにまとめてグループ化する。
④having：グループ化されたデータに条件を適用して満足していないものは除く。
⑤select：実際のデータ値を出力する。
⑥order by：データを並べ替えて示す。
pi Music Boxをupdateする（その３）

いよいよGoogle Play Music（gmusic）をmopidyで利用できるようにするのだが、
以前のpiMusicBoxでもこれはできている。
しかし、gmusicを聴いているとランダムに突然再生が中断されるという現象が発生する。

https://github.com/mopidy/mopidy-gmusic/issues/161
による
/lib/python2.7/site-packages/mopidy/audio/actor.py
へのパッチを当てるのがpiMusicBoxをupdateする目的。

# gmusicapiのインストール
基本、pip installでいけるはずだが、いろいろと準備が必要。

`$ git clone https://github.com/simon-weber/gmusicapi.git`
して得られるrequirements.txtの内容をinstallする。

`$ sudo pip install -r requirements.txt`

途中でエラーとなる場合は
`sudo pip install proboscis==1.2.6.0`
と単独でinstallしもう一度
`$ sudo pip install -r requirements.txt`
何回か繰り返す。

sixは1.10.0にversion downする必要がある
最終的にrequirements.txtのパッケージが全てinstallされたら

`$ sudo pip install gmusicapi`
として
Successfully installed gmusicapi-12.1.0
となればOK。

# Mopidy-Gmusicのinstall
こちらも準備が必要

`$ sudo apt-get install libxml2-dev libxslt1-dev`
`$ sudo pip install Mopidy-Gmusic`

# /etc/mopidy/mopidy.confの編集

https://qiita.com/blueknight611jp/items/265ad4fb966198e6d188
に従って
[gmusic]
の項目を設定。

これでmopidyをrestartすればBROWSEにGoogle Musicが出てくるはず。

すべてのTrack/Artist/Albumが表示されるようになるには時間がかかる
Radioだと表示が早い。

#中断対策
`sudo vi /usr/lib/python2.7/dist-packages/mopidy/audio/actor.py`

`#_GST_PLAY_FLAGS_AUDIO = 0x02`
`_GST_PLAY_FLAGS_AUDIO = 0x02 + 0x80`
と修正してmopidyをrestartする。
コンピュータの仕組みを勉強しながらC言語やろうぜ！　#2

# 前回のあらすじ

https://qiita.com/GRGSIBERIA/items/bd3e5edb8e55117fd891

# コメントでメモを取る

プログラミングの重要な機能として**コメント**があります。**コメントした部分はプログラムとして実行されません**。

コメントを書くのはプログラマになるならば非常に重要な基礎教養とも言えます。ここではコメントの心得については差し控えますが、C言語にはコメントを書く機能があります。

まずは大筋としてのコメントを見てみましょう。

```c
/**
* プログラムの開始地点
* @return exit code
* @note main関数は引数がない(void)と任意のコマンドライン引数を取る
*/
int main()
{
    // 何もしない
    return 0;     // OSに正常終了を通知する
}
```

## 行コメント

**行コメント**とは、`//`で始まるコメントです。

```c
// 行コメント
return 0;    // 行コメント
```

このように、行の頭に行コメントを書く方法と、プログラム行の終わりにコメントを書く方法があります。

## 複数行のコメント

長いコメント、何か目立たせたいコメントなどは**複数行のコメント**を使います。行コメントは、`/*`と`*/`の間で囲った部分が問答無用でコメントになります。

```c
/******************************************************************************

                            Online C Compiler.
                Code, Compile, Run and Debug C program online.
Write your code in this editor and press "Run" button to compile and execute it.

*******************************************************************************/
```

このコメントとかパッと見てきれいですね。頭の部分`/*`とお尻の部分`*/`で挟まっている間はコメントです。なので、このコードは全文がコメントになります。

この例はかなり大げさですが、実用的な側面としてプログラムの単位ごとに目立たせる目的で複数行コメントを書きます。

```c
    /**
     * とても難しい処理
     **/
    printf("Hello, world");
```

さらに実用性を求めるとDoxygenというプログラムを使って、特殊なコメントを書いた部分を抽出して自動的に仕様書（のようなもの）を作ることができます。

興味があればぜひ参照してみてください。

https://qiita.com/wakaba130/items/faa6671bd5c954cb2d02

# おわりに

コメントを書く方法について学習しました。プログラムと関係ないように見えますが、コメントはプログラミング言語の中で比較的重要なポジションにあります。

コメントがないとなぜそのコードを書いたのかわからなかったりするので、最初のうちはたくさんコメントを残しましょう。復習になります。
macOS Mojaveでphpbrewをインストールする

# 概要
PHPのバージョン管理するためとxdebugが簡単にインストールできると聞き、これはphpbrewを導入するしかないと思い立ったところ、エラーで結構詰まったのでその話を書きます。

# `brew link --force` ができない？！
phpbrewをインストールするために色々な記事を読んだ感覚としては、

- インストールしようとしたら、ライブラリがないことでエラーが出る
- `brew install` で必要なライブラリをインストールする
- `brew link --force` でライブラリのシンボリックリンクを作成する　←これ
- 再インストールすると成功する

という流れでしたが自分のMac環境で実行すると以下のワーニングが出てしまって、このままインストールを続行してもライブラリが見つからないというエラーが頻出して作業中断してしまいました（もちろん環境変数の設定もしましたよ）。

```bash

$ brew link zlib --force

Warning: Refusing to link macOS-provided software: zlib
For compilers to find zlib you may need to set:
  export LDFLAGS="-L/usr/local/opt/zlib/lib"
  export CPPFLAGS="-I/usr/local/opt/zlib/include"
```

どうやらhomebrewからMacが提供しているソフトウェアにリンク貼ることができなくなってしまっていたみたいでした。
https://nathankleyn.com/2019/01/15/homebrew-system-util-breaking-change/

# 解決策
以下のように設定してコマンド投げたらうまくいきました！

```bash
$ phpbrew install 7.2.9 +default +mysql +pdo \
+bz2="$(brew --prefix bzip2)" +zlib="$(brew --prefix zlib)" \
+curl="$(brew --prefix curl)" +iconv="$(brew --prefix libiconv)"
```

何をしているかというと `phpbrew install` を実行しとときに出力されたエラーのライブラリに対してパスを教えてあげています。
各ライブラリのパスを直打ちしてもいいのですが、 `brew --prefix`でパスを出力してくれるので便利です。

```bash

$ brew --prefix zlib
/usr/local/opt/zlib
```
RxSwiftのSubjectとRelayについて理解する

# はじめに
「比較して学ぶRxSwift」を読んで、SubjectやRelayについての理解が深まったので、整理しました。

# Subject・Relayとは

Observableはイベントを検知するためのクラスですが、
一方SubjectとRelayはイベントの検知も、イベントの発生もできるクラスです。

|                 | 流せるイベント                  | バッファ |
|:----------------|:----------------------------|:-------|
| PublishSubject  | onNext, onError, onComplete | 持たない |
| BehaviorSubject | onNext, onError, onComplete | 持つ 　  |
| PublishRelay    | onNext                      | 持たない |
| BehaviorRelay   | onNext                      | 持つ    |

※ Subjectは３種類のイベントを流すことができ、RelayはonNextのみ。
※ Publishはバッファを持たず、Behaviorはバッファを持つ。

## バッファとは
BehaviorSubject/Relayは、subscribe時に1つ過去のイベントを受け取ることができる。
最初にsubcribeするときは、宣言時に設定した初期値を受け取る。

## 用途
* Subject 
   * エラーによって処理を分けたいとき(通信処理やDB処理などでメッセージを出したい）

* Relay
   * UIに値をバインドする(イベントを拾えない状態にならないようonNextのみを保証したい)

## RelayでのonNextイベント
Relayで、onNextのイベントを流すには、acceptのメソッドを使用する。
内部的にはSubjectのラッパーとなっており、onNextを呼んでいる。

```swift:RxSwift/PublishRelay
public final class PublishRelay<Element>: ObservableType {
    private let _subject: PublishSubject<Element>
    
    // Accepts `event` and emits it to subscribers
    public func accept(_ event: Element) {
        self._subject.onNext(event)
    }
   ...
}
```

# 参考

[比較して学ぶRxSwift](https://booth.pm/ja/items/1010258)
明日はgcloudやろう

# 今日は何も出来なかった
- 外出したり疲れたり
- 明日から鳥取に1週間出張。普段より時間が取れるので色々ゆっくりやろう
- おやすみなさい

# 今日の気持ち
- 父の日という事もあり、好物のカレーを作ってもらった
- 子供達に誇れるエンジニアでいる、そしてなる！
SpringBootのFilter適用順

#目的

- SpringBootで利用されるFilterについて主に適用順に関して細かい所まで見ていく

#前提知識

- FilterはFilterRegistrationBeanでラップしてBean登録すると順番や適用URLなどを設定できる
- Orderedインターフェースを実装しても順番をコントロールできる
- Filterを直接Bean登録すると一番最後に適用される
- AutoConfigureでデフォルトで登録されるfilter類がいくつかある

https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-embedded-container-servlets-filters-listeners-beans
#疑問点

- Orderがかち合った場合はどうなるのか?
- Requestが来た時にどのようにFilterが展開されるのか

#検証
##Requestが来た時にどのようにFilterがセットされるか？
- `ApplicationFilterFactory`がFilterChainを作成している

```java:ApplicationFilterFactory.java
public static ApplicationFilterChain createFilterChain(ServletRequest request,
            Wrapper wrapper, Servlet servlet) {

        //省略

        // Acquire the filter mappings for this Context
        StandardContext context = (StandardContext) wrapper.getParent();
        FilterMap filterMaps[] = context.findFilterMaps();

        // If there are no filter mappings, we are done
        if ((filterMaps == null) || (filterMaps.length == 0))
            return filterChain;

        // Acquire the information we will need to match filter mappings
        DispatcherType dispatcher =
                (DispatcherType) request.getAttribute(Globals.DISPATCHER_TYPE_ATTR);

        String requestPath = null;
        Object attribute = request.getAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR);
        if (attribute != null){
            requestPath = attribute.toString();
        }

        String servletName = wrapper.getName();

        // Add the relevant path-mapped filters to this filter chain
        for (int i = 0; i < filterMaps.length; i++) {
            if (!matchDispatcher(filterMaps[i] ,dispatcher)) {
                continue;
            }
            if (!matchFiltersURL(filterMaps[i], requestPath))
                continue;
            ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
                context.findFilterConfig(filterMaps[i].getFilterName());
            if (filterConfig == null) {
                // FIXME - log configuration problem
                continue;
            }
            filterChain.addFilter(filterConfig);
        }

        //省略

        // Return the completed filter chain
        return filterChain;
    }
```

この実装を覗いてもわかるように、Filterの適用順序自体は`StandardContext`から取り出した時点で決まっている。

Contextへは`ServletContextInitializerBeans`が登録を行っているが`FilterRegistrationBean`と`Filter`で登録は別々に行われる。
`FilterRegistrationBean` => `Filter`という順番で取りあえず格納される。
そののちOrder要素に沿ってソートされる。

ソートはOrderの番号に従って整列されるのが前提であるが、Orderが被った場合は下記の順番で並ぶ

1. `FilterRegistrationBean`　=> `Filter`
2. Beanの登録順

したがって、下記のようなConfigを指定すると

```Java:FilterConfig.java
public class FilterConfig {



	@Bean
	public FilterRegistrationBean fugaFilterConfig() {
		FilterRegistrationBean bean = new FilterRegistrationBean(new FugaFilter());
		bean.setOrder(Ordered.LOWEST_PRECEDENCE);
		return bean;
	}


	@Bean
	public Filter hogeFugaFilterConfig() {
		Filter bean = new HogeFugaFilter();

		return bean;
	}

	@Bean
	public Filter hogeFilterConfig() {
		Filter bean = new HogeFilter();
		return bean;
	}
}
```
FugaFilter => HogeFugaFilter => HogeFilterという順でFilterが適用される。
【秀丸】grepの結果に検索文字列が使用されている関数名を追記するマクロ

```c++
//grepの結果に検索文字列が使用されている関数名を追記するマクロ
//①タブモード
//②grep結果ウィンドウを右端に置いておく
//③grep結果ウィンドウをアクティブにしてから実行


call Initialize;
call Main;
call Finalize;
endmacro;


Initialize:
	disabledraw;																					//画面の更新を抑止

	//grep結果バックアップ
	call AllCopy;
	newfile;																						//新規ファイルを開く(resultまとめ用)
	newfile;																						//新規ファイルを開く(grep結果バックアップ)
	call AllPaste;
	prevtab;
	prevtab;

	//grep結果の行数カウント
	gofileend;																						//ファイルの末尾にカーソルを移動
	#MAX_COLUMNS = y;																				//カーソル位置(行)を取得
	gofiletop;																						//ファイルの先頭にカーソルを移動

	#lineNo = 0;
	$C_FUNC_SEIKI_GREP = "^[_a-zA-Z][^\\(=;:]*[\\t ]+\\**[_a-zA-Z][_a-zA-Z0-9]*\\([^;]*$";			//関数名取得正規表現(C言語)
	$FILE_NAME_X = "):";																			//ソース名を抽出するために利用
	return;


Main:
	while ( #MAX_COLUMNS > #lineNo )
	{
		call SearchFunction;
	}
	
	nexttab;
	replaceall "\n【改行削除用文字列】", "",regular;
	call AllCopy;

	prevtab;
	call AllPaste;
	return;


SearchFunction:
	#lineNo = #lineNo + 1;
	moveto2 0, #lineNo;
	selectline;

	$findText = gettext(seltopx,seltopy,selendx,selendy);											//grep結果のある一行
	#fileNameEndNo = strstr( $findText, $FILE_NAME_X );												//ファイル名までの文字盤目を検索
	$fileName = leftstr( $findText, (#fileNameEndNo + strlen($FILE_NAME_X)) );						//ファイル名抽出
	$grepText = rightstr( $findText, (strlen($findText) - #fileNameEndNo - strlen($FILE_NAME_X)) );	//検索文字列抽出
	
	tagjump;

	searchup2 $C_FUNC_SEIKI_GREP, regular;															//関数名を上方向に検索
	if(result)
	{
		selectline;
		$functionText = gettext(seltopx, seltopy, selendx, selendy);								//関数名取得
	}
	else
	{
		message "関数がみつかりません。";
	}

	backtagjump;

	nexttab;
	insert $fileName + "\t" + $functionText + "【改行削除用文字列】" + $grepText;
	prevtab;

	return;


Finalize:
	enabledraw;          																			//画面の更新を許可します
	message "完了";
	return;


//*****************************//
AllCopy:
	selectall;
	copy;
	return;


AllPaste:
	selectall;
	paste;
	return;
```
Pythonで2つ以上の関数合成

最近Haskellで関数型プログラミングの勉強を始めて、幸せになっているKekehoです。
関数合成というのができることを知って、これPythonでもやりたい!となったので早速実装していきましょう。

これといって難しいこともなく、シンプルに実装できます。

# そもそも関数合成とは
数学でやったアレです。データxに対してf → gと関数を適用していきたいとき、

```math
g(f(x))
```
って書きますよね。数学っぽく書くと、

```math
g \circ f
```
になります。
Pythonで書くと、

```python
# 事前に関数f, gは定義されているとする
f_to_g = lambda x: g(f(x))
```
ってなりますね。
これで引数xに関数をf→gという順番で適用させていき、その値を返してくれるという**合成関数**f_to_gができました。
嬉しくなっちゃいますね。

こんな感じで、手作業でいいならシンプルに書けてしまいます。記事が終わってしまいそうですね。

# しんどい
しかし、もっとたくさん関数合成をしたい場合はどうすればいいでしょうか。
例えば、引数xに対してf→g→h→i→j...と関数を適用していきたい場合は?

もちろん`lambda x: j(i(h(g(f(x))))`と書けばいいだけです。
しかしながら、なんだか右から左に読んでいかないと適用順が把握できなくて直感的ではないですね。
更に、括弧が多すぎたりして読み書きがしづらいです。

アラビア語とLispが堪能な人材を雇う前に、関数合成をしてくれる関数を書くべきです。
↓こんな感じの関数を作りたいですね。

```python:理想像
# j⚪︎i⚪︎h⚪︎g⚪︎f
composited = composite(f, g, h, i, j)  # 合成関数compositedを作成

```

# 実装例
再帰で実装してみました。
流石に1000個以上もの関数を合成する場面はまずないと思うのですが、もしやりたいなら

```python
import sys
sys.setrecursionlimit(任意の数)  # 再帰のリミット数を設定(デフォルトは1000)
```
でいい感じに設定したほうがいいかもしれません。

以下に実装例を示しておきます。
分かりづらいところあったらコメントで指摘していただければ嬉しいです。

```python:実装例
from typing import List
from types import FunctionType, LambdaType


def composite(*func: List[FunctionType]) -> LambdaType:
    if len(func) < 2:
        # エラー処理(流石に関数は2つ以上ないと合成もクソもない)
        raise TypeError(f'composite expected over 2 arguments, but got {len(func)}')
    if len(func) == 2:
        # 再帰の末尾
        return lambda *args, **kwargs: func[1](func[0](*args, **kwargs))

    # 再帰でぶん回す(((((((((((っ･ω･)っ ﾌﾞｰﾝ
    return lambda *args, **kwargs: composite(*func[1:])(func[0](*args, **kwargs))
```

# テスト
実際使ってみましょう。あくまでも例なので適当です。

試しに、人名をイニシャルに加工する合成関数を考えてみます。`('taro', 'yamada')` → `'T.Y'`

ファーストネームとラストネームを受け取るデータとしましょう。 `'taro', 'yamada'`
**heads**関数でそれぞれ頭文字を取る `['t', 'y']` → **dot_join**関数で結合 `'t.y'` → **str.upper**関数で大文字に `'T.Y'`
こんな感じで関数を適用していけばOKそうですね。

```python:test.py
import composite # さっき書いたcomposite関数をいい感じにimportしておいてください

heads = lambda first, last: (first[0], last[0])
dot_join = lambda sequence: '.'.join(sequence)

name_to_initial = composite(heads, dot_join, str.upper)
print(name_to_initial('taro', 'yamada'))
```

```shell
$ python3 test.py
T.Y
````

やったね!

# 感想
Pythonは関数も第一級オブジェクトなので、簡単に実装できて嬉しかったです。
goステートメントのgo func() {} ()の最後の丸括弧()が何かわからなかったのでメモ


以下のようなコードの中にある `go func() {} ()` の最後の丸括弧 `()` がついている理由がわからなかったので調べた。
deferでも同じかもしれない。

```goroutine.go
package main

import (
    "fmt"
	"time"
)

func main() {
	go func() {
		fmt.Println("goroutine")
	}() // この丸括弧()の意味がわからなかった
	time.Sleep(time.Second)
}
```

[ドキュメント](http://golang.jp/effective_go#goroutines) には `関数を呼び出すために必要。` とあった。
最初どういうことかわからなかったけど、スターティングGo言語を読んで、無名関数が利用されているとわかった。


```
func() {
        fmt.Println("goroutine")
}
```
が無名関数で、この無名関数をgo文で呼び出す、ということで最後に `()` をつけている...んだと思う。


定義した関数を利用する形に書き直すと以下になる。


```goroutine.go
package main

import (
    "fmt"
	"time"
)

func f() {
    fmt.Println("goroutine")
}

func main() {
	go f()
	time.Sleep(time.Second)
}
```

## 参考

* [スターティングGo言語 (CodeZine BOOKS): 松尾愛賀: Books](https://www.amazon.co.jp/%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0Go%E8%A8%80%E8%AA%9E-CodeZine-BOOKS-%E6%9D%BE%E5%B0%BE-%E6%84%9B%E8%B3%80/dp/4798142417)
* [goステートメント - Goプログラミング言語仕様 - golang.jp](http://golang.jp/go_spec#Go_statements)
* [ゴルーチン - 実践Go言語 - golang.jp](http://golang.jp/effective_go#goroutines)
* [go - Why add "()" after closure body in Golang? - Stack Overflow](https://stackoverflow.com/questions/16008604/why-add-after-closure-body-in-golang)