dorapon2000’s diary

忘備録的な。セキュリティとかネットワークすきです。

Perlのautovivificationをいろいろ実験

Modern Perlを読んでいたら、autovivificationという機能があるということを今更ながら知った。たいへん便利だ。。。癖が強いらしいので手を動かして挙動を確かめてみる。

autovivificationとは

my %users;
$users{Brad}{id} = 228;
$users{Jack}{id} = 229;

$users{Brad}はまだ定義されていない(undef)はずだが、$users{Brad}{id}で代入できている。これはperl$users{Brad}を自動生成しているからで、autovivificationと呼ぶ。

perldocにもしっかりと説明がある。 autovivification

実験

Perl 5.30.2で行った。

use Data::Dumper;

sub func_array {
    my @h = @_;
    return @h;
}

sub func_ref {
    my ($h) = @_;
    return $h;
}

{
    # ハッシュ
    my %h;
    $h{empty}{aaa} = 'CCC';
    $h{not_empty}{aaa} = 'ZZZ';
    if (undef $h{undeff}{aaa}) {}
    if (exists $h{exists}{aaa}) {}
    func_array($h{via_func}{aaa});
    warn Dumper(\%h);
}

{
    # ハッシュリファレンス
    my $h;
    $h->{empty}->{aaa} = 'CCC';
    $h->{not_empty}->{aaa} = 'ZZZ';
    if (undef $h->{undeff}->{aaa}) {}
    if (exists $h->{exists}->{aaa}) {}
    func_ref($h->{via_func}->{aaa});
    warn Dumper($h);
}

{
   # 宣言と代入が同じ場合
    my $h->{aaa}->{bbb} = 'CCC';
    warn Dumper($h);
}

出力結果

$VAR1 = {
          'exists' => {},
          'undeff' => {
                        'aaa' => undef
                      },
          'via_func' => {},
          'empty' => {
                       'aaa' => 'CCC'
                     },
          'not_empty' => {
                           'aaa' => 'ZZZ'
                         }
        };
$VAR1 = {
          'not_empty' => {
                           'aaa' => 'ZZZ'
                         },
          'empty' => {
                       'aaa' => 'CCC'
                     },
          'via_func' => {},
          'undeff' => {
                        'aaa' => undef
                      },
          'exists' => {}
        };
$VAR1 = {
          'aaa' => {
                     'bbb' => 'CCC'
                   }
        };
  • リファレンスであろうと、なかろうと、宣言と同時に代入しようとautovivificationはされた
  • 参考のQiitaの記事でも取り上げられているように、undef関数でもautovivificationされた
  • キーの存在確認をするexistsですらautovivificationされた
  • undefとexistsでは生成のされ方が少し違うので注意
  • 関数に存在しないキーで引数として渡す際にもautovivificationされたが、最後までは生成されなかった?

no autovivification

参考で上げているQiitaの記事ではautovivificationというプラグマモジュールでautovivificationをいい感じに無効化していたため、インストールして使ってみた。

$ cpanm autovivification
# この一行を先程のコードの先頭に追加
no autovivification;
# no autovivification qw/ fetch exists delete /;と同じ

出力結果

$VAR1 = {
          'empty' => {
                       'aaa' => 'CCC'
                     },
          'via_func' => {},
          'undeff' => {
                        'aaa' => undef
                      },
          'not_empty' => {
                           'aaa' => 'ZZZ'
                         }
        };
$VAR1 = {
          'undeff' => {
                        'aaa' => undef
                      },
          'empty' => {
                       'aaa' => 'CCC'
                     },
          'via_func' => {},
          'not_empty' => {
                           'aaa' => 'ZZZ'
                         }
        };
$VAR1 = {
          'aaa' => {
                     'bbb' => 'CCC'
                   }
        };

existsだけautovivificationが無効化された。metacpanに書かれているが、何も指定せずno autovivificationした場合、rvalueデリファレンス$h->{a}->{b}が右側)・exists・deleteでautovivificationが無効化されるようだ。storeを指定すればlvalueデリファレンス$h->{a}->{b}が左側)でも対応できる。

no autovivification qw/  fetch exists delete store /;

storeを指定すると上で示したコードは実行できないコードとなるので、適宜修正する必要がある。もし実行した場合、以下のようなエラーが出る。

Can't vivify reference at tmp.pl line 16.

参考

qiita.com

developer.hatenastaff.com

最近読んだ本の感想

半年近くブログを更新していないせいで広告が出てしまったため、最近読んだ本をネタに更新しておく。

読んだ本一覧

開発系

  • ドメイン駆動設計入門
  • カイゼン・ジャーニー
  • Effective Python第2版
  • 達人に学ぶDB設計徹底指南書
  • 達人に学ぶSQL徹底指南書第2版
  • ソフトウェア技法練習帳
  • 最強のCSS設計

それ以外

  • 予想どおりに不合理
  • 「ついやってしまう」体験のつくりかた

ドメイン駆動設計入門

現実世界の注目している領域をドメインと呼び、それをコードへ落とし込むためにどういう思想や設計が必要かがわかりやすく記載されている。

ドメイン駆動設計入門 ボトムアップでわかる! ドメイン駆動設計の基本 | 成瀬 允宣 |本 | 通販 | Amazon

中規模なモジュールを1から作るにはどうすればいいのか、自分には皆目検討がつかないなぁと思い購入。自分はオブジェクト指向というメリットを活かしきれてなかったと痛感した。デザインパターンは勉強してきたけれど、設計とは目的が違う。自分の経験の中で、『最初はこれでうまくいくと思ってた設計は柔軟性がなく、拡張してたら似てるロジックがいたるところに、、、じゃあどうすればよかったかなんて考えてもわからない。』なんてことがあったけど、答えはこの本の中に。

個人的に好きだったのはリポジトリリポジトリでDB依存な実装を隠せば複数DB扱えるし、テストもしやすいというのはそのとおりだと思う。ただ、トランザクションまで設計で扱うのはやりすぎて逆に複雑になりそうだと思った。また、ドメイン駆動設計を取り入れるにはチームの同意も必要。

カイゼン・ジャーニー

ストーリー形式にアジャイル開発について学べる本。

カイゼン・ジャーニー たった1人からはじめて、「越境」するチームをつくるまで | 市谷 聡啓, 新井 剛 |本 | 通販 | Amazon

とても読みやすかった。主人公の江島がアジャイルのツールを使いながら問題解決していくのは臨場感あって、雰囲気でしか知らなかったアジャイル開発がどういうものなのか理解できた。

Effective Python第2版

Pythonの知られざるチップが90項目も書かれている。第2版でpython3.8対応。

Effective Python 第2版 ―Pythonプログラムを改良する90項目 | Brett Slatkin, 石本 敦夫, 黒川 利明 |本 | 通販 | Amazon

実は初版も昔読んでいる。掲載されている項目数も増えてpython3.8にも対応しているとのことで購入(並べてみると2.5倍くらい厚い)。自分が初版の内容を忘れてるor当時理解できなかったこともあり、2回目でも十分学びがあった。python3.8で追加されたwalrus演算子(:=)で不要に変数のスコープを広げないテクニックを見て、pythonっぽいと感じたり、特殊メソッド駆使してOOPをするテクニックはそんなに頑張るのかとも思いつつわくわくした。特に「並行性と並列性」の章は気合が入っているように感じて、pythonにはGILという制約がある中、いろいろな並列・並行処理のやり方を紹介している。家宝にします。

達人に学ぶDB設計徹底指南書

標準的なDBの、物理設計、正規形の説明からパフォーマンス設計、アンチパターン、グレーノウハウなどを説明している。

達人に学ぶDB設計 徹底指南書 | ミック | 工学 | Kindleストア | Amazon

特定のDBに依存しない部分で設計のノウハウ解いている。もともとMySQL関係の本を買うつもりだったが、DBの共通部分で一旦勉強しておいたほうが良いと思い購入。アンチパターンとグレーノウハウで著者がどれくらいの頻度で現実に存在するのか言及していたり、INDEXを貼るレコード数やカーディナリティの具体的な目安は、応用する際の助けになると思った。

達人に学ぶSQL徹底指南書第2版

標準的なSQLを駆使して複雑なことをクエリ一発で解決しようという本。

達人に学ぶSQL徹底指南書 第2版 初級者で終わりたくないあなたへ | ミック | コンピュータ・IT | Kindleストア | Amazon

上の作者のSQLの本。DB設計の本は2012年発売と少し古いが、こちらは2018年なため新しい。基本的にORMを使うため生のSQLをコードに埋め込むことはあまりないが、複雑なSQLに興味があったため購入。この本のおかげで、どこまでがDBの一般的な機能なのかという線引きができた。例えば、複合インデックスを使う場合、WHERE句にはインデックスに定義した順番でカラムを指定する必要があるというのはMySQLの機能だと勝手に思っていたが、この本に書かれており、DB共通のやり方だと知った。また、ある程度、排中律や述語などの論理学をベースにすすめるため、厳密性もあっていい。

SQLを構築するのはパズルのようで面白かったが、そこまで複雑なことはSQLではなくプログラムにやらせそうとは思った。

ソフトウェア技法練習帳

ソフトウェアテストの演習を、同値分割法・境界値分析、デシジョンテーブル、状態遷移テストなどの方法を用いてこなしていく。

ソフトウェアテスト技法練習帳 ~知識を経験に変える40問~ | 梅津 正洋, 竹内 亜未, 伊藤 由貴, 浦山 さつき, 佐々木 千絵美, 高橋 理, 武田 春恵, 根本 紀之, 藤沢 耕助, 真鍋 俊之, 山岡 悠, 吉田 直史 | コンピュータ・IT | Kindleストア | Amazon

境界値を選んで終わりという雑なテストの知識しかなかったため、新しい知識を取り込んで行きたいと思い購入。それぞれの手法の説明は一切ないが、ググりながらで十分演習ができた。ただ、組み合わせテストのためにPictMasterというツールを紹介しているが、当方Excelが使えないためできる問題だけこなした。要件を確認することが答えに含まれていたり、実践的で経験になった。

最強のCSS設計

OOCSS、SMACSS、BEMなどのCSS設計をケーススタディ形式で学べる。

Amazon.co.jp: 最強のCSS設計 チーム開発を成功に導くケーススタディ eBook: 堀口 誠人: Kindleストア

本棚に積まれていた本をようやく読んだ。ストーリー形式で読みやすいしレイアウトもわかりやすい。ストーリーの若手役の人がする失敗は自分もしそうで、文量抑えめなのに良いポイントを抑えてくれてると思った。自分のCSSはBootstrapの構造を真似ているだけだったため、ここでいったんOOCSSの知識を学べてよかった。BEMを使う機会はおそらく当分ないが、知識として持っておきたかった。さくっとCSS分野を学べる自分にあっている本だった。

予想どおりに不合理

大量の実験(多くは著者自身が行った)や例をもとに、人間が以下に不合理な行動を繰り返しているかを説明する行動経済学の本。

予想どおりに不合理 行動経済学が明かす「あなたがそれを選ぶわけ」 | ダン アリエリー, 熊谷 淳子 | 産業研究 | Kindleストア | Amazon

この記事に列挙したなかで一番読んでよかった。この本は以下の広告から始まる。

  1. 59ドルのオンライン新聞購読
  2. 125ドルの印刷版新聞購読
  3. 125ドルのオンラインと印刷版新聞購読

2が意味不明と思いながら買うなら3つ目を選ぶ人は多いと思う。実際に学生を対象にした実験では多かった。しかし

  1. 59ドルのオンライン新聞購読
  2. 125ドルのオンラインと印刷版新聞購読

この2つだけになった途端に1を選ぶ人が多くなる。マーケティングの知識がまったくない自分にとっては冒頭からドキリとさせられた。こういう例が大量にあり、ビジネスに限らず様々なことに応用できそうだと感じた。各実験に対する参考文献がしっかり記載されている点もうれしい。

「ついやってしまう」体験のつくりかた

任天堂wiiの企画担当を務められていた方なりにUXを体系的にまとめた本。

「ついやってしまう」体験のつくりかた――人を動かす「直感・驚き・物語」のしくみ | 玉樹 真一郎 | 産業研究 | Kindleストア | Amazon

予想通りに不合理もそうだが、分厚い技術書ばかりだとモチベーションが保てないので息抜きに購入。UXについての知識は皆無なので手始めに良さそうだと思った。そして、スーパーマリオブラザーズのマリオにはヒゲがあるのか、帽子をかぶっているのか、ステージ1-1のマリオの初期位置が中央ではないのか、などはすべて理由があることを知った。この本の中で一番印象的だったのは、ゲームにギャンブル要素とユーザーの性格が出てしまう選択肢を入れることがユーザーの飽きない・成長する体験につながること。特にギャンブルは予想通りに不合理でも触れられている。

mac + miniconda + VSCodeでPython環境構築

前から書きたかった自分なりのPython環境の構築方法をまとめる。

どの言語でも同様だが、環境構築の際は言語のバージョン管理、プロジェクトごとの環境切り替えが大切になる。nodeであればnodenv+npmで、perlであればplenv+cartonでそれらを実現できる。pythonはというとAnacondapyenvvirtualenvvenvPipenvなどなど戦国時代のごとく様々なツールが存在し、どれが自分にあっているのか悩む。

各ツールの違いについては以下の記事がわかりやすい。

qiita.com

結局のところ、自分にはminicondaでバージョン管理と環境切り替えをして、コーディングはVSCodeでやるのが一番あっていた。バージョン管理と環境切り替えを1つのツールでできるのが便利。大元のAnacondaと違って、軽いからすぐインストールできる点も嬉しい。

目次

  • miniconda
    • minicondaのインストール
    • condaの簡単な使い方
    • 仮想環境を配布する
    • condaの注意点
  • VSCode

実施環境

  • macOS Catalina 10.15.4
  • fish 3.1.0
  • conda 4.7.12
  • VSCode 1.44.4

miniconda

minicondaのインストール

公式のインストーラでもインストールできるが、macならbrewで一発。

$ brew install Caskroom/cask/miniconda

# fishの人は
$ conda init fish  # ~/.config/fish/config.fishにコマンドが追加される

# zshの人は
$ conda init zsh  # ~/.zshrcにコマンドが追加される

f:id:dorapon2000:20200429004122p:plain

成功すると右側に(base)と表示される。 condaは仮想環境ごとにPythonのバージョンとモジュールを管理していて、baseはデフォルトの仮想環境。

condaの簡単な使い方

# baseのPythonのバージョン
$ python --version
3.7.4

# 最初の仮想環境はbaseしかない
$ conda info -e
# conda environments:
#
base                  *  /usr/local/Caskroom/miniconda/base

# Python 3.8で新しい仮想環境を作成
$ conda create -n test_env python=3.8

# test_envという仮想環境が追加されている
$ conda info -e
# conda environments:
#
base                  *  /usr/local/Caskroom/miniconda/base
test_env              *  /usr/local/Caskroom/miniconda/base/envs/test_env

# test_envにスイッチ(右側にtest_envと表示される)
$ conda activate test_env

# しっかりpythonのバージョンが切り替わっている
$ python --version
3.8.2

# ここにインストールするモジュールはこの環境下でだけ使える
$ conda install numpy -y

# モジュールが存在するためバージョン情報を表示できる
$ python -c "import numpy;print(numpy.version)"
1.18.1

# デフォルト環境に切り替える
$ conda activate base

# この環境にはnumpyがないためエラー
$ python -c "import numpy;print(numpy.__version__)"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'numpy'

# 環境の削除
$ conda remove -n test_env --all

# ふりだしに戻る
$ conda info -e
# conda environments:
#
base                  *  /usr/local/Caskroom/miniconda/base

プロジェクトごとに新しい仮想環境を作成して、そこに必要モジュールをインストールしていくという使い方になる。 そのプロジェクトで必要なモジュールがなにかはっきりする。

仮想環境を配布する

手元の仮想環境を他の端末や他の人の環境でも再現させることができる。

$ conda create -n test_env python=3.8
$ conda activate test_env
$ conda install numpy -y

# 環境をenv.yamlに書き出す
$ conda env export > test_env.yaml
$ cat test_env.yaml
name: test_env
channels:
  - defaults
dependencies:
  - blas=1.0=mkl
  - ca-certificates=2020.1.1=0
...略
prefix: /usr/local/Caskroom/miniconda/base/envs/test_env

# もとの環境を削除しても
$ conda activate base
$ conda remove -n test_env --all

# test_env.yamlで再現できる
$ conda env create --file test_env.yaml
$ conda info -e

condaの注意点

condaにないモジュール

中にはconda installでは入手できないモジュールも存在するが、そういうときは仕方ないのでpipでインストールする。 condaはpipとは連携していないため、pipでいれたモジュールは仮想環境を切り替えてもimportできてしまうし、conda env exportしてもそこに情報は残らない。でも仕方ない。

anyenvやpyenvとの併用

condaが併用するようには作られていないため、バグる可能性がある。

VSCode

(前準備)VSCodeのインストール

以下からインストール

Download Visual Studio Code - Mac, Linux, Windows

必要な拡張機能とモジュールのインストール

エディタとして欲しい機能は①デバッグ機能、②Lint、③自動整形の3つ。

marketplace.visualstudio.com

拡張機能Pythonを入れる。

この拡張機能はflake8とautopep8を後ろで動かしてLintと自走整形をするからインストールする。

$ conda activate test_env
$ conda install flake8 -y
$ conda install autopep8 -y

仮想環境の切り替え

f:id:dorapon2000:20200429131811p:plain

VSCodeの左下にpythonのバージョン情報が書かれるようになった。 そこをクリックするとVSCodeで使うpythonを切り替えられる。

f:id:dorapon2000:20200429131847p:plain

先ほど作成したtest_envにしてみる

f:id:dorapon2000:20200429131905p:plain

Pythonデバッグ

Pythonファイルを開いてF5を押すとデバッグの構成を聞かれるので「Python File」を選ぶ。

f:id:dorapon2000:20200429133052p:plain

実行結果が下のターミナルに表示される

f:id:dorapon2000:20200429133109p:plain

Hello world!!

PythonでLint

setting.jsonでLintにflake8を使うよう書く。

# setting.json
    "python.linting.enabled": true,
    "python.linting.pylintEnabled": false,
    "python.linting.flake8Enabled": true,
    "python.linting.lintOnSave": true,

参考:https://qiita.com/psychoroid/items/2c2acc06c900d2c0c8cb

f:id:dorapon2000:20200429134223p:plain

保存する度に、文法的な誤りやPEP8に準拠しない書き方の部分に赤波線がつく。 python.linting.lintOnSaveをfalseにすれば、逐次誤りを指摘してくれるが、まだ書き途中に波線つくのが嫌いなのでtrueにしている。

Pythonで自動整形

setting.jsonで自動整形にautopep8を使うよう書く。

# setting.json
    "python.formatting.provider": "autopep8",
    "[python]": {
        "editor.formatOnSave": true,
    },

保存するたびに、自動整形してくれるようになる。自動整形せずに保存したい場合はコードパレットでSave without Formattingを選ぶ。

一部のルールを無効にする

基本はコーディング規格のPEP8に準拠したいけれど、個人的に3つのルールを--ignoreしている。

E501

横幅を79文字以内にしろというルール。さすがに許して。

W503W504

複数行にまたがる式を書くときに演算子を前に書け(W503)と後ろにかけ(W504)という矛盾した対のルール

# W503準拠
income = (gross_wages
          + taxable_interest)

# W504準拠
income = (gross_wages +
          taxable_interest)

好みの方だけ--ignoreできるよう2つ用意されているが、喧嘩両成敗でどちらも--ignoreしてしまう。他の人のコードをVSCodeで見るときに赤波線がついてほしくない

setting.json

# setting.json
    "python.linting.flake8Args": [
        "--ignore=E501,W503,W504",
    ],
    "python.formatting.autopep8Args": [
        "--ignore=E501"
    ],

autppep8の方は、何もしなくてもデフォルトでW503とW504の整形が無効化されている。整形してほしい場合は--selectを使う。

# setting.json
    "python.formatting.autopep8Args": [
        "--ignore=E501",
        "--select=W503"
    ],

まとめ

  • バージョンと環境切り替えはconda
  • コーディングはVSCode

よきpythonライフを〜

VSCodeのPerl開発環境

Perl5でデバッグ・Lint・自動整形ができるVSCode環境を整えたので忘備録。

環境

(前準備)Perlのインストール

VSCodeと関係ないが、バージョン管理ができるplenvでperlをインストールした。

# plenvのインストール
$ brew install plenv
$ brew install perl-build

# シェル起動時にplenvを自動で初期化(fish版)
# https://formulae.brew.sh/formula/plenv
$ echo 'if plenv > /dev/null 2>&1; plenv init - | source ; end' >> ~/.config/fish/config.fish
$ source ~/.config/fish/config.fish

# シェル起動時にplenvを自動で初期化(bash版)
# https://tutorial.perlzemi.com/blog/20180816153437.html
$ echo 'export PATH="$HOME/.plenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(plenv init -)"' >> ~/.bash_profile
$ exec $SHELL -l

# インストールが成功していればバージョンが表示される
$ plenv --version

# インストールできるperlのバージョン一覧(エラー後述)
$ plenv install -l

# (メモっていたときの)最新バージョンをインストール
$ plenv install 5.30.1 --as 5.30

# 現在のperlのバージョン
$ plenv version

# 使用するperlのデフォルトを先程ダウンロードしたバージョンに変更
$ plenv global 5.30.1

# ちゃんと変更されたか確認
$ plenv version

# インストールされているperlのバージョン一覧
$ plenv versions
  system
* 5.30 (set by /Users/dorapon/.plenv/version)

パッケージ管理ツールcpanmをインストール。

$ plenv install-cpanm
$ cpanm --version

エラー:No backend configured for scheme https

メモを取っていた当時はうまくいっていたが、改めて手元で実行したらエラーがでた。

$ plenv install -l
Available versions:
No backend configured for scheme https at /usr/local/Cellar/perl-build/1.30/libexec/lib/perl5/CPAN/Perl/Releases/MetaCPAN.pm line 48.

検索したらこんなツイートをみつけたので、cpanmでPerl::Buildをインストールして再実行してみたらエラーが消えた。

$ cpanm Perl::Build
$ plenv install -l
Available versions:
 5.31.9
 5.31.8
 5.31.7
 5.31.6

よくわからないがめでたしめでたし。

perlデバッグ設定

marketplace.visualstudio.com

VSCode拡張機能Perl Debugを入れる。これだけでデバッグビューから簡単にPerlデバッグができるようになる。

perlのLint設定

VSCode拡張機能Perl Toolboxを入れる。Toolboxの要件にperlcriticがあるので、cpanmを使ってインストール。

$ cpanm Perl::Critic;

setting.jsonにインストールしたperlcriticまでのパスを追加。私の場合、perlcriticはホームディレクトリ直下の.plenv/以下にあった。

    "perl-toolbox.lint.path": "/Users/dorapon/.plenv/versions/5.30/bin/perlcritic",

VSCodeを再起動するとperlファイルで構文エラーがある場所に赤波線がついてくれるようになる。

f:id:dorapon2000:20200309033336p:plain

perlの自動整形

marketplace.visualstudio.com

VSCode拡張機能perltidyを入れる。perltidyの要件にperltidy(同じ名前のperlモジュール)があるので、cpanmを使ってインストール。

$ cpanm Perl::Tidy;

setting.jsonにインストールしたperltidyまでのパスを追加。保存時に自動整形してくれるようにもする。

    "[perl]": {
        "editor.formatOnSave": true,
    },
    "perltidy.executable": "/Users/dorapon/.plenv/versions/5.30/bin/perltidy",

VSCodeを再起動するとperlファイルの保存時に自動整形してくれるようになる。

perlシンタックスハイライト

拡張機能Better Perl SyntaxとテーマSyntax Highlight Themeを入れた。

    "workbench.colorTheme": "Syntax Material Dark",

f:id:dorapon2000:20200309034331p:plain

おしゃれ🍷

おわりに

どんな言語でもバージョン管理ツール・デバッグ・Lint・自動整形環境は整えたい。

参考

plenvを使ったPerl環境構築 〜2018年度版〜 - Masteries

VSCodeでPerlデバッグ - Qiita

cpanmによるPerlのローカル環境構築 - Perlプログラミング入門ゼミ - Perlでテキスト処理・Linuxサーバー管理・Webシステム開発

perlcriticを使って自動でコードの品質を担保する仕組みを作ってみた - Qiita

Perlのコード整形ツールPerltidyを導入する - Qiita