読者です 読者をやめる 読者になる 読者になる

mizdra's blog

ぽよぐらみんぐ

夏のCLI commandsものまね大会

「夏のCLI commandsものまね大会」、やります。

概要

ザックリ言うとCLI commandsをNode.jsで実装します。例えば、lsコマンドのようにNode.jsで特定のディレクトリに格納されているファイル一覧を出力するCLI commandを作るといった感じです。

方針

制作していくにあたって方針を立てておきます。

  1. 任意のCLI commandsをNode.jsで実装する。
  2. 実装は満足する範囲内で行うものとし、全ての機能を実装したり1つの機能を完璧に実装する必要はない。
  3. 使用する言語はNode.js(version: 6.4.0)とする。
  4. ES 2015+で書く。
  5. babelやtscなどのトランスパイラを用いても、最終的にNode.jsで実行可能であれば良しとする。
  6. コードは綺麗に時間を掛けて書く。
  7. 可能な限りライブラリを使用する。
  8. コードを書き終えたらコーディング中に思ったことや感想などを記事にする。

リンク

あとがき

頑張ります。

管理者権限無しでCentOS 6.5上にC++開発環境を作成した時のメモ

大学の講義てC++を書いていて、大学のPC上でもシンタックスハイライトとか補完とかを効かせながらC++コーディングしたいなと思っていた。 以下はvimで良い感じのC++開発環境を構築したときのメモ。

目標 & 方針

  • clangの導入
  • vimC++開発
  • sudo権限がなく、yumなどの付属のパッケージマネージャを利用することができないので、自前でビルドし、porgでインストールする
    • バイナリは~/localフォルダにインストールする
    • ただし、vimプラグインはneobundle.vimを使って.vim/bundleにインストールする

環境

  • CentOS(x86_64) 6.5
  • sudo権限を持たないユーザで作業
  • シェルはtcsh
  • インストールされているvimluaが有効になっていない

(大学のサーバなのでセキュリティ上あまり詳しいことは書けない…)

準備

  • ~/localディレクトリを作成し、~/local/binにPATHを通しておく
  • neobundle.vimを導入しておく

インストールしたもの一覧

欲しいものはllvm, vim-clang, color_codedのみだが、依存パッケージのインストールされていたバージョンが低かったり、そもそもインストールされていなかったりしていたので、合計10個のパッケージを新規インストールすることになった。

  1. porg 0.8 (パッケージ管理に使用)
  2. gcc 6.1.0
  3. python 2.7.11
  4. cmake 3.5.2
  5. llvm 3.8.0 (python 2.7+, gcc 4.7.0+に依存、build時にcmake 3.4.3+が必要)
  6. lua 5.3.2
  7. vim 7.4 (luaに依存)
  8. vim-clang (clang, vimに依存)
  9. glibc 2.17
  10. color_coded (clang, vim 7.4p330+, lua 5.1+, gcc 4.9+, glibc 2.15+に依存)

1から順にインストールしていく。

1. porgのインストール

$ tar xzvf porg-0.8.tar.gz
$ cd porg-0.8
$ ./configure --disable-grop --prefix=$HOME/local
$ make
$ make install
$ make logme

2. gccのインストール

# `ftp.tsukuba.wide.ad.jp/software/gcc/releases/`から最新版のgccをDLする
$ wget http://ftp.tsukuba.wide.ad.jp/software/gcc/releases/gcc-6.1.0/gcc-6.1.0.tar.gz
$ tar xf gcc-6.1.0.tar.gz
$ cd gcc-6.1.0

# 必要なパッケージのDL
$ contrib/download_prerequisites

# ビルド用ディレクトリ作成
$ mkdir ../build
$ cd ../build

# configure
$ ../configure --disable-multilib --enable-languages=c,c++ --host=x86_64-redhat-linux --build=x86_64-redhat-linux --target=x86_64-redhat-linux --disable-libgcj --with-system-zlib --enable-checking=release --prefix=$HOME/local --with-local-prefix=$HOME/local

# ビルド(時間掛かる)
$ make -k -j8 STAGE1_CFLAGS='-march=core2 -O3' BOOT_CFLAGS='-march=native -Os' >& /dev/null && echo "GCCビルド成功" || echo "GCビルド失敗"
$ porg -lp gcc-6.1.0 "make install"

3. pythonのインストール

$ wget https://www.python.org/ftp/python/2.7.11/Python-2.7.11.tar.xz
$ tar xf Python-2.7.11.tar.xz
$ cd Python-2.7.11
$ ./configure --host=x86_64-redhat-linux --build=x86_64-redhat-linux --target=x86_64-redhat-linux --prefix=$HOME/local CFLAGS="-march=core2 -O3"
$ make -j8
$ porg -lp python-2.7.11 "make install"

4. cmakeのインストール

$ wget https://cmake.org/files/v3.5/cmake-3.5.2.tar.gz
$ tar xf cmake-3.5.2.tar.gz
$ cd cmake-3.5.2
$ ./configure --prefix=$HOME/local
$ make -j8
$ porg -lp cmake-3.5.2 "make install -j8"

5. llvmのインストール

# llvmのDL
svn co http://llvm.org/svn/llvm-project/llvm/tags/RELEASE_380/final llvm

# clangのDL
cd llvm/tools
svn co http://llvm.org/svn/llvm-project/cfe/tags/RELEASE_380/final clang
cd ../...

# compiler-rtのDL
cd llvm/tools/clang/tools
svn co http://llvm.org/svn/llvm-project/clang-tools-extra/tags/RELEASE_370/final extra
cd ../../../..

# ビルド用ディレクトリ作成
$ mkdir build
$ cd build
$ cmake -G "Unix Makefiles" -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_ASM_COMPILER=gcc -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$HOME/local -DGCC_INSTALL_PREFIX="${HOME}/local" -DLLVM_PARALLEL_COMPILE_JOBS=8 -DLLVM_PARALLEL_LINK_JOBS=8 -DLLVM_TARGETS_TO_BUILD="X86" ../

# ビルド(すごく時間掛かる)
$ make -j8

$ porg -lp llvm-3.8.0 "make install"

6. luaのインストール

$ wget http://www.lua.org/ftp/lua-5.3.2.tar.gz
$ tar zxvf lua-5.3.2
$ cd lua-5.3.2
$ make linux
$ porg -lp lua-5.3.2 "make install INSTALL_TOP=$HOME/local"

# 確認
$ lua -v
Lua 5.3.2  Copyright (C) 1994-2015 Lua.org, PUC-Rio

7. vimのインストール

$ wget https://github.com/vim/vim/archive/master.zip
$ unzip -d vim master.zip
$ cd vim/src
$ ./configure --enable-multibyte --enable-xim --enable-fontset --enable-luainterp --with-features=huge --disable-selinux --prefix=$HOME/local --enable-luainterp=yes --with-lua-prefix=$HOME/local --enable-rubyinterp=yes --enable-pythoninterp=yes --with-python-config-dir=$HOME/local/lib/python2.7/config
$ make -j8
$ porg -lp vim-7.4 "make install"

# 確認
$ ./vim --version | grep +lua
+dialog_con_gui  +lua             +rightleft       +windows

8. vim-clangのインストール

vimプラグインマネージャを利用すれば簡単にインストールできるので省略。

9. glibcのインストール

$ wget http://ftp.gnu.org/gnu/glibc/glibc-2.17.tar.gz
$ tar zxvf glibc-2.17.tar.gz
$ mkdir glibc-2.17/build
$ cd glibc-2.17/build

# パスが通ってるディレクトリに入れると既存のglibcと競合して不具合が発生するので、ここでは``$HOME/local/glibc-2.17``に入れた
$ ../configure --prefix=$HOME/local/glibc-2.17 --enable-shared --disable-profile --disable-debug

$ make

# 以下を実行するとエラーが発生する。恐らくバグ。今のところ無視しても問題なく動作している。
# $ make check

$ porg -lp glibc-2.17 "make install"

10. color_codedのインストール

vimプラグインマネージャを利用すれば簡単にインストールできるので、詳細は省略。
ただし、color_codedは使用する前にビルドしておく必要があるが、その際にglib 1.15+へのパスを教えてあげなければ正しくビルドが行えない。
自分はneoBundle.vimを使っていたので以下のように設定した。

NeoBundleLazy 'jeaye/color_coded', {
  \ 'build': {
  \   'unix': 'cmake -DCUSTOM_CLANG=1 -DLLVM_ROOT_PATH=$HOME/local/glibc-2.17 . && make && make install',
  \ },
  \ 'autoload': { 'filetypes' : ['c', 'cpp', 'objc', 'objcpp'] },
  \ 'build_commands' : ['cmake', 'make'],
  \ 'external_commands' : ['clang']
\}

動作確認

適当に.vimrc書いてcppファイルを開いてみた。 f:id:mizdra:20160618170226p:plain ちゃんと動いた。めでたしめでたし。

LCGでMath.imulのベンチマーク

ES2015にてjs高速化の一環としてMath.imul関数が実装された。 本記事では実装されたMath.imulとそのPolyfillのベンチマークをLCG(線形合同法)で取る。

前提

  • LCGでベンチマークを取っているのでMath.imulの演算処理のみに焦点を当てたベンチマーク結果は取れません。そうした純粋な結果のみを知りたい方はリポジトリをクローンして自分でカスタマイズして下さい。

環境

ベンチマーク詳細

function imul(a, b) {
  var ah  = (a >>> 16) & 0xffff;
  var al = a & 0xffff;
  var bh  = (b >>> 16) & 0xffff;
  var bl = b & 0xffff;
  return ((al * bl) + (((ah * bl + al * bh) << 16) >>> 0)|0);
}

// Polyfill
(function() {
    console.time('mul1');
    calc();
    console.timeEnd('mul1');
    
    function calc() {
        var seed = 0x00000000;
        var max = MAX_FRAME;
        for(var i = 0; i < max; i++)
            seed = u32(imul(0x41C64E6D, seed) + 0x6073);
    }
    
    function u32(x) {
        return x >>> 0;
    }
})();
// Math.imul
(function() {
    console.time('mul2');
    calc();
    console.timeEnd('mul2');
    
    function calc() {
        var seed = 0x00000000;
        var max = MAX_FRAME;
        for(var i = 0; i < max; i++)
            seed = u32(Math.imul(0x41C64E6D, seed) + 0x6073);
    }
    
    function u32(x) {
        return x >>> 0;
    }
})();

32bitのseedをmax回LCGで回すベンチマーク。今回はmax = 10000000とした。

結果

LCGを回し終わるまでの時間を計測する。単位はms。

Polyfill Math.imul
Chrome 361.045 493.741
Firefox 108.52 58.36
Safari 542.977 260.964

Firefox, Safariの結果は予想通りMath.imulのほうが速かった。 Chromeのみが何故かPolyfillのほうが速かったが、今後のV8エンジンの改善によって解決すると思われる。 Math.imulの中身はネイティブ実装だろうし、Polyfill使うくらいだったらMath.imulを使ったほうがいいんじゃないかな。

ソースコード

github.com

参考

反動ダメージについて

事の発端

噂の 自販機乱数の人の記事 を読んでいて、すてみタックルの反動ダメージが第六世代では「与ダメx0.33 (四捨五入)」であるのに対し、第五世代以前では「与ダメx(0x548/0x1000) (四捨五入)」と、不自然な計算式であることに疑問を感じていた。

blastoise-x.hatenablog.com

当記事の中で、第五世代以前の計算式はincorrectと述べられているように本人もあまり正確に調査していなかったようなので、自分で調べてみることにした。

調査内容

与えたダメージの1/3が自分に反動ダメージとして帰ってくると言われているすてみタックル等の技の反動ダメージの正確な計算式を調べる。

検証に使用した技

検証した世代

  • 第三世代
  • 第四世代
  • 第五世代*1
  • 第六世代*2

第一世代・第二世代は需要がなさそうということから、また調査環境が整ってないということから調べなかった。きっとやる気に満ち溢れた人が代わりに調査してくれるでしょう!!

調査結果

結論を先に書くと以下のような計算式になった。

{ \displaystyle
damage := 与えたダメージ
}
{ \displaystyle
recoil     := 反動ダメージ
}
{ \displaystyle
round     := 四捨五入関数
}
{ \displaystyle
floor     := 切り捨て関数
}

第五世代以降

{ \displaystyle
recoil = round(damage \times (33 \div 100))
}

第四世代以前

{ \displaystyle
recoil = floor(damage \times (1 \div 3))
}

例外(第三世代~第六世代共通)

反動ダメージは1より小さくならない。(最低1は反動ダメージを受ける)

詳細

1/3反動ダメージの算出方法については諸説あるが、ここでは代表的な

  • {damage \times (0\rm{x}548 \div 0\rm{x}1000)}
  •  {damage \times (1 \div 3)}
  •  {damage \times (33 \div 100)}
  •  {damage \times (333 \div 1000)}

の4つについて調べた。

第五世代以降

  • {damage = 23, recoil = 8} のとき
{\times (0\rm{x}548 \div 0\rm{x}1000)}  {\times (1 \div 3)}  {\times (33 \div 100)}  {\times (333 \div 1000)}
raw 7.591796875 7.66666666666667 7.59 7.659
四捨五入 8 8 8 8
五捨六入 7 8 7 8
切り捨て 7 7 7 7
切り上げ 8 8 8 8


- {damage = 53, recoil = 17} のとき

{\times (0\rm{x}548 \div 0\rm{x}1000)}  {\times (1 \div 3)}  {\times (33 \div 100)}  {\times (333 \div 1000)}
raw 17.494140625 17.6666666666667 17.49 17.649
四捨五入 17 18 17 18
五捨六入 17 18 17 18
切り捨て 17 17 17 17
切り上げ 18 18 18 18


- {damage = 153, recoil = 50} のとき

{\times (0\rm{x}548 \div 0\rm{x}1000)}  {\times (1 \div 3)}  {\times (33 \div 100)}  {\times (333 \div 1000)}
raw 50.501953125 51 50.49 50.949
四捨五入 51 51 50 51
五捨六入 50 51 50 51
切り捨て 50 51 50 50
切り上げ 51 51 51 51


{recoil = round(damage \times (33 \div 100))} のみ一致。

第四世代以前

  • {damage = 20, recoil = 6} のとき
{\times (0\rm{x}548 \div 0\rm{x}1000)}  {\times (1 \div 3)}  {\times (33 \div 100)}  {\times (333 \div 1000)}
raw 6.6015625 6.66666666666667 6.6 6.66
四捨五入 7 7 7 7
五捨六入 7 7 7 7
切り捨て 6 6 6 6
切り上げ 7 7 7 7


- {damage = 24, recoil = 8} のとき

{\times (0\rm{x}548 \div 0\rm{x}1000)}  {\times (1 \div 3)}  {\times (33 \div 100)}  {\times (333 \div 1000)}
raw 7.921875 8 7.92 7.992
四捨五入 8 8 8 8
五捨六入 8 8 8 8
切り捨て 7 8 7 7
切り上げ 8 8 8 8


{recoil = floor(damage \times (1 \div 3))} のみ一致。

例外(第三世代~第六世代共通)

  • {damage = 1, recoil = 1} のとき
{\times (0\rm{x}548 \div 0\rm{x}1000)}  {\times (1 \div 3)}  {\times (33 \div 100)}  {\times (333 \div 1000)}
raw 0.330078125 0.333333333333333 0.33 0.333
四捨五入 0 0 0 0
五捨六入 0 0 0 0
切り捨て 0 0 0 0
切り上げ 1 1 1 1


どの世代の計算式にも一致しなかった。

調査データ

調査に使ったデータを公開しておく。
調査結果が正しいかどうか確かめたい時にどうぞ。

参考

*1:第五世代は自販機乱数の人によって既に調査済であったが確認の意味も含めて再調査した

*2:調査済だが第五世代と同じ理由で再調査

ポケモンを一行で表現する構文「PokeSugar」を作った

趣味プロジェクトでポケモンを一行で表現する構文が必要になったので作った。
名前の由来はPokemonSyntactic sugarから。

更新履歴

v0.1.0

  • 構文をABNFで書いた。
  • オプション値で配列を使う際に各要素を区切る記号をスラッシュからパイプに変更した。

はじめに

GitHubで公開している仕様を読んで下さい。

github.com

構文を導入するメリット

様々な場所でポケモンに関する議論が展開されていく中で、ポケモン自体の表し方が多様化しており、場所によってポケモンの表現がまちまちになっている。PokeSugarではそれを定義化することで統一を図り、人や機械にとって扱いやすい「ポケモンを表現する構文」の提供を目指す。ポケモンを文字だけで表せるので、一行だけでリソースとしても利用出来る。

構文の例

ラティオス!臆病?浮遊@拘り眼鏡(流星群|サイコショック|波乗り|めざパ炎){C252|S252}[H31|A30|B31|C30|D31|S30]
ラティオス!臆病?浮遊@拘り眼鏡(流星群|サイコショック|波乗り|めざパ炎){C252S252}[3VacsU]
ラティオス!臆病@拘り眼鏡(流星群|サイコショック|波乗り|めざパ炎){CSぶっぱ}[めざパ炎理想]

ランドロス-霊獣 !意地っ張り ?威嚇 @スカーフ (地震|蜻蛉返り|はたき落とす|馬鹿力) {ASぶっぱ}
ヒードラン !冷静 @拘り眼鏡 (噴火|オバヒ|ラスターカノン|大地の力) {HCぶっぱ} <レベル:100|性別:♂>

何故この構文にしたのか

構文仕様についてはGitHubに載っているので、ここではこの仕様にした経緯について書く。

識別子による工夫

まずポケモンを表現する上で欠かせないのが種族, 性格, 特性, 持ち物, , 努力値, 個体値の7つの要素だろう。 これらの要素は!, ?などの記号と組み合わせることにより、機械が識別しやすいようにした。また、持ち物の識別子に@を利用して普段見慣れている構文に近づけたり、覚えやすいようにした。

括弧による工夫

, 努力値, 個体値は比較的文字数が多くなるので、括弧で括って可読性を高めた。
もし括弧で括らなかった場合、以下のように見辛くなる。

ラティオス!臆病?浮遊@拘り眼鏡$流星群|サイコショック|波乗り|めざパ炎#C252S252*3VacsU

オプションによる工夫

レベル性別など普段は使われない要素をオプションとして保持することで可読性を高めた。使わない要素に識別子を与えても利用者が覚える際に負担がかかるだけだ。

<レベル:100|性別:♂>
<リボン:'ゴージャスリボン|ロイヤルリボン|ゴージャスロイヤルリボン'|色:通常色>

自由度による工夫

人によってひらがな, カタカナ, 漢字, 英語, 略語など様々な文字で要素を記述するので、PokeSugarでもそれに対応した。

"対応した"というよりは寧ろ"決めていない"とするほうが正しい。仕様では要素に使用する文字に殆ど制約を設けていない。どの形式に対応するかは構文を利用するプログラムやソフトウェアが決める。これにより柔軟に情報を表現できる。

バンギラス
りゅうせいぐん
流星群
龍星群
竜星群
10万ボルト
十万ボルト
Aのすがた
\!のすがた
\?のすがた
CSぶっぱ
CSぶっぱ余りH
5VaU
3VacsU

種族ブロックは必ず先頭でなければならないが、他のブロックの順序に指定はない。仕様では可読性を重視してフォルム, 性格, 特性, 持ち物, , 努力値, 個体値, オプションの順で書いてある。また、種族ブロックを除いた他のブロックは省略可能なので以下のようにも書ける。

ラティオス!臆病?浮遊@拘り眼鏡(流星群|サイコショック|波乗り|めざパ炎){C252S252}[3VacsU]
ラティオス@拘り眼鏡?浮遊!臆病{C252S252}[3VacsU](流星群|サイコショック|波乗り|めざパ炎)
ラティオス[3VacsU]
ラティオス

種族ブロックを除く他のブロックの前であれば空白を挿入することが出来る。

ヒードラン !冷静 @拘り眼鏡 (噴火|オバヒ|ラスターカノン|大地の力) {HCぶっぱ} <レベル:100|性別:♂>

最後に

自分の趣味プロジェクトに使う構文ゆえに全く期待していないが、この構文が誰かの役に立つと嬉しい。
オプションは誰でも自由に拡張できるのでライセンスの下であれば、カスタマイズをするものアリだろう。

おわり。

2015年の振り返り

2015年の振り返りをする。本当は年が明ける前に投稿したかった

"今年"は2015年、"来年"は2016年のことを指す。

プログラミングを振り返る

  • 1月: メタ言語学習
  • 2~4月: JavaFXで乱数ツール製作
  • 5月: 非IDEエディタへの移行作業
  • 6~8月: Node.jsでフロントエンド開発
  • 9~11月: ES6学習
  • 12月: TypeScript学習

1月: メタ言語学習

Sass, Jade, TypeScriptなどのメタ言語について調べた。この学習では既存のWeb言語の問題点やそれを解決する手段、メタ言語を利用するメリットを知ることが出来た。調べたついでに記事も書いた。

slim - 小規模静的サイト開発のためのメタ言語 - Qiita

2~4月: JavaFXで乱数ツール製作

HTML以外での初のGUIアプリ作成だった。 最初に僕がJavaFXを使おうと思ったのは、FXMLと組み合わせることでHTML感覚でGUIアプリを作ることが出来ると思ったから。実際にはJavaFXを触る上で、クラスとメソッドを使ってコンポーネント操作をする際に、今までとは異なる知識が要求された。その知識を身につけるまでにかなりの時間を掛けてしまった。約三ヶ月。長かった。

ちなみにこの時期からQiitaやITニュースで技術系の記事を平日は毎日読むようになった。

5月: 非IDEエディタへの移行作業

以前までは開発環境としてIDE(NetBeans)を利用していたのだが、以下の理由から軽量な開発エディタに乗り換えたいと思うようになった。

  • 重い(起動が遅い, メモリの大量消費)
  • 使わない機能が多すぎてIDEを十分に活用出来ていない
  • 高機能ゆえにメニューが複雑
  • IDEに依存したプロジェクトになってしまう(例: NetBeansプロジェクトはnbprojectフォルダに依存している)*1

取り敢えずIDEではないエディタで当時話題になっていたものを調べた所、Atom, Brackets, Sublime Textあたりが候補に挙がった。 最終的には全て実際に使ってみて、快適そうだったBarcketsに乗り換えた。(Atomは重すぎ, Sublimeは初期設定が面倒だった)

当時はよく考えていなかったが、Node.js開発をするにあたりCLIを積極的に使うので、CLIと連携しやすい非IDEエディタを選んだのは正解だったと思う。

6~8月: Node.jsでフロントエンド開発

一年前に軽く触ってから放置していたNode.js開発を再開した。ただし一年前とは違い、サーバーサイドではなくフロントエンドの開発にNode.jsを利用した。はじめにgulp, webpackなどのビルドツールについて調べ、それからbabelの開発環境を作った。この辺りの情報は日本語のものが少なく、またすぐに古くなってしまうため、積極的に公式ドキュメントから情報収集した。僕は英語が苦手だったので読むのに苦労した。英語もっと勉強しなければ。

9~11月: ES6学習

夏に作成したbabel開発環境を使ってES6の学習を進めた。特に大規模開発に利用されるES6 Modulesを中心に勉強した。ES6学習をする中で、テストを導入してみたり、npmモジュールを作って公開してみたりと色々なことをやった。自分の作ったツールが公開されるということは、誰かに利用される可能性があるということで、他人に見られても恥ずかしくないコードを書くように心掛けた。

正直、この時点でオブジェクト指向プログラミングやソフトウェア設計について学んでおけば良かったと思う。来年はちゃんと勉強しよう。

12月: TypeScript学習

ここまでNode.js -> ES6と学習してきて、やっとTypeScriptの学習を始められた。本当はもっと早い段階でTypeScriptをやろうと思っていたのだが、CLIの操作に慣れていなかったので、先にES6学習をするという形を取った。(別にそのままTypeScriptやっても躓く要素なかったと思う)

この学習ではES6で書いたnpmモジュールをTypeScriptで書き換える作業をして、型付き言語に慣れることからはじめた。また、よりTypeScriptの機能を活かせるようにVSCodeにエディタを乗り換えて開発をした。下旬は年末で忙しかったため*2、あまり作業は出来なかった。残念。

以下は実際に作成したnpmモジュール。

GitHubを振り返る

f:id:mizdra:20160103192801p:plain

TypeScript学習を期に積極的にコミットするよう心掛けたが、全体的には殆どコミットしなかった。
開発欲はあるのに作りたいものが無い、という状態が半年くらい続いているので来年はそれを何とかしたい。

学業を振り返る

今年は大学入試を控えた受験生だった。夏休みまでは学校で勉強していたのだが、とある事情により*3、それ以降は自宅学習に切り替えた。今考えると家よりも学校のほうが勉強してたし、この選択は間違ってたと思う。今年一番後悔してる。

そんな後悔と受験への不安を抱えていたが、受かったらラッキーと思って出願した推薦入試に見事合格してしまった。
正直落ちたと思っていた。本当に良かった。

何はともあれ、自分の受験に関わった方々に感謝したい。
ありがとう先生。ありがとう家族。ありがとう大学。

今年読んだAdvent Calendar

興味をもった記事だけ読んだ。

全く読まなかったもの

一年を通して振り返る

記事とかドキュメントとか沢山読んだお陰で色々なことを学ぶことができた。また、受験を通して将来について考える時間を取れたのは非常に良かったと思う。今まで自分が何となく考えてた進路がより明確になったことで気分がスッキリした。

来年は引き続きjs、加えてGoやC++も勉強したい。入学予定の大学に詳しい人に話を聞いたところ、大学ではオブジェクト指向プログラミングやソフトウェア設計について殆どやらないそうなので、自分で勉強しようと思う。それと英語ちゃんとやろう。

おわり。

*1:単に自分のプロジェクト管理が下手なせいかもしれない。

*2:イカ楽しい。まだBの雑魚だけど。

*3:教室で騒いでる人たちがいて集中できなかった。辛い。

Node.js始める→TypeScript始める

はじめに

この記事では以下のことをやる。

  • Node.js環境構築
  • VSCodeでTypeScript環境構築

Node.js始める

Node.jsとは何か?

まず「Node.jsとは何か?」を理解する。 Node.jsは「サーバーサイドJavaScript」として有名だが、PHPなどのサーバーサイド言語とは仕組みが異なる。

また、サーバーサイド開発以外でも用いられることにも注意しなげればならない。
Node.js CLI(コマンドラインからの操作)でJavaScriptを実行出来る機能を活かして、クライアントサイド(いわゆるブラウザで表示される側, HTML)の開発にも使われている。

この時点ではクライアントサイド開発でどのようにNode.jsが使われているかイメージが湧かないだろうが、Node.jsと触れていく内に自然と分かるはずなので、深く考える必要はない。

Node.jsをインストールする。

Node.jsは更新が頻繁に行われているので、好きな時に簡単にバージョンアップ出来るよう、バージョン管理ツールを使ってインストールする。

WindowsMacで使うバージョン管理ツールが異なる。

Windows
- nodistによるNode.Jsのバージョン管理 | Anojin

Mac
- 初心者向け:nodebrewでNode.jsをバージョン管理し、環境を整える(MacOSX) | tipsBear

ちなみに記事投稿時点でのNode.js最新安定バージョンは5.2.0。
インストールが成功したかを確認するには以下のように打てば良い。

$ node -v
v5.2.0

プロジェクトを作成する

Node.jsプロジェクトを作成するにはまずpackage.jsonをプロジェクトルートに配置する。 package.jsonではプロジェクトの設定や、プロジェクトが依存するnpmパッケージなどを記述する。*1

ちなみにnpmは「Node.js向けパッケージマネージャー」のことである。
以下のnpm公式サイトを見れば分かる通り、様々なパッケージがnpmリポジトリで提供されている。

package.jsonnpm initコマンドで簡単に作成出来る。*2

$ mkdir node-sample
$ cd node-sample

# npmを更新する
$ sudo npm install npm -g

# package.jsonを作成
$ npm init
# 対話形式で色々聞かれるが、全てEnterで飛ばしてOK
...
node-sample
└ package.json

以下の記事を見ながら実際にnpmコマンドを使って、npmの動作を確認すると良い。

Node.jsでコードを実行する

より理解を深めるためにもNode.jsで簡単なモジュールを作成してみる。
作業は先程作成したプロジェクト内で行う。

今回は現在時刻を「2015-12-15 17:46:45」のフォーマットで出力するモジュールを作成する。
モジュールには、カスタマイズした時刻フォーマットを取得することの出来る「moment」を使用する。

$ npm install moment --save

npm installには--save, --save-devオプションなどが存在するが、ここでは解説しない。
よく分からなかったら--saveを付けておけば良いと思う。

プロジェクトルートに以下のファイルを作成する。

node-sample
├ index.js
└ package.json

nodeコマンドで実行。

# "."はカレントディレクトリを表す
$ node .
2015-12-15 17:46:45

Node.js環境構築は以上。

TypeScript始める

TypeScriptとは何か?

JavaScriptに型を追加したAltJS。
加えてJavaScript次期仕様であるECMAScript 2015(ES6)もサポートしている。

class Student {
    fullname : string;
    constructor(public firstname, public middleinitial, public lastname) {
        this.fullname = firstname + " " + middleinitial + " " + lastname;
    }
}

interface Person {
    firstname: string;
    lastname: string;
}

function greeter(person : Person) {
    return "Hello, " + person.firstname + " " + person.lastname;
}

var user = new Student("Jane", "M.", "User");

document.body.innerHTML = greeter(user);

こんな感じで書ける。つよい。

必要なnpmパッケージをインストールする

TypeScript→JavaScriptトランスコンパイルには、npmパッケージ「typescript」を使う。

# v1.7.*を指定してインストール
$ npm install typescript@1.7 -g

# インストール出来たか確認
$ tsc -v
message TS6029: Version 1.7.3

TypeScriptをコンパイルする

今回はサンプルとして型とES6 Moduleを使ったプログラムを書いた。
先程と同様に、プロジェクトフォルダ「ts-sample」を作成し、npm initを済ませておく。

以下のファイルを作成する。

ts-sample
├ src
│ ├ helloModule.ts
│ └ index.ts
│
├ package.json
└ tsconfig.json

加えて、package.jsonmainプロパティの値を./lib/index.jsに書き換える。

実際にコンパイルしてみる。
コンパイルにはtscコマンドを使う。*3

$ tsc -p .

.コンパイルする際に基準とするディレクトリを表す。(今回はプロジェクトルートを指す)
-pオプションを指定するとtsconfig.jsonの内容を元にコンパイルが実行される。
コンパイル後、以下のようにlibフォルダが追加される。

ts-sample
├ lib
│ ├ helloModule.js
│ └ index.js
│
├ src
│ ├ helloModule.ts
│ └ index.ts
│
├ package.json
└ tsconfig.json

出力されたファイルを実行するには以下を叩く。

$ node .
Hello TypeScript!
ES6

この時、nodeコマンドは指定されたディレクトリのpackage.jsonmainの値を参照し、その値が表すファイルを実行している。(今回は./lib/index.js)

VSCodeを使って開発する

Microsoft製の開発エディタ「Visual Studio Code」(以下VSCode)を使ってTypeScript開発をする。 VSCodeを使うことで以下のようなメリットを享受出来る。

  • 文法を解析し、シンタックスハイライト表示してくれる
  • 型情報をエディタが理解して、型情報の表示や補完、リファクタリングなどを行ってくれる
  • package.jsontsconfig.jsonなどの設定ファイルを理解してくれる
  • Windows, Mac, Linuxに対応しているのでどのOSからも同じ操作で作業出来る
  • 同じElectron(HTML+JS+CSSベースのGUIプラットフォーム)で作られているAtomやBracketsよりも軽い

インストール方法や動作の確認は以下のサイトを読んで行うと良い。

VSCodeでtscと連携する

VSCodeではtscコマンドをタスクとして登録し、それにキーショートカットを割り当てて簡単に実行出来る。

まずはタスクの登録を行う。 作成済みの「ts-sample」プロジェクトをVSCodeで開き、以下の手順でタスクを作成・登録する。

  • F1キーでコマンドパレットを開く
  • configure task runnerと入力し、Enterでtasks.jsonを作成
  • tasks.jsonargsプロパティの値を["-p", "."]に書き換える

これでタスクの登録が完了した。
タスクはCtrl+Shift+B, ↑⌘Bで実行出来る。
これはtsc -p .と等価である。

コンパイルエラーなどはCtrl+Shit+U, ↑⌘Uでアウトプット画面を開いて確認出来る。

最後に

今回は純粋にtscでTypeScriptをビルドすることだけに焦点を置いたが、他にもビルドツールやその他のnpmモジュールを組み合わせることで、より凝ったビルドをすることが出来る。
Qiitaやはてなブログでその類の記事は沢山書かれているので、興味のある方は調べてみると良いかもしれない。

おわり。

*1:この記事ではnpmパッケージの意味については触れない

*2:npmコマンドはNode.jsと一緒にインストールされている。

*3:tscコマンドはtypescriptと一緒にインストールされる