OmniAICreator/Qiita-1.07M huggingface dataset:
Python で複雑な構造の dict オブジェクトをセレクタ的にアクセスできるようにする

概要
-----------------

JSON をロードしたときなど、配列とdictが何重にもネストしたような複雑な構造のdictオブジェクトができます。
このオブジェクトをアクセスしやすくする(とくにエラーまわりを解りやすくする)下記の機能を提供します。

- (中間でも末端でも)キーがないときにフルパスで解りやすいエラー:

```python
hoge = DataSelector(data)

hoge['aaa']['bbb']['ccc']

# ccc というキーは存在しないときのエラー
# path "ROOT.aaa.bbb.ccc" is not found!

# bbb というキーは存在しないときのエラー
# path "ROOT.aaa.bbb" is not found!

for v in hoge['aaa']['bbb']['ccc']:

# ccc が配列でないときのエラー
# path "ROOT.aaa.bbb.ccc" is not list!

for k, v in hoge['aaa']['bbb']['ccc'].items():

# ccc が dict でないときのエラー
# path "ROOT.aaa.bbb.ccc" is not dict!
```

- 値にアクセスしやすくするセレクタ:

```python
hoge = DataSelector(data)

# 値の取得
hoge['aaa']

# 複数階層も可
hoge['aaa.bbb']

# 値がない場合にデフォルト値（通常ならエラーが出る） ※ aaa がない場合でもデフォルト値
hoge.find('aaa.ccc', '')

# dict でループ
for k, v in hoge.items():
for k in hoge.keys():
for v in hoge.values():

# リストとしてループ
for v in hoge:
```


定義するクラス
-----------------


```python
class DataSelector:
    def __init__(self, data, parent_path='ROOT'):
        self.parent_path=parent_path
        self.data=data
    def __getitem__(self, path):
        return self.find(path)
    def _check_dict(self):
        if type(self.data) != dict:
            raise Exception(f'path "{self.parent_path}" is not dict!')
    def _check_list(self):
        if type(self.data) != list:
            raise Exception(f'path "{self.parent_path}" is not list!')
    def __iter__(self):
        self._check_list()
        for i, v in enumerate(self.data):
            yield DataSelector(v, f'{self.parent_path}[{i}]')
    def items(self):
        self._check_dict()
        for k, v in self.data.items():
            yield k, DataSelector(v, f'{self.parent_path}.{k}')
    def keys(self):
        self._check_dict()
        return self.data.keys()
    def values(self):
        self._check_dict()
        for k, v in self.data.items():
            yield DataSelector(v, f'{self.parent_path}.{k}')
    def find(self, path, default_val=None):
        paths = path.split(".") if type(path) == str else [path]
        _data = self.data
        _path = self.parent_path
        for p in paths:
            _path = f'{_path}.{p}'
            if p in _data:
                _data = _data[p]
            elif default_val is not None:
                _data = default_val
            else:
                raise Exception(f'path "{_path}" is not found!')
        if type(_data) == list or type(_data) == dict:
            return DataSelector(_data, _path)
        else:
            return _data
```

使い方
-------------

```python
res = list()
root = DataSelector(data)
for k1, v1 in root.items():
    # もしも root が dict でないなら下記のエラーで教えてくれる
    # path "ROOT" is not dict!
    bbb = v1['aaa.bbb']
    # もしも aaa や bbb が存在しないなら下記のエラーで教えてくれる
    # path "ROOT.aaa" is not found!
    # path "ROOT.aaa.bbb" is not found!
    for v2 in bbb:
        # もしも bbb がリストでないなら下記のエラーで教えてくれる
        # path "ROOT.aaa.bbb" is not list!
        res.append(dict(eee=v2['ccc']))
        # もしも ccc が存在しないなら下記のエラーで教えてくれる
        # path "ROOT.aaa.bbb[0].ccc" is not found!
```
Ubuntu 18.04.1 LTS にQt5 をインストールする

こんにちは、chlochanです。今日は Qt5 を Ubuntu 18.04.1 LTS にインストールしてみます。

#Install Qt 5 on Ubuntu 18.04.1 LTS 
wiki.qt.ioで探して見ましたが、Ubuntu 18.04.1 向けのインストール方法はなかったので、 Ubuntu 12.10 向けの以下のインストール方法を参考にインストールします。
[Install Qt 5 on Ubuntu](https://wiki.qt.io/Install_Qt_5_on_Ubuntu)

まず、インストーラーをダウンロードします。2018/11/23 時点での最新版は 5.11.2 です。

~~~bash
$ wget http://download.qt.io/official_releases/qt/5.11/5.11.2/qt-opensource-linux-x64-5.11.2.run
~~~
run ファイルに実行属性をつけて実行し、Qt5 をインストールします。

~~~bash
$ chmod +x qt-opensource-linux-x64-5.11.2.run
$ ./qt-opensource-linux-x64-5.11.2.run
~~~
g++ をインストールします。

~~~bash
$ sudo apt-get install build-essential
~~~
フォントライブラリをインストールします。

~~~bash
$ sudo apt-get install libfontconfig1
~~~
Qt Creatorを起動します。 Tools > Options を選択します。 Kits をクリックし、 Compilers タブ を選択します。 コンパイラが、自動的に検出(Auto-detected)、されていない場合は、手動でコンパイラを設定します。

OpenGL のライブラリをインストールします。

~~~bash
$ sudo apt-get install mesa-common-dev
~~~
以下の追加パッケージのインストールも必要です。次のコマンドを実行します。この追加パッケージのインストールで、-lGL が見つからない、という問題が起こる事を防げます。

~~~bash
$ sudo apt-get install libglu1-mesa-dev -y
~~~

上記の方法でダウンロードしてインストールする場合、ファイルの関連付けは自動的には行われません。よって関連づけるため、"Qt-Creator.desktop" という名前のファイルを作成し、ファイルに次のように入力します。なお、<ユーザー名> のところはインストールしたユーザー名にします。

~~~
[Desktop Entry]
Version=1.0
Encoding=UTF-8
Type=Application
Name=QtCreator
Comment=QtCreator
NoDsiplay=true
Exec=/home/<ユーザー名>/Qt5.11.2/Tools/QtCreator/bin/qtcreator %f
Icon=/home/<ユーザー名>/Qt5.11.2/5.11.2/Src/qtdoc/doc/images/landing/icon_QtCreator_78x78px.png
Name[en_US]=Qt-Creator
~~~
このファイルを自分のホームディレクトリの .local/share/applications に置きます。
また、同じディレクトリ内の "defaults.list" という名前のファイルに次の行を追加します。ファイルがなければ作成します。

~~~
text/qtcreator=Qt-Creator.desktop; 
~~~
ファイル /usr/share/applications/mimeapps.list を開き、次の行が存在しているか確認します。もし無い場合は、[added Associations] の下に追加します。

~~~
application/vnd.nokia.qt.qmakeprofile=qtcreator.desktop
~~~
もし、ファイル /usr/share/applications/mimeapps.list そのものが無い場合は作成し、ファイルに次のように入力します。

~~~
[added Associations]
application/vnd.nokia.qt.qmakeprofile=qtcreator.desktop
~~~

次のコマンドを実行します。

~~~bash
$ sudo update-mime-database /usr/share/mime
~~~
これで Qt がファイルの関連付けリストに追加されました。
EXCELのHLOOKUP関数の意外な使い道

#Excelで表（テーブル）検索といえばVLookUpさんの独擅場？
と思っていました。
HLookUpなんて要らん子だと
ところが、ある条件を満たす場合はVLookUpで検索できないけれどHLookUpでは検索できる場面があります。

#VLookUp関数の弱点
そもそもプログラマーだとテストデータを作成するのにExcelをよく利用するかと思います。なんせリレーショナルなデータを作成するのだから参照しまくりで作った方がデータの変更時は楽ですしね。
で、よく使うのがVLookUp関数なのですが、こいつの弱点は検索キーを左端に持ってこないといけないという事。で、そもそもDBの設計で必ずPKが1項目で済むというのは少なく、複数項目でPKとするテーブルが多くなります。なのでVLookUpに固執すると左端にPK列を結合したものを用意してVLookUpするのですが、PK以外で検索する場合もあります。となると左へ追加追加していってくと、正直見づらくなります。特にスクロールの固定をしたい場合はPK列を固定とするのでそれより左の列は全部常に表示される状態になりますので、検索用の見る必要のない列を残す羽目になります。列を非表示にしたり幅を0にしたりして何とかならなくもないのですが、気分的に邪魔なものは邪魔なのです。そこで、条件付きですがHLookUpさんの出番となります。

#HLookUp関数って左端の列が見出しで項目は行でレコードが列なんじゃねーの？
通常はそのように使用します。で、キーは本来は項目となる一番上の行を指定するはずなのです。

##それはそうと、テーブル好きですか？僕は構造化参照まで含めて大好きです
セル範囲をA1:H36とか書いても一々その範囲を見ないとわからないから嫌いなんですよね。だもんでテーブル名[#データ]とか=[@参照したい列名]とかで指定できる構造化参照を愛用しています。これExcel2007以降で追加された機能でテーブルに対して使用できます。詳細はググってもらうとして大事なのはテーブルにすると一般的なVLookUpで検索しやすい行がレコードの表になります。そして大事なのが列名は一番上の見出し行で重複しません。先の構造化参照で列名を指定に使うので、重複したらどっちやねん！？状態になるため、重複した見出しを入れようとしても後ろに番号が振られて必ずユニークになるのです。・・・おや？HLookUpさんは一番上の行を検索して探すんじゃぁ・・・

#テーブルなら実は検索でHLookUpも使えます
発想の転換。VLookUpもHLookUpも関数の解説では検索するキーデータをもとに最初の項目で検索してレコードを特定し、欲しい項目を指定して値を取得とありますが、テーブルを使えば項目名がユニークになるので、欲しい項目名をキーとして検索して項目を特定し、VLookUpでよく使用するMatchを使って列番号を取得するのと同じような感じでレコードを特定することができてしまいます。これのメリットはレコードの特定には端の項目である必要が無いという事です。なので、検索用に結合したデータを置く項目は左端にする必要が無いので右の方に逃がしてしまえるのです。

#で、結局どうやればいいの？
以下の通り
```
=HLOOKUP("内容",t一覧[#すべて],MATCH(F1,t一覧[管理番号],0)+1,FALSE)
```

「"内容"」は欲しい項目名を文字列で指定
「t一覧」はテーブル名
t一覧[管理番号]の「管理番号」が検索したい項目名
「F1」が検索したいデータの入ってるセル
「Match」の結果に＋１しているのは検索対象が見出しも含めた[#すべて]にしているので、1行下へずらす必要があるためなのでした。


![image.png](https://qiita-image-store.s3.amazonaws.com/0/244471/9a6bd4de-e94a-039a-fdb9-a15ef45d16e6.png)


ぶっちゃけ、Index＋Matchの方が良さ気なんだけど、HLookUpだって行レコードの形式でも検索できるよってかVLookUpよりも融通が効くからむしろHLookUpとVLookUp逆の方が便利になりそうじゃね？ってお話
Docker入門にもブラウザでできる「Katacoda」がおすすめ

# はじめに

[Docker 入門にはインストールなしで使える「Play with Docker」がいいと思う](https://qiita.com/tag1216/items/ec7228440f6eaf849cd6#ssh%E3%81%8C%E4%BD%BF%E3%81%88%E3%82%8B)
こちらに触発されまして
私もついこの前知った「Katacoda」を皆様とシェアしたいと思い書かせて頂きましたm(_ _)m

# Katacodaとは

[Katacoda](https://www.katacoda.com/)
ブラウザだけで、ハンズオン形式に学ぶ事ができたり
使い捨て環境で自由に遊ぶ事ができるサイトです。

Docker以外にもKubernetesやTensorflow、Golangなどなど
たくさんのコースを一通り学ぶことができますし、そのための環境が用意されています。

<img src='https://qiita-image-store.s3.amazonaws.com/0/198971/ca589b24-e9c0-ee9c-73a8-0685fd4f3732.png' width='80%'>

...何をモチーフにしてるんですかねぇ？

## 実際の画面

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/757abc8c-f874-5809-fc6a-573a244e28fd.png)

左側にテキストがあり、右側にコンソールが表示されています。
特定のコマンドを実行すると、次のSTEPに進めるようになっています。

## おすすめ理由

- 何から始めたらいいかわからない人でも、ハンズオンで学べる
- 無料で250以上のシナリオが学べる
- ブラウザだけで完結
- 難易度と所要時間が書いてある。
- Playgroundで自由に遊べる環境がある。

## コース一覧(一部)

いっぱいあって表示しきれないので[Kotacodaコース一覧](https://www.katacoda.com/learn)に飛んで覗いてみてください。
※1コース内に複数のシナリオがあります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/551c0e25-ea8b-cd57-1857-aab2160c0dff.png)


## 難易度と所要時間がわかる！

シナリオ開始前に、以下のようなWelcomeページが表示されるのですが
そこに難易度と所要時間が書いてあるので、隙間時間に自分のレベルにあった学習ができます。


![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/6b371b23-3dbd-a5e9-b80f-f7307bbe81da.png)

## Playgroundで自由に遊べる！

使い捨ての環境であんな事やこんな事ができちゃいます。
[このページ](https://www.katacoda.com/learn)を下の方にスクロールするとPlayground一覧があります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/8c25b406-6622-b3fb-1077-e7b49f03a8d8.png)

### 試しにUbuntuでnginxのコンテナを起動して、ブラウザからアクセスしてみる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/f0232e10-16a9-5efe-d6c3-a067ba77fd90.png)

Terminal横の「＋」をクリック
![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/cec4d869-e3c3-c6d8-8514-b5c7b0f79bca.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/42679cdd-0767-993c-a278-ab5928eaa6c9.png)


### 試しにGo実行環境でHello World

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/43d171e4-f585-8ba9-782a-3ccf34f967a8.png)

## まとめ

ブラウザからポチポチするだけで使い捨て環境を自由に使えるのは
めちゃくちゃ便利だなぁと思いました。
私も触りだして間もないので、いろいろ試してみたいと思います。

### 参考

[ブラウザで実行できるplaygroundまとめ]
(https://qiita.com/AkihiroSuda/items/71eb91752375829d30eb)
[コンテナ技術の学習するなら圧倒的にKatacodaがおすすめ #k8s #kubernetes](https://budougumi0617.github.io/2018/06/10/katacoda-introduction/)
OculusRiftDK2のセッティング


# 概要
OculusRiftDK2でホラーゲームを作成することになるにあたり、OculusRiftの設定をしていたのだが、
色々詰まりまくったので、OculusRiftの設定をし，Unityで使えるようにするまでの流れの備忘録を作成しておきたい。

# 参考資料
- [Oculusソフトウェアのインストールでエラー「KB2670838」「KB3033929」が出た時の対処法](https://mashironote.com/2017/07/31/oculus-error-kb2670838-kb3033929/)

# 開発環境
Unity 2017.4.0
OculusRiftDK2

# Oculusのセットアップ
**1.まず，Oculus公式サイトよりSetUp.exeをダウンロードしてくる。**

**2.SetUp.exeを起動する。**

  ※ここで，WindowsのUpdateをしろと求めてくることがあります。（自分は求められました）
    指定のものをインストールしてUpdateを試みたけど、またしてもWindowsのUpdateを求められた(内容は同じ)。
    解決策としては、SetUp.exeを起動する際に，コマンドプロンプトで起動するとうまくいった。

>SetUp.exe /bypassHotfixCheck

↑のような感じで起動すると，HotfixCheckをスルーできるのでセットアップを進めることができます。

**3.セットアップを流れのままに進めていく**
    ※センサー系のチェックとのところは何一つとして認識されないまま，スキップして進めたけど問題ありませんでした。

**4.続いて，Unityを起動し，File>BuildSettings>PlayerSettings>XRSetttingsにある,*Virtual Reality Support*にチェックを入れる**
  ※この際，virtual Reality SDKsにOculusと追加されてれば完了です。

**5.後はUnityEditorで実行をすればMainCameraで映るものが勝手にVRで映ってくれるようになるかと思います。**


#最後に
今回は初めてのVRのセットアップでかなり時間がかかってしまった。
なんかDK2だと古いSDKを入れなきゃ上手くいかないとかいう情報もあったけど，普通に公式のexeでやったらすんなりいきました。
最初から公式の方法でやればよかった。色々あった制約のせいでめんどくさがって公式以外の方法？でやっていたけど公式が一番です。
拙い文章ですが，これが誰かのお役に立てれば幸いでございます（笑）
テンプレートの部分特殊化を用いた際の落とし穴(msvc限定?)

# 要約
* 部分特殊化したテンプレートをネストした場合、msvcで完全型として展開されないケースがある
* 継承を使って回避することはできるが、気をつけよう

コンパイラの仕様のコーナーケースを突くような話になってきました。

# 事例
```cpp
template<typename F>
class Func;
template<typename TResult, typename ...TArgs>
class Func<TResult(TArgs...)> {};

template<typename T, size_t TAlign = alignof(Func<void(T)>)>
class FuncOwner {};

template<typename T>
class Hoge {
  FuncOwner<T> owner;
};
```
1. 部分特殊化を使った関数オブジェクトストレージを定義する([参考](https://qiita.com/rita0222/items/286bc7f6c98aa160b41b))
2. 任意の型を引数に取り、それを1.の型に対する引数の一部(返値でも引数でも可)で利用した上で、完全型でないと不可能な評価をデフォルト引数上で行う(alignofやsizeofなど)テンプレートクラスを定義する
3. 2.を利用するテンプレートクラスを定義する

これが、msvc(15.7.5)では `error C2027: 認識できない型 'Func<void(T)>' が使われています。` となります。
gcc(9.0.0)やclang(8.0.0)ではエラーにはなりませんでした。

# 解決策
部分特殊化を行った型を直接利用せず、継承を挟むことで回避できます。

```cpp
template<typename F>
class FuncImpl;
template<typename TResult, typename ...TArgs>
class FuncImpl<TResult(TArgs...)> {};

template<typename F>
class Func : public FuncImpl<F> {};
```

恐らくですが、部分特殊化のマッチングを解決するタイミングが、テンプレートパラメータのデフォルト引数上ではなく、親クラスの指定時にずれることで、問題が解消したものと思われます。

# 分析
テンプレートの展開は、具体的な型が与えられてから行うものだと思っていましたが、msvcは違うようです。
1. `FuncOwner`を利用する`Hoge`が定義された時点で、ある程度の展開を行おうとする
2. デフォルト引数に含まれる`Func<void(T)>`のTが与えられていないことで、定義済みの部分特殊化のマッチングから外れる
3. 宣言のみの`Func<F>`を利用しようとして、定義がないためにエラーになる
といった感じでしょうか。

実際に、`Hoge`の定義を削除して`FuncOwner`を直接具体的な型で利用するコードを記述した場合は、エラーになりません。
また、`FuncOwner`のアライメントの値をクラススコープ内の定数として定義した場合もエラーになりません。
前者はテンプレートのネストがトリガーになっていること、後者は型引数リスト部とクラススコープ内(そして恐らく親クラスの指定時も)で評価のタイミングが異なることを示唆していると考えられます。

# 考察
* 結局msvcが間違ってるんだろうか
* 型引数のデフォルト値で完全型を期待するのも良くない気はするが、型引数でサイズを指定するニーズは無くせない（と思う）
* とりあえず部分特殊化したら、継承で包んでおくのが無難？
Selectorの意外と知られてなさそうな事。

この記事ではSelectorについて意外と知られていないのでは？と思っている事を書きました。

<h2>一致するものが複数ある場合、その中で最前面にある画面要素に対して作用する。</h2>
Selectorは画面の中で一意になるところまで絞り込む必要はありません。ただ、同じSelectorの画面が複数表示されている場合、一番前面にあるSelectorの条件を満たす画面要素をSelectします。

<h2>アプリケーション横断的なSelectorを作る事ができる。</h2>
下記Selectorはタイトルに無題が含まれていればどのようなアプリケーションでもSelectします。
\<wnd omit:app='notepad.exe' cls='\*' title='\*無題\*' />
キーとなっているのは対象アプリに対してomitしている事です。「無題」というタイトルのExcelファイルやメモ帳どちらに対しても作用可能です。一つ前のトピックで話した通り、より前面にあるアプリケーションを指定します。

<h2>UiElement型から取得できる。</h2>
UiElement型はFind Activityなどを使うと取得できますが、こちらをSelectorに戻す事が可能です。方法としては取得したUiElement型のSelectorメソッドを使い、さらにToStringメソッドを使えば、Clickアクティビティで使えるSelector文字列が作られます。elementという変数の場合であれば、たとえば下記操作になります。
element.Selector.ToString

<h2>終わりに</h2>
画面要素取得はSelectorを使いFindアクティビティでUiElement型の変数を取得したあと、Find Childrenアクティビティで子要素を取得したり、Get Ancestorアクティビティで親要素を取得する事も可能です。Selector、及びUiElement型について詳しくなる事で、取りにくい画面要素を取得できるようになります。ぜひSelectorやUiElementで様々な事を試してみてください。
XamppでPythonを動かす方法

# XamppでPHPのようにPythonを動かしたい
手軽にWEBサーバーを動かすのに便利なXamppですが、PythonもぜひXamppで動かしたいと思ったのでその方法を記録に残しておきます。


# http.confを書き換える
まずXamppのパネルを開き、「Apache」モジュールの右側にあるConfigボタンを押します。
するとプルダウンメニューが開き、そのうち一番上に「Apache(http.conf)」というメニューがあるのでクリックしましょう。

http.confがメモ帳などで開かられたら、その一番下に以下の記述を付け足してください。

```apache
AddHandler cgi-script .py
ScriptInterpreterSource Registry-Strict
```

Apache側の記述は以上になります。


# Pythonスクリプト側の記述。



Pythonスクリプトの一例として以下のように書きます。
(今回はAnacondaをインストールしてる場合になります)

```python

#!C:\Users\username\Anaconda3\python.exe
# -*- coding: utf-8 -*-

print("Content-Type: text/html\n")
print("Hello World")

```

一行目のusernameはあなたのPCのユーザー名と入れ替えてください。

もしAnacondaがインストールされておらず、通常のPythonのみインストールされている場合は以下のように一行目だけ書き換えてください。

```python
#!C:\Program Files\Python36\python.exe
```

今回は以上になります。
2018年11月第3週　今週気になった記事まとめ

# 今週気になった記事まとめ
##■なにこの理想のボタン。エンジニアの聖地AWS Loft Tokyoに行ったら｢全自動幹事ボタン｣が作れた
https://www.gizmodo.jp/2018/11/amazon-aws-loft.html
サクッと言えるほどには楽ではないものの、タイトル通りの機能が結構シンプルに実現化することができている。
思ってるよりも各種サービスや各種APIで意外なことが実現できるようになっているらしい。

##■360度VRでまるでスクリーンに飛び込んだかのようにド派手アクションを楽しめる映画「THE LIMIT」が公開中
https://gigazine.net/news/20181121-robert-rodriguez-the-limit/
魅力的なコンテンツだとは思うのだけれど、今はなかなか身近に手ごろに楽しめる環境ないのがやはりネックか。
スマホでどこまで真価を感じることができるのか。。。

##■ビル・ゲイツが「シリコンバレーを理解したいのならドラマ『シリコンバレー』を見るべき」と熱く語る理由
https://gigazine.net/news/20181120-understand-silicon-valley/
シリコンバレーを理解したいのなら、とあるが、ITエンジニアがシリコンバレーを理解する必要はどれくらいあるのだろうか・・・？
結局のところ直接的な影響は無いはずで、間接的、それもかなり間を介したものくらいしかないと思うだけれど。
Makefileをタスクランナーとして使うときに .PHONY を自動生成する

タスクランナーとして Makefile を使うときに、ターゲットと同じファイルがあっても良いように `.PHONY` ターゲットを書きますよね？
でも面倒じゃないですか。というわけで思いつきました。`.PHONY` を自動生成すれば良いのです。

```Makefile
x:
	echo $@
y:
	touch $@
z:
	touch $@

NO_PHONY = /^(z):/
.PHONY: $(shell cat $(MAKEFILE_LIST) | awk -F':' '/^[a-z0-9_-]+:/ && !$(NO_PHONY) {print $$1}')
```

```console
% make x
echo x
x

% make y
touch y
% make y
touch y

% make z
touch z
% make z
make: 'z' は更新済みです.
```

`NO_PHONY` に正規表現を書いておけば、それらは `.PHONY` に含まれません。
複数のターゲットをまとめて書いてたり、変数にしてる場合には対応できてないですけど、タスクランナーとして使う場合あまりやらないのでそこはまぁ良いでしょう。必要なら `.PHONY` に並べてあげるだけです。

便利。
日本時間の歴史的な変遷

日本時間って言ったらUTC+09:00でしょと思ってる人へ

とんでもない間違いである。というのも、歴史的に、このような変遷を辿っているためである。

https://www.iana.org/time-zones

ここからData Only Distributionをダウンロードしてみよう。そしてJapanで探して行くと、こういう記述になる。

## まず夏時間に関するルール

- 1948・1950・1951年に関しては、5月第1土曜日24時から夏時間の適用を開始
- 1949年に関しては、4月第1土曜日24時から夏時間の適用を開始
- この4年間について、9月の第2土曜日25時(9日以降の日曜日の0時)で夏時間を終了

## 歴史的な標準時の変遷

- 1887年12月31日15時(UTC)=1888年1月1日0時(UTC+09:00)以降はUTC+09:00
- それより前はUTC+09:18:59(当時の東京天文台を基準にした？時刻。ただ、Google Mapsを調べると座標が合わない。Google Mapsの座標系では今その場所(東経139度44分40.90秒、北緯35度39分16.0秒)は[港区三田1-3-24](https://www.google.co.jp/maps/place/35%C2%B039'16.0%22N+139%C2%B044'40.9%22E/@35.6544444,139.7425057,17z/data=!3m1!4b1!4m5!3m4!1s0x0:0x0!8m2!3d35.6544444!4d139.7446944)だが、[Wikipediaの記述](https://ja.wikipedia.org/wiki/%E5%9B%BD%E7%AB%8B%E5%A4%A9%E6%96%87%E5%8F%B0)を信じるなら現在の港区麻布台にないとおかしい。と思っていろいろ調べたら、[座標系が変更になっていた](http://hiroba.jmc.or.jp/archives/53899532.html)ため、現在の座標系に直した座標を調べると[港区麻布台2-18-1](https://www.google.co.jp/maps/place/35%C2%B039'29.2%22N+139%C2%B044'28.9%22E/@35.6580992,139.7391688,17z/data=!3m1!4b1!4m5!3m4!1s0x0:0x0!8m2!3d35.6580992!4d139.7413575)付近になる模様)

というわけで、

- 1951年以前のデータを取り扱う時は、夏時間に留意する
- 1887年以前のデータを取り扱う時は、そもそもずれが整数時間じゃない

という点に気をつけたほうがよい。
pocketを複数のtagで検索する方法

# pocketを複数のtagで検索する方法

![Pocket_App_Logo.png](https://qiita-image-store.s3.amazonaws.com/0/102978/195eb33a-46c2-4b35-7ca0-bdacc49001af.png)



---

# 結論

有料会員限定

あとで読む系鉄板アプリの一つ [pocket](https://getpocket.com/) ですが、複数のタグを用いて絞り込み検索する方法が分かりづらかったりします

やり方は簡単です
***#をつけるだけ***です

これだけです
タグとタグの隙間は半角スペースで区切ります




実際に入れるとこんな感じ
↓↓↓
![pokecttags3.png](https://qiita-image-store.s3.amazonaws.com/0/102978/ecd3c6b1-a176-b9cc-46db-cec4c44ce111.png)






# なぜ必要なのか
pocketの検索窓に`「coffee tokyo」`もしくは`「#coffee #tokyo」`と入力した場合ではそれぞれ絞り込みの精度（仕組み）が異なるためです。前者は（良くも悪くも）タグ付けされていない情報まで出力されてしまいます。後者はタグ付けされた情報のみが抽出されます。

メニューのTagsなどからタグ検索は可能ですが、そこから複数のタグを一度に選択することはできません

pocketをタグで管理されている方はどの程度いらっしゃるのか分かりませんが、意外と便利ですよ（笑）

# tagで整理するメリット

1. 検索精度が高まる
2. スキマ時間など時間を掛けず整理できる
3. 内容を忘れた記事でもキーワードを覚えているだけで検索できる
4. 自分の読んだ記事、読もうと思った記事の中だけから検索できる
5. 後日タグをつけることは記事の内容を思い出すこと=復習になる

思い出すことの大切さはエビングハウスの忘却曲線でも説かれていますね（笑）
自分の話になってしまいますが、暇な時タグ付けすることでその記事に何が書いてあったのか思い出すことになり、結果復習することになり、頭の中にインデックスができます

（実際は忙しさにかまけて`これは！`といった記事にしかタグ付けできていませんが…）

ぜひ皆さんも一度タグで管理することをおすすめします




## ref

chromeの拡張機能はこちら
https://chrome.google.com/webstore/detail/save-to-pocket/niloccemoadcdkdjlinkgdfekeahmflj?hl=ja


[【Pocket活用法】お気に入り整理術！既読管理とタグと☆ - つぶ式](https://tbshiki.com/pocketuse/)

https://help.getpocket.com/article/1012-searching-for-tags-with-pocket-premium


tag
---
pocket
ポケット
あとで読む
リマインド
tag
タグ
複数
やり方
検索
方法
記事
管理
2つ以上
Microsoft 管理コンソール

Windows10 Pro x64 ja-JP 1809
%windir%\System32\

| ファイル名 |対象|
|:---------------------------|:-------|
|azman.msc|承認マネージャー|
certlm.msc|証明書 - ローカルコンピューター|
|certmgr.msc|証明書 - 現在のユーザー|
|comexp.msc|コンポーネントサービス|
|compmgmt.msc|コンピューターの管理|
|devmgmt.msc|デバイス マネージャー|
|DevModeRunAsUserConfig.msc|ユーザーの構成|
|diskmgmt.msc|ディスクの管理|
|eventvwr.msc|イベント ビューアー|
|fsmgmt.msc|共有フォルダー|
|gpedit.msc|ローカルグループ ポリシー エディタ|
|lusrmgr.msc|ローカル ユーザーとグループ(ローカル)|
|perfmon.msc|パフォーマンス モニター|
|printmanagement.msc|印刷の管理|
|rsop.msc|ポリシーの結果セット|
|secpol.msc|ローカル セキュリティポリシー|
|services.msc|サービス|
|taskschd.msc|タスク スケジューラ|
|tpm.msc|コンピューターのトラステッドプラットフォーム モジュール(TPM)の管理(ローカルコンピューター)|
|virtmgmt.msc|Hyper-V マネージャー|
|WF.msc|セキュリティが強化された Windows Defender ファイアウォール|
|WmiMgmt.msc|コンソール ルート\WMI コントロール(ローカル)|
Virtualboxのゲスト(Kali Linux)でguest addition CD imageを実行できない問題

# 発生した問題
guest additions CD imageを実行しようとすると
`Oops! There was a problem running this software. Unable to locate program`
上記のエラーメッセージが表示され、実行できない。

## 原因
どうやらKali Linuxの初期状態では、マウントされたファイルシステムのバイナリを実行できないようになっている。

## 解決策
`/etc/fstab`を編集する。

```bash
初期状態
/dev/sr0    /media/cdrom0    udf,iso9660    user,noauto         0    0

変更後
/dev/sr0    /media/cdrom0    udf,iso9660    user,noauto,exec         0    0
```
この変更を行った後、再起動する。
再起動後、guest additions CD imageを実行できるようになっている。

### 参考にしたサイト
* [StackExchange - Guest additions 'unable to locate program' Kali Linux 2.0]
(https://unix.stackexchange.com/questions/239973/guest-additions-unable-to-locate-program-kali-linux-2-0)
kerasとMatplotlibを使ってデータセットCIFAR-10の画像を表示させて遊んでみた

## Matplotlibとは？
グラフが描画できるライブラリ
機械学習のデータの可視化などに利用される

## CIFAR-10とは？
32×32サイズの画像6万枚が10種類のラベルとセットで含まれている
画像とラベルの種類はairplane,automobile,bird,cat,deer,dog,frog,horse,ship,truckの10種類


## 実際にmatplotlibで表示させて遊んでみる

###1.データをインポート


kerasを使ってCIFAR-10の画像をインポートします
(※kerasはインストール済みの状態とします)

~~~Python
from keras.datasets import cifar10
(x_train,y_train),(x_test,y_test) = cifar10.load_data()
~~~

機械学習での学習用とテスト用のデータなので(x_train,y_train),(x_test,y_test)となっています(※詳しい話は割愛)

###2. Matplotlibをインポート

~~~Python
from matplotlib import pyplot as plt
~~~

###3. CIFAAR-10の画像データを表示させる

　例：1枚目の画像を表示させる場合

~~~Python
plt.imshow(x_train[0])
plt.show()
~~~

### JupyterNotebookで手順1から試していくと

1枚目の画像
![スクリーンショット 2018-11-23 1.08.10.png](https://qiita-image-store.s3.amazonaws.com/0/317125/feb47dbc-d04e-4b68-f557-3bed03c1ad8b.png)
かえる(frog)・・・？



4枚目
![スクリーンショット 2018-11-23 1.09.56.png](https://qiita-image-store.s3.amazonaws.com/0/317125/1ba2de40-80e0-b63b-411e-7668a1c7e8c7.png)
これは鹿(deer)っぽい



40枚目
![スクリーンショット 2018-11-23 1.12.29.png](https://qiita-image-store.s3.amazonaws.com/0/317125/7abdfe67-d1e8-5302-4b87-d910928dd20a.png)

ん〜ー。




(※正解のラベルはy_trainに付いてます)
自作シェルスクリプトにヘルプやらバージョンメッセージを実装？する面白い方法があった

# はじめに

これは環境変数などをexportするようなスクリプトを書く場合の方法です　

# 本題

とあるアプリのシェルスクリプトに個人的に面白いと感じたヘルプやバージョンのメッセージを実装している例があったので，紹介する．（ここに著作権は無いはず．．．）

その書き方の特徴はメッセージの内容をコメントアウトした状態で利用している点である．

```shell:script.sh
export FILENAME=$(basename $0)
## file    : ${FILENAME}
## version : 3.14
#% help info brbrbrbr
case $1 in
  v) # version
    sed -n 's/^##//p' $0 | envsubst | less
esac
```
```shell:実行結果
$ ./script.sh -v
file    : script.sh
version : 3.14
```

"-v"のオプションをつけたときは，"##"とコメントアウトしている部分が表示される．
そして， FILENAME という環境変数が展開されて出力される．

これの面白い点は

* コメントアウトされているものを出力で利用している点
* "envsubst"によって，コメントアウト内の環境変数が展開されて出力する点

この他にもヘルプなどでは別のコメントアウト方法（"#%" etc）をすれば，
多種多様なオプションの出力に対応できる．

# 最後に

普通にスクリプト内のただの変数をsedで表示できる方法がないかなぁ

# 追記

```
sed -n 's/^##//p' $0 
より
awk -F' ' '/^##/{print $2}' $0 
の方が理解しやすいか?
```
長澤さんの「Kotlin Contracts」を読んだまとめ

この記事を書くきっかけは、長澤さんがKotlin1.3の新機能「Contracts」について発表していた資料が素晴らしかったので、復習も兼ねてアウトプットしようと思ったためです。

# 長澤さんの資料
Kotlin Contracts #m3kt - Speaker Deck
https://speakerdeck.com/ntaro/kotlin-contracts-number-m3kt

# Contractsについて

## 1.3前はnullチェックしてもスマートキャストできない

```kotlin
  val name: String? = ""
  if (!name.isNullOrBlank()) { //stdlibの関数
      println("Hello, ${name.capitalize()}") // <= エラー
  }
```

エラーメッセージ

```
Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?
```
「nullableなので `?.` または `!!.` じゃないとダメだぞ」

これは自分のプロジェクトでも書いてて遭遇した。
null&空白チェックしてるのになぁ

1.3より前の場合、こうしなきゃいけなかった

```kotlin
  val name: String? = ""
  if (name != null && name.isNotBlank()) { // <= 1.3前
      println("Hello, ${name.capitalize()}")
  }
```
## 1.3からはスマートキャストが効く

```kotlin
  val name: String? = ""
  if (!name.isNullOrBlank()) {
      println("Hello, ${name.capitalize()}") // <= エラーにならない！
  }
```

## Contracts（契約）とは
**事後条件**

- 関数を呼び出したあとの状況を関数が保証する

### ソースで見てみる
`isNullOrBrank()` の中を覗いてみる

```kotlin
public inline fun CharSequence?.isNullOrBlank(): Boolean {
    contract { // <= 注目ここから
        returns(false) implies (this@isNullOrBlank != null)
    } // <= ここまで
//falseが返されるとき、この文字列はNotNullであることを意味する、という契約
    return this == null || this.isBlank()
}
```

## 自作関数に契約

自作してみる

```kotlin
@ExperimentalContracts
fun Any?.isNotNull(): Boolean {
    contract { // <= 契約
        returns(true) implies (this@isNotNull != null)
    }
    // trueが返されるとき、thisはNotNullである契約
    return this != null
}
```

作ると分かるが、 `@ExperimentalContracts` が必要とIDEに怒られる

## 契約対応している標準関数

kotlin.testも含む

- assertTrue
- check
- require
- assetFalse
- assertNOtNull
- checkNotNull
- requireNotNull

# val変数が絶対初期化されるのにコンパイルエラーになる（Kotlin 1.3前）

```kotlin
val x: Int
run {
    x = 12345 // <= ラムダのなかで初期化してるのにコンパイルエラー
}
println(x)
```

Kotlin 1.3ではContractsによりこれが解決された

runの中を覗いてみる

```kotlin
public inline fun <T, R> T.run(block: T.() -> R): R {
    contract { // <= 契約を発見
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
// blockが「ちょうど一度だけ」呼び出される
    }
    return block()
}
```

## InvocationKindの種類

- AT_MOST_ONCE //関数のパラメータは一度呼び出されるか、まったく呼び出されません。
- AT_LEAST_ONCE //関数のパラメータが1回以上呼び出されます。
- EXACTLY_ONCE //関数パラメータは、1回だけ呼び出されます。
- UNKNOWN //関数のパラメータが呼び出されますが、呼び出すことができる回数は不明です。

## 契約対応している標準関数

- EXACTLY_ONCE
  - run
  - with
  - apply
  - also
  - let
  - takeIf
  - takeUnless
- UNKNOWN

# 契約DSLまとめ
- contract: 関数の先頭におく必要がある
- returns(): 関数の実行が成功したら
- returns(Any?): 引数の値 true|false|null を返したら
- returnNotNull(): NotNullを返したら
- callsInPlace:　引数の関数が呼ばれる回数を保証

# まとめ
- スマートキャストや変数初期化において、面倒なことがKotlin 1.3で解消された
- 契約DSLで契約を表明することでコンパイラに意味が伝わる
デプロイした時にでたエラー

#はじめに
Herokuにデプロイした時にでた二つのエラーとそれに対する解決方法を紹介

##一つめのエラー
まあまあ苦戦したやつ
<img width="1440" alt="スクリーンショット 2018-11-22 23.35.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/281214/289c3ef5-1f77-b50e-14df-85cce242c103.png">

###原因
いろいろそれっぽいことやったが、全然解決できず、結局ググったら、なんかrubyのバージョンとdeviseのバージョンが原因みたい

###解決方法
その時Rubyを2.5.0とdeviseを3.4.1を使ってて、deviseを4.0.0にしたら解決できました。
後々調べたら、やっぱり他の方も同じエラーが出ているみたいで、僕が経験した組み合わせ以外にも、Ruby 2.5.0,devise 4.3.0の組み合わせも同じエラーが出るみたいです。

##二つめのエラー
エラー画面ではないですが、ローカルでエラーログが出なかったので一応これを貼り付けときます。
<img width="539" alt="68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3234303238302f35653335396634372d313538632d666162362d626334392d6538643739666562646130622e706e67.png" src="https://qiita-image-store.s3.amazonaws.com/0/281214/9d5f3627-dd17-5d8d-ec7e-0b4c29be18d0.png">

###原因
開発中のアプリをデプロイする時はデータベースを更新しないといけなかったみたいで、それをしてなかったのが原因

###解決方法
データベースをマイグレーションする

```
$ heroku run rails db:migrate
```
このコマンドひとつで解決しました。

##参考サイト
[Syntax error on Ruby 2.5.0](https://github.com/plataformatec/devise/issues/4736)
[作業中のブランチをHerokuにデプロイする
](https://qiita.com/Chinats/items/c00df6e3ca81184606fe)
rails consoleでmigrationをする

新しくmodelを作って色々やりたいときに、
rails g model hogeをして
rails db:migrateをして
rails cでデータ操作をして
rails d model hogeするのが
面倒だな...と思ったので、migrationもrails consoleに任せられないかどうかを試してみました。

####事前準備

普通にrails consoleに入ってmodelとmigration classを作成します。

```
$ rails c --sandbox
```
```ruby
class Person < ApplicationRecord; end

class CreatePeople < ActiveRecord::Migration[6.0]
  def change
    create_table :people do |t|
      t.string :name
      t.integer :age

      t.timestamps
    end
  end
end
```

####migration
```ruby
ActiveRecord::Migration.run(CreatePeople)
-- create_table(:people)
   (19.0ms)  SELECT sqlite_version(*)
   (1.0ms)  CREATE TABLE "people" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar, "age" integer, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL)
   -> 0.0226s
=> [CreatePeople]
```

####rollback
```ruby
ActiveRecord::Migration.revert(CreatePeople)
-- drop_table(:people)
   (0.5ms)  DROP TABLE "people"
   -> 0.0012s
=> nil
```


勿論、データ操作も可能です。

```ruby
Person.create!(name: "John", age: 25)
   (0.2ms)  SAVEPOINT active_record_1
  Person Create (0.3ms)  INSERT INTO "people" ("name", "age", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["name", "John"], ["age", 25], ["created_at", "2018-11-22 14:38:36.161985"], ["updated_at", "2018-11-22 14:38:36.161985"]]
   (0.1ms)  RELEASE SAVEPOINT active_record_1
=> #<Person id: 1, name: "John", age: 25, created_at: "2018-11-22 14:38:36", updated_at: "2018-11-22 14:38:36">
Person.first
  Person Load (0.4ms)  SELECT  "people".* FROM "people" ORDER BY "people"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<Person id: 1, name: "John", age: 25, created_at: "2018-11-22 14:38:36", updated_at: "2018-11-22 14:38:36">
```
・ActiveRecord::Migration.run
・ActiveRecord::Migration.revert
共に、可変長引数のメソッドのため、複数classの指定が可能です。
https://api.rubyonrails.org/classes/ActiveRecord/Migration.html


####もっと楽をしたい人の為に...
上記メソッドを呼ばずとも、migrationは可能です。

```ruby
class Person < ApplicationRecord; end

class CreatePeople < ActiveRecord::Migration[6.0]
  create_table :people do |t|
    t.string :name
    t.integer :name

    t.timestamps
  end
end
-- create_table(:people)
   (1.5ms)  SELECT sqlite_version(*)
   (10.4ms)  CREATE TABLE "people" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" integer, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL)
   -> 0.0197s
=> []

```
【Python基礎】set型（セット型）の使い方

##1. セット型(set)とは
- セットはPythonで扱える集合を表すデータ型である。
- リスト等と同様に複数の要素をもつことが可能。
- 集合なので、リストとは異なり要素は順番がない。
- 重複した要素は取り除かれる。



##2. "あいうえお"を例に見てみる
```python
words = "あいうえお"
#文字数を見る
print("文字の数は"+ str(len(words))+"だよ")
#文字の種類を洗い出す
print("文字の種類は"+ str(set(words))+"だよ")
#文字の種類の数を数える
print("文字の種類の数は"+ str(len(set(words)))+"だよ")
```
>文字の数は5だよ
文字の種類は{'え', 'う', 'お', 'あ', 'い'}だよ
文字の種類の数は5だよ

```python
words = "あいうえお"
#文字数を見る
print("文字の数は"+ str(len(words))+"だよ")
#文字の種類を洗い出す
print("文字の種類は"+ str(set(words))+"だよ")
#文字の種類の数を数える
print("文字の種類の数は"+ str(len(set(words)))+"だよ")
```




##3. "ぼぼぼーぼぼーぼぼ"を例に見てみる
```python
words = "ぼぼぼーぼぼーぼぼ"
#文字数を見る
print("文字の数は"+ str(len(words))+"だよ")
#文字の種類を洗い出す
print("文字の種類は"+ str(set(words))+"だよ")
#文字の種類の数を数える
print("文字の種類の数は"+ str(len(set(words)))+"だよ")
```
>文字の数は9だよ
文字の種類は{'ー', 'ぼ'}だよ
文字の種類の数は2だよ

<img src="https://3.bp.blogspot.com/-DjgwmUHkSkE/VOsJ7ZyWvnI/AAAAAAAArvQ/rI6_l0igQJQ/s400/hair_afro.png" width=30%>

## おまけ　改行を含めた文章（今回は"すもももももももものうち"）を例に見てみる
```python
#改行を含めたテキストを代入するために"を3つずつでくくる
words = """すももも
ももも
もものうち"""
#文字数を見る
print("文字の数は"+ str(len(words))+"だよ")
#文字の種類を洗い出す
print("文字の種類は"+ str(set(words))+"だよ")
#文字の種類の数を数える
print("文字の種類の数は"+ str(len(set(words)))+"だよ")
```
>文字の数は14だよ
文字の種類は{'う', 'ち', 'の', 'す', 'も', '\n'}だよ
文字の種類の数は6だよ

改行も一文字としてカウントされましたね！

<img src="https://1.bp.blogspot.com/-6HT7iIJ1Xs8/VGX8hLBmrOI/AAAAAAAApIA/W_dTS-CzgNA/s400/fruit_momo.png" width=30%>
Rails & docker-compose のマイクロサービスで開発する時に環境変数の設定はどうしてるんだろう

CIを回すためのRSpecやRuboCop環境を整えていく中で、つい昨日まで開発環境が「不便だなぁ」と感じていたこと、皆さんはどのように解決しているのか気になったので投稿してみました。

## 今携わっているプロジェクトの開発環境

* Ruby 2.5.3
* Rails 5.2.1
* docker-compose version 1.23.1
* docker-compose.yml version '2'
* 20個近くの独立したDockerコンテナ
    * Railsが動いていたり
    * lambdaのモックがあったり
    * S3のモックがあったり

## 不便だなぁと感じていたところ

* RSpecやRuboCopを回すためにDockerコンテナに `docker exec -it hoge-container bash` で入り、`bundle exec guard --force-polling` で監視しながら結果を逐次確認する作業が必要になる
* Railsの起動には色々な環境変数の設定が必要で、環境変数はdocker-compose.ymlに一元管理されている
    * 自分のマシンは MacBook なのでterminal-notifierを使ってRSpecやRuboCopの結果を見たいが、ローカル環境でguardを立ち上げるために、毎回Dockerコンテナ毎の環境変数を設定しなくてはならない
    * Dockerコンテナでguardを立ち上げたり回したりすると重い & 遅い。Dockerコンテナ上だとterminal-notifierが使えない
* RSpecやRuboCop用のguardコンテナを別途立ち上げるのも検討したが、
    * terminal-notifierが使えない
    * コンテナが増えることでマシンの負荷が増える
    * guardのREPL？が使えない
    * ログがdocker-compose logs に紛れる

など、自分の知識が足りないだけでもっといい方法があるような気がしますが、
昨日までこのようなモヤモヤを持ちながらひたすらに開発を進めていました。

## (自分の中では)解決策

自分と自分以外の人が開発しやすく、環境を共有しやすい方法が無いか昨日の夜から真剣に一晩悩んで、今朝試してみたところうまくいきそうだったので一気に環境を作り、夜になった今ではかなり快適になったので、ここにその解決法を残しておきます。
あくまで自分の印象として快適になった、というだけでまだ自分以外に共有されていないので、周りの反応は来週以降にならないとわかりません。

### docker-compose.yml を読み込んで Rails 内で環境変数を設定する gem を作った

[docker_compose_yaml_loader](https://rubygems.org/gems/docker_compose_yaml_loader) です。
プロジェクトの開発環境ではエラーや不具合がないレベルでしか作られていないので、もしかするとうまく処理できないことがあるかもしれませんが、今のところ問題なく動いています。

### 使い方

Gemfile

```Gemfile
group :development, :test do
  gem 'docker_compose_yaml_loader'
end
```

config/test.rb

```config/test.rb
DockerComposeYamlLoader::Environments.setup(Rails.root.join('./docker-compose.yml'), key: 'webapp') do |env|
  env.set('DATABASE_HOST', '127.0.0.1') # docker-compose.ymlのままだと動かない設定は、上書きできる
  env.set('DATABASE_PORT', '13306')
end
```

これだけの設定で、docker-compose.ymlの設定を流用でき、重複定義にならず定義場所が散らばらないようにできました


## 上記の解決方法がベストなのかどうか、今でも自信がありません。
皆さんの開発環境ではどのような設定やツールでストレスの少ない開発環境を実現しているのか、コメントしていただけるととても嬉しいです。


乱筆・乱文なのは重々承知の上で、記事を投稿してしまうことを何卒お許しください。
ドットインストールにおけるローカル開発環境構築【Mac編】

##ローカル環境開発とは
WEBアプリケーションなどを作成した際に、それをオンラインで公開するためには「サーバー」という環境を用いて、PCで作成したアプリケーションの中身とインターネットを接続する必要があります。
このサーバーですが、基本的には運営会社にお金を払って貸してもらう形になります。
しかし開発中などは余計なお金がかかってしまうため、このローカル開発環境といった自前のサーバーを用意してテストなどを行います。

##準備するもの
- Mac OSがインストールされているパソコン
- Internet環境
- ターミナル
- Google Chrome
- Virtual Box
- Vagrant
- Cyberduck


##手順（準備編）
1. まずMac OSがインストールされているパソコンを用意し、インターネットが接続できる環境を用意します。
2. Google ChromeなどのブラウザからVirtual Boxの[ダウンロードページ](https://www.virtualbox.org/wiki/Downloads)を開きMac用のファイルをダウンロードします。
3. 手順に従ってVirtual Boxのファイルを開きインストールします。
4. 次にVagrantの[ダウンロード](https://www.vagrantup.com/downloads.html)を行います。
5. Vagrantの操作はターミナルを用いて行います。
6. ドットインストールではターミナルの細かい設定を行なっています。必要な方はターミナルの環境設定から背景や文字フォントなどの変更を行なってください。

ここまでが終われば環境構築の準備は終了です。
次は実際に必要な仮想マシンを立ち上げる作業へ移ります。

##手順（実装編）
1. ```cd```のコマンドを入力しホームディレクトリに戻ります。
2. 今回のドットインストールで行う作業用に```mkdir MyVagrant```というコマンドでMy Vagrantというフォルダを作成します。
3. 次に```cd MyVagrant```で移動し、```mkdir MyCentOS```というフォルダを作成します。
4. ```cd MyCentOS```で移動し、```vagrant init bento/centos-6.8```というコマンドで仮想マシン設定用のVagrantfileを作ります。
5. 作成したVagrantfileを編集するため、 ```sed -i '' -e 's/# config.vm.network "private_network", ip: "192.168.33.10"/config.vm.network "private_network", ip: "192.168.33.10"/' Vagrantfile```というコマンドを実行します。
6.　```vagrant up```で仮想マシンを起動し、```vagrant status```で環境を確認します。このとき「default running」という表記が出ればマシンが無事動いていることがわかります。

ここで仮想マシンの実装が完了しました。
次は仮想マシンの設定と、実際に使っていく手順です。

##手順（設定と実行）
1. ```vagrant ssh```でサーバーにログインできます。$の前が「vagrant@localhost」となっていればOKです。
2. 次にシステムを最新にアップデートするための```sudo yum -y update```というコマンドを入力します。
3. スクリプトを入手するため、```sudo yum -y install git```というコマンドを実行します。
4. ```git clone https://github.com/dotinstallres/centos6.git```というコマンドで、gitを使ってアプリケーションの設定用スクリプトをダウンロードします。
5. centos6というフォルダが作成されているため、```cd centos6```で移動します。
6. ```./run.sh```でダウンロードしたスクリプトを実行し、```exec $SHELL -l```でそれらの設定を反映させます。
7. 最後にCyberduckという仮想マシン上のファイルを転送できるツールを[ダウンロード](https://cyberduck.io/download/)し、環境設定からお好みの設定をすれば環境構築の作業は終了となります。
Haskell Hello,Worldへの道

#インストール
Stackをインストールした。
最初はHaskell Platformをインストールしようと考えてました。
しかし、オールインワンは簡単で良さげだけど、ググってると後々めんどくさくなりそうな気がしたので、野生の勘でStackにしました。
いくつかのサイトでbrewをオススメみたいなこと書いてあったけどbrewが何者かも知らないので

curl -sSL https://get.haskellstack.org | sh

とターミナルに入力してインストール

export PATH=~/.local/bin:$PATH

とパスを通して
これで始められると思って

ghci

としたら

-bash: ghci: command not found

とか出たので、じゃあ

stack ghci

こんな感じかなっと入力
また長めの待ち時間が今。

#なんかエラー出てるよ
次の日の朝
ターミナルを見ると

ghc-8.4.4:    9.81 MiB / 220.05 MiB (  4.46%) downloaded...

なんかインストールが止まってる
ここはしれっと「ctrl＋c」

ちなみに環境は
開封したばかりのMac mini
dellの108キーボード

再度

stack ghci

今度はコマンドラインのXcodeインストールしてくれってお願いされたのでXcodeまるっとインストール

これまた長い待ち時間
洗濯とコーヒーと皿洗い...

Xcodeのダウンロード・インストールが終わったので
軽くXcodeを開いて
今度は、ターミナルを見ると
なんかエラーがでてる・・

Configuring GHC ...                                                          
Received ExitFailure 77 when running
Raw command: /Users/mf/.stack/programs/x86_64-osx/ghc-8.4.4.temp/ghc-8.4.4/configure --prefix=/Users/mf/.stack/programs/x86_64-osx/ghc-8.4.4/
Run from: /Users/mf/.stack/programs/x86_64-osx/ghc-8.4.4.temp/ghc-8.4.4/

調べてみてもよくわからないので
再々度

stack ghci

なんかいい感じ！

Prelude>

テンションが上がる

#Hello,World!
「すごいHaskellたのしく学ぼう！」を片手に

Prelude> Hello,World!

「すごいHaskellたのしく学ぼう！」は一先ず無視

<interactive>:1:6: error: parse error on input ‘,’

ぬぬぬ、じゃあこんな感じで

Prelude> "Hello,World!"
"Hello,World!"

よっしゃ！
初めてのVagrantを用いた仮想環境構築方法

#1.そもそも仮想化とは？仮想環境とは？
　　___仮想化（Virtualization）とは、物理的な環境に捉われることなく、ハードウェアに含まれるCPUや
　　メモリなどのリソースを論理的に分割・統合する技術___のことをいいます。
　　___仮想マシン（Virtual Machine、VM）___は、その仮想化の技術を用いてPCを動作させることをいいます。
　　ざっくり言うと、目の前の___1つ___しかないサーバを___複数___のサーバがあるように分割し動作させることをいいます。
　　この時点で、___「かなり便利そう！」___や___「早く使いたい！」___という気持ちになりますよね！（僕はなりました^^笑）
　　具体的には、目の前のMac上でWindowsやLinuxを動作させることができます
　　用語として、この場合Macが___「ホストOS」___といい、WindowsやLinuxを___「ゲストOS」___といいます。

#2.仮想マシンのメリット・デメリットは？
　　簡単に仮想マシンを導入することによるメリット・デメリットを列挙します。

　___☆メリット☆___
　　1.サーバの台数を減らしコスト削減
　　2.管理の手間が減らせる
　　3.すぐにサーバを用意できてしまう
　　4.複数のOSが使える
　　　　　　　　　　　　　　　　　　etc

　___★デメリット★___
　　1.小規模環境ではコストが割高になる
　　2.仮想環境を管理するための知識と技術が必要になる
　　3.物理ハードウェアに障害での影響範囲が大きくなる可能性がある
　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　etc

#3.Vagrantとは？
　　___Vagrant___とは、仮想環境を作成するにあたって、とても便利なソフトウェアです。
　　設定や仮想マシン(VM)の作成方法などを手助けしてくれます。
　　Vagrantを使えば、簡単な数行のコマンドで仮想環境を構築することができます。
　　しかし、Vagrant自体には仮想化に関する機能は搭載されていないので、
　　別途仮想化ソフト(___VirtualBox___、VMware、EC2など)が必要になります。
![vagrantup-card-320x160.png](https://qiita-image-store.s3.amazonaws.com/0/314881/5d50ce15-9ab7-9682-5e42-e04e7dcd19db.png) <img src="https://qiita-image-store.s3.amazonaws.com/0/314881/ab0d7349-2866-4e80-0aa4-77c78151f37b.jpeg" width=20%>

#4.Vagrant、VirtualBoxのインストール
　●___Vagrantのインストール___
　　[Vagrant](https://www.vagrantup.com) ←こちらから
　　※最新バージョン　Vagrant 2.2.1(2018.11.22 現在) ※以下バージョン確認

```php:Vagrantのバージョン確認
$ vagrant -v # -v は --versionと同義
Vagrant 2.2.1 

#インストールしているVagrantが最新版かどうかの確認方法
$ vagrant version
Installed Version: 2.2.1
Latest Version: 2.2.1
```
　●___VirtualBoxのインストール___
　　[VirtualBox](https://www.virtualbox.org) ←こちらから
　　※最新バージョン VirtualBox 5.2.22(2018.11.22 現在)

#5.Vagrant Boxのダウンロード
　___Vagrant Box___とは、仮想マシンのテンプレート（雛形）となるファイルです。
　手動で1からOSをインストールするのは大変です。
　が！しかし！例えばCentOSのBoxでCentOSの環境を構築することができます。
　早速ですが、以下のコマンドでVagrant Boxを追加します。

```php:boxの追加
$ vagrant box add box名 boxのURL
```

　●___Vagrant Boxのダウンロード___
　　[Box](https://app.vagrantup.com/boxes/search) ←BoxのURLはこちらから

　例えば、___CentOS 6.4___というBoxを追加する場合

```php:CentOSのboxを追加
$ vagrant box add CentOS 6.4 http://developer.nrel.gov/downloads/vagrant-boxes/CentOS-6.4-x86_64-v20131103.box
```

　　ダウンロードが完了したら、一覧を確認してみましょう。

```php:boxの一覧確認
$ vagrant box list
bento/centos-6.8 (virtualbox, 2.3.4)
centos/7         (virtualbox, 1809.01)
centos64         (virtualbox, 0)
```

#6.仮想マシン操作の前準備

　　仮想マシンを作るフォルダの作成をする。

```php:仮想マシン操作の前準備
$ cd              # ホームディレクトリに移動
$ mkdir MyVagrant # MyVagrantフォルダの作成（※今後はこのフォルダで仮想マシンを作っていく）
$ cd MyVagrant    # 先ほど作成したMyVagrantフォルダに移動
$ mkdir MyCentOS  # MyCentOSフォルダを作成（仮想マシンを作るフォルダの作成　※フォルダ名は任意）
$ cd MyCentOS     # MyCentOSフォルダに移動
```

　　続いて、Vagrantの___初期化___をし、___Vagrantfile___を作成する。（___※最初だけ！___）

```php:vagrantの初期化＆Vagrantfileの作成
$ vagrant init box名
```

#7.Vagrantの実行　仮想マシンの起動

　　vagrantの実行＝仮想マシンの___起動___となります。

```php:vagrantの実行　仮想マシンの起動
$ vagrant up
```

　　次に仮想マシンに___sshログイン___します。

```php:仮想マシンにsshログイン
$ vagrant ssh
```

　　これでログインまでいけました。

---
　___補足___
　　仮想マシンから___ログアウト___する。

```php:仮想マシンからログアウト
$ exit
```

　　仮想マシンを___シャットダウン___する。

```php:仮想マシンのシャットアウト
$ vagrant halt
```
sortコマンドチートシート

# 区切り文字としてタブ文字を指定する

[sortコマンドやcolumnコマンドで区切り文字にタブ文字を指定する](https://qiita.com/miminashi/items/a0d22ada995b8bbdff16) にまとめた


# セマンティックバージョニング的な命名規則でソートする

例えばこんな感じで、ドット区切りの整数がそれぞれ独立してインクリメントされる命名規則のファイル（本のセクションや[セマンティックバージョニング](https://semver.org/lang/ja/)など）があったとすると、

```shell-session
$ ls -1
1.3
5.6
6.10
6.3
```

以下のように、`-t`オプションで`.`を区切り文字として指定して、`-k`オプションを複数個使うと、各フィールドごとに整数としてソートしてくれます。

```shell-session
$ ls -1 | sort -t '.' -k 1,1n -k 2n
1.3
5.6
6.3
6.10
```

最後のフィールドに対応する`-k`オプション以外は`-k 1,1n`のようにフィールドの開始と終了を指定してあげるのがポイントのようで、ここを`-k 1n`としてしまうとうまくソートできませんでした。


参考: https://abicky.net/2011/07/24/174632/
プロジェクト作成後にstyleをlessやscssに変更する方法[Angular]

私はいつもいつもng newしてからあっlessにし忘れた…！！となり、そこから検索するはめになります。最近ng newの時にきいてくれるようになったと耳にしたのですがまたやってしまいました。大体ng newと同時にするやつばかりで地味に探すのに時間がかかったりするので自分用にまとめておきます。

これだ！！
```ng config schematics.@schematics/angular:component.styleext scss```
前まではSetでしたが6以降configに変更されたそうですね。
既存のcssは自分でscssに変更してあげる必要があります。

念の為、newするときに指定する方法も書いておきます。
```ng new my-sassy-app --style=scss```
【ググってもカス】contactform7の送信完了（サンクス）画面を無理やり作った

## そう、私はカスなのだ
こんばんは。カスです。
contactform7って知ってますか？
私はWordPressなら大体このフォームプラグインを使うんですが、如何せんthanksページがないんですよ。
そこで、今回初めてググってググってやってみようと思ったんだけど・・・・・私はググってもカスだったため、ネット上の情報では実装できませんでした。

とはいえ、一概に私がカスってわけでもなさそうで、結構ちゃんと調べると同じような現象の人も結構いた。

そんなカスな私および、普段はめちゃめちゃできるけどここで詰まった！っていう人でも実装できるとっても簡単な（完全なる力技）thanksページ導線を作ったので、もしもう作る気失せて寝ようとしてるそこのエンジニアさんがいるならば、野暮ったさは目をつぶって使ってみてください。

### 実装方法
1.thanksページを固定ページで作成
2.contactform7の送信完了文言をweitに変更
3.以下ソースコードをコンタクトフォームが入っているところにガツンと入れる

```javascript
<script>
      send = document.getElementsByClassName('wpcf7-mail-sent-ok')[0];
      if(send.innerHTML == 'wait') {
        location.href = 'http://localhost:8000/thanks/';
      }
</script>
```

ほら、簡単やろ？w
仕組みは簡単で、送信完了時にcontactform7が吐き出す完了文言をjsで見て飛ばすっていうなんとも原始的な方法を取ってみました。
一周回ってシンプルじゃない？（思考停止
もうね、私にはこれしか考えつかなかったのです。

てかそろそろcontactform7完了ページ作ってwwwwww
特定の文字列を全て置換する[Javascript]

"apple,banana,orange" のような文字列を "apple banana orange" に置き換えたいとします。
（カンマを半角スペースに）
PHPですと以下のように、

```php:php
<?php
$str = "apple,banana,orange";
str_replace(',', ' ', $str);
```
と、str_replace() を呼ぶことで全て置換することができます。
[PHP:str_replace](http://php.net/manual/ja/function.str-replace.php)

しかし同様のノリでjavasciptで書くと...

```javascript:javascript
const str = "apple,banana,orange";
const replaced = str.replace(',', ' ')
console.log(replaced) // apple banana,orange
```
と、マッチした先頭のものしか置換されません。

# 正規表現
String.prototype.replace()で全置換をする場合、正規表現を使います。

```javascript:javascript
const str = "apple,banana,orange";
const replaced = str.replace(/,/g, ' ')
console.log(replaced) // apple banana orange
```
上記のように第一引数に正規表現リテラル（もしくはRegExpオブジェクト）を渡します。
またgフラグをつけることで、全てのマッチを探すことができます。
[String.prototype.replace()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/replace)
[RegExp](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/RegExp)

# split + join を組み合わせる
```javascript:javascript
let str = "apple,banana,orange"
str = str.split(',') // ["apple", "banana", "orange"]
str.join(' ') // "apple banana orange"
```
String.prototype.split() は、引数に渡された文字で文字列を分割して、配列形式にして返します。
そして Array.prototype.join()は、引数に渡された文字で配列の要素を連結して、文字列にします。
[String.prototype.split()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/split)
[Array.prototype.join()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/join)
[初心者]サーバサイドの役割で疑問に思ったことを調べてみた

新人エンジニアが自分なりに調べたことをまとめるログとして残しました。

# 疑問に思ってたこと

## HTTPでリクエストを送ったあとに何がどう動いているの？
- 下に記載している「ネットワークはなぜつながるのか 第2版」が非常に勉強になった。（OSを出て、LANに行ったくらいから飽きて読んでない）
    - [ネットワークはなぜつながるのか 第2版](http://amzn.asia/d/eZndBQx)

## Apache, nginxとかってなんで必要なの？
- HTTPリクエストを処理するため。
- APサーバと分けてセキュアにするため
- プロキシサーバとして使うため（これは知らん。後で調べる。）
- その他諸々

## APサーバソフトはWEBサーバの機能も兼ねるって聞いたんだけど？
- まだ正確に把握できてはないが、簡単なのはWEBサーバだけでいいかも。
- しっかりと作ったり運用を考えるのであればWEBサーバもしっかり導入するべき。
    - [Apache HTTP ServerとApache Tomcatの連携する意味](https://fa11enprince.hatenablog.com/entry/2015/01/19/233740)
    - [Why should I integrate Apache with Tomcat? (or not)](https://wiki.apache.org/tomcat/FAQ/Connectors#Q3)

## 前Railsでアプリ作ったとき、サーバの構築云々とかやらなくてもHerokuにデプロイしたら動いたんだけど、なんで？
- Buildpackという仕組みによって、アプリケーションに必要なツールをダウンロードしてくれたりする。最高か。いや、神か。
- HerokuではDynosというのがいい感じにやってくれるらしい。
    - [Heroku Dynos](https://jp.heroku.com/dynos)
- DockerとPaaSの関係などが非常にわかりやすかったし面白かった。
    - [http://techtarget.itmedia.co.jp/tt/news/1601/28/news04.html](http://techtarget.itmedia.co.jp/tt/news/1601/28/news04.html)
        - これは導入のアジャイル開発やDevOpsはちょっとよくわかんなかった（そりゃそうだろ感があった）が、それを実現するための技術として紹介されていたDockerやPaaSに関する内容は充実していて面白かった。

# その他参考文献
（別に全部読んでないです。必要なところだけ。）

## 本
- [プロになるためのWeb技術入門](http://amzn.asia/d/eGMV8yh)
- [Webを支える技術](http://amzn.asia/d/8U7FaHg)
- [新人エンジニアのためのインフラ入門](http://amzn.asia/d/fTD5EvV)

## サイト
- [PaaSの基礎知識とHerokuで開発を始める準備](https://codezine.jp/article/detail/8051)
- [ApacheとNginxとPassengerとUnicornの違い【すごい初心者向け】](http://fujiike.hateblo.jp/entry/2015/08/20/170751)
- [Apache HTTP ServerとApache Tomcatの連携する意味](https://fa11enprince.hatenablog.com/entry/2015/01/19/233740)
- [Why should I integrate Apache with Tomcat? (or not)](https://wiki.apache.org/tomcat/FAQ/Connectors#Q3)
- [Cloud Foundryで学ぶ、PaaSのしくみ講座](https://www.slideshare.net/jacopen/paas-for-beginners)

## 読みたいなーと思った本
（どなたか持っていたら貸してくださると嬉しいです。）

- [Webサーバを作りながら学ぶ 基礎からのWebアプリケーション開発入門 (Software Design plus)](http://amzn.asia/d/eSh4pzE)
- [Docker/Kubernetes 実践コンテナ開発入門 ](http://amzn.asia/d/8rtl8x9)
入力直後に変換を入れる場合のUX

## Controlledのメリット

ReactではControlled Componentといって、デフォルトで`<input>`などにデータは保存されず、`onChange`イベントでデータを拾って回収する必要があります。

ただ、必ずしもこれは入力フォームのデータをそのまま保存する必要がない、ということでもあります。たとえば、内部で扱うデータは摂氏だけど、`onChange`で華氏→摂氏に変換、`value`で逆変換を行えば、データ構造に変化なくフォームだけ華氏に切り替えられます。

## 不可逆変換の、UX上の問題点

そのように、可逆な変換を行う分にはユーザーが気づく機会もなく、便利なだけなのですが、不可逆な変換を入れるととたんにややこしくなります。

たとえば、`onChange`で数字をコンマ区切りにするような処理を入れた場合、「12,345」を入力するつもりであっても、「1234」まで入力したところで「1,234」となってしまい、なかなか気持ち悪いものとなります。

さらに、`onChange`で特定の文字だけ削るような処理を入れると、その文字を入力した場合に**何も反応しない**ような挙動となってしまいます。ユーザーの操作を「認識はしているけど表示上は何も変化しない」挙動を起こすと、ユーザーとしては「押していないんじゃないか」と不安をいだいたりして、ユーザー体験を損ねてしまいます。

## 対策

「入力を受け付ける」→「自動変換」というプロセスがわかりやすくなるようにするために、変換は`onBlur`まで遅らせてしまうのもいいでしょう。入力が終わってフォーカスを移せば、値が変換されます。Reactで再現するには、本来の値データ以外に「入力中の仮の値」を入れるためのデータ領域が必要となります。

```jsx
class BlurChangingInput extends React.Component{
  state = {
    value: '',
    inputtingValue: null
  }

  // そのまま入力中の値を格納するだけ
  handleChange = e => {
    this.setState({inputtingValue: e.target.value});
  }
  
  // 値を変換（ハイフンを消す）
  // 入力中の値はクリア
  handleBlur = () => {
    const value = this.state.inputtingValue.replace(/-/g, '');
    this.setState({value, inputtingValue: null});
  }
  
  render() {
    const {inputtingValue, value} = this.state;
    const displayValue = inputtingValue == null ? value : inputtingValue;
    return(
      <input type="text"
        value={displayValue}
        onChange={this.handleChange}
        onBlur={this.handleBlur}
        placeholder="ハイフンは自動で消えます"
        className="form-control"
      />
    );
  }
}
```

なお、`inputtingValue == null`としていますが、**空文字列も正当な値**なので、`inputtingValue || value`とした場合にはフォームを空にしようとした瞬間に元の値が復活する、という挙動になってしまいます。


## CodePenに上げました

比較のために「その場でハイフンを消す」フォームと「blurで消す」フォームを作ってみました。動きをご自身でも試していただければと思います。

<p data-height="265" data-theme-id="0" data-slug-hash="xQWKBJ" data-default-tab="html,result" data-user="jkr2255" data-pen-title="xQWKBJ" class="codepen">See the Pen <a href="https://codepen.io/jkr2255/pen/xQWKBJ/">xQWKBJ</a> by Jkr2255 (<a href="https://codepen.io/jkr2255">@jkr2255</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
immutableな即値のリファレンスは再利用されるけどmutableな即値のリファレンスは再利用されずに新しく作られるし、immutableな即値のリファレンスの格納場所は遠いという知見を得た。

メモ書きです。
もうちょっと詳しく調べたいため、書き残しておきます（こうやって公開しておけば、サボらずに調べるでしょきっと!）。
何か知ってたり、指摘がある場合はコメントしてください。嬉しいです。

## Immutableな即値のリファレンス
```Rust
fn main() {
    let s = &1000u32;
    let t = &1000u32;
    println!("s  :{}, {:p}, {:p}", *s, s, &s);
    println!("t  :{}, {:p}, {:p}\n", *t, t, &t);
}
```

結果はこう。

```
s  :1000, 0x560b2a7ec5c0, 0x7ffe04f9aa90
t  :1000, 0x560b2a7ec5c0, 0x7ffe04f9aa98
```

変数sとtは同じアドレスを指している（へぇー）。
でも変数自体の番地は違うな（当たり前）。

## Mutableな即値のリファレンス

```Rust
fn main() {
    let s = &mut 1000u32;
    let t = &mut 1000u32;
    println!("s  :{}, {:p}, {:p}", *s, s, &s);
    println!("t  :{}, {:p}, {:p}\n", *t, t, &t);
}
```

結果はこう。

```
s  :1000, 0x7ffd8c5934fc, 0x7ffd8c5934f0
t  :1000, 0x7ffd8c59350c, 0x7ffd8c593500
```

あー、ふーん...(わからん）。
なるほど...?つまりこういう事か？

![memory.png](https://qiita-image-store.s3.amazonaws.com/0/150312/87ff381d-bf30-923a-124e-ecc18f143cdb.png)

immutableな時とmutableの時で、なんで即値の格納場所が変わるんだろう。

### immutableな変数とmutableな変数の比較

以下のコードも動かしてみた

```Rust
fn main() {
    let s = &1000u32;
    let t = &1000u32;
    println!("s  :{}, {:p}, {:p}", *s, s, &s);
    println!("t  :{}, {:p}, {:p}\n", *t, t, &t);

    let s = &1000u32;
    let mut t = &1000u32;
    println!("s  :{}, {:p}, {:p}", *s, s, &s);
    println!("t  :{}, {:p}, {:p}\n", *t, t, &t);

    let s = &1000u32;
    let t = &mut 1000u32;
    println!("s  :{}, {:p}, {:p}", *s, s, &s);
    println!("t  :{}, {:p}, {:p}\n", *t, t, &t);
}
```

結果はこう。

```
s  :1000, 0x558ff5a9fec0, 0x7ffe8895f048
t  :1000, 0x558ff5a9fec0, 0x7ffe8895f050

s  :1000, 0x558ff5a9fec0, 0x7ffe8895f188
t  :1000, 0x558ff5a9fec0, 0x7ffe8895f190

s  :1000, 0x558ff5a9fec0, 0x7ffe8895f2c8
t  :1000, 0x7ffe8895f2dc, 0x7ffe8895f2d0
```

うーん、わからんけど、タイトルの知見を得た。
コード実行して適当に考えただけの仮説だけど、

- immutable即値は変更する必要もないのでReadOnlyなエリアに置く
- mutableな即値・変数は、変更可能なため、スタック領域に置く
    - immutableな変数はドロップをしたいため、ReadOnlyなエリアには置かない

立ててみました。
これを立証するためのコード、もしくはドキュメントがあればいいんだけど...。
誰かご存知ないでしょうか。

## 超解説！！！！！！！！！

わかったら追記します。