OCaml プログラムをコンパイルする
インストールとか環境構築については今度書くとして、今日はコンパイルについて。
バイトコードとネイティブコード
OCaml をインストールすると標準で 2 種類のコンパイラがついてくる。
バイトコード
- コンパイルしたプログラムは機種(ハードウェア・OS)に非依存
- Linux でコンパイルしたものを Windows で実行したり、異なる環境でも実行可能
- 実行にはバイトコードインタプリタ
ocamlrun
が必要(これも標準でついてくる)
ネイティブコード
- コンパイルしたプログラムは機種(ハードウェア・OS)に依存する
- コンパイルした環境と異なる環境では動かない場合がある
- インタプリタは不要でハードウェアから直接実行できる
- ネイティブコードの方が実行速度は速い
コンパイルしてみる
サンプルとして階乗を求める関数 fact
と、
(* fact.ml *) let rec fact n = if n = 0 then 1 else n * fact (n - 1)
それに引数 10 を渡して実行した結果を表示するプログラムを書く。
(* main.ml *) open Fact let () = print_int (fact 10); print_newline()
ocamlc でコンパイル
コンパイルして実行ファイルを作成するには以下のように入力する。-o
オプションで実行ファイルの名前を指定する。
$ ocamlc -o fact10 fact.ml main.ml
コンパイルすると実行ファイル fact10
と fact.cmi
, fact.cmo
, main.cmi
, main.cmo
というファイルが生成され、fact10
を実行すると結果が表示される。
$ ./fact10
3628800
しかし、ocamlc
に渡す順番を逆にするとエラーになる。
$ ocamlc -o fact10 main.ml fact.ml File "main.ml", line 1, characters 5-9: Error: Unbound module Fact
これは main.ml
の中で fact.ml
で定義されている関数 fact
を参照している、つまり main.ml
は fact.ml
に依存しているからである。
ocamlopt でコンパイル
ocamlc
と同様に -o
で出力するファイル名を指定する。
$ ocamlopt -o fact10 fact.ml main.ml
実行ファイルの他に生成されるファイルが ocamlc
の場合とは一部異なった。
ocamlc
では fact.ml
から fact.cmi
, fact.cmo
が生成されたのに対して、fact.cmi
は同じで、fact.cmo
の代わりに fact.cmx
と fact.o
が生成されていた。
この *.cmi
, *.cmo
, *.cmx
, *.o
とやらは何だろうか。こういう普段見慣れないファイル形式が一度に複数出てくると、ウッてなるんだよね。落ち着いてマニュアルを見てみる。
.cmi
とは
- インターフェイスをコンパイルしたもの
*.mli
をコンパイルすると*.cmi
が出力される*.mli
が無い場合は*.ml
から*.cmi
が生成される
ocamlc
でコンパイルした*.cmi
とocamlopt
でコンパイルした*.cmi
は同一
.cmo
とは
.o
とは
.cmx
とは
参照
- OCamlプログラムをコンパイルする – OCaml
- Batch compilation (ocamlc)
- Native-code compilation (ocamlopt)
- 書籍『プログラミング in OCaml』
プログラミング in OCaml 〜関数型プログラミングの基礎からGUI構築まで〜
- 作者: 五十嵐淳
- 出版社/メーカー: 技術評論社
- 発売日: 2014/12/09
- メディア: Kindle版
- この商品を含むブログ (12件) を見る
ネイティブコードにコンパイルされたコンパイラ
上述の ocamlc
と ocamlopt
はバイトコードでコンパイルされたコンパイラのようで、ネイティブコードでコンパイルされたものもあり、通常はこちらを使うらしい。
ocamlc.opt
ocamlopt.opt
ネイティブコード にコンパイルされた バイトコード および ネイティブコード コンパイラ。 ネイティブコード コンパイルが可能な環境では通常このコンパイラを使う。
OCaml コンパイラソースで make opt の後に make opt.opt を行うと作成される。 通常の ocamlc, ocamlopt は バイトコード で実行されるが、 *.opt コンパイラはネイティブコードに コンパイルされているため ocamlc, ocamlopt よりコンパイル速度が早い。 (バイトコード版コンパイラがひどく遅いわけではないが。)
ocamlc, ocamlopt 以外の OCaml のツールにも、.opt の suffix がついた ネイティブコードバージョンが存在するのでそちらを使ったほうがよい。
OCaml に再入門( 3 年ぶり 2 回目)
最近、OCaml に再度入門しようとしている。前に触ってみたのは 3 年前くらいだろうか。書籍『プログラミングの基礎』を読み進めながら一部を自分でも書いて動かして、という感じで途中までやっていた。
最後までやらずにやめてしまったのは何故だったか、あまり覚えていないけれど
- より優先順位の高いプロジェクトがあり、そちらに取り組むことにしたから
- OCaml は Python や JavaScript などと比べると日本語の情報が少なく、敷居が高く感じたから
- Emacs の中で対話環境を動かして、バッファの内容を即実行させることができたのだが、実行結果が少しずれて表示されてしまい、その直し方がわからず、何だか気持ちが悪いなという思いがつきまとっていたから
という感じだった気がする。まぁ結局のところ、必要に迫られていたわけでもないから、ということだろう。
その後、Go を少し勉強した。仕事で使う小さなツールを 2, 3 個書いて、それらは毎日のように使っているので Go は手を出してよかったと思う。仕事で使うツールを書くなら Go で書くのがよさそうだと思うが、今は仕事で使うツールを書くために週末の自分の時間を使いたいとは思わなくなったので、Go 自体の勉強もストップしている。
しばらく触らないと忘れて、忘れるとまた調べ直すために時間がかかることが億劫に感じられて触らなくなる、という疎遠ループ。
で、しばらくプログラミングとは関係ないことに取り組んでいてそちらはそちらで引き続きやっているのだけど、気分転換も兼ねてまたプログラミングに関する何かを勉強しようかなと思っていた。
そしたら、たまたま読んだ以下の記事で『プログラミング in OCaml』が紹介されていたので OCaml を再び触り始めた次第。
この本は、OCaml を使うつもりがとくにない人でも、独力でプログラミングを学んできたような人であれば、読むといいことがたくさん書いてあると思っています。 具体的には、OCaml というプログラミング言語でのプログラムの書き方だけでなく、どうしてそういう機構になっているのかがいちいち詳しく解説されており、プログラミング言語の理論についても味見できるようになっています。
やはり強静的型付けで、コンパイラがしっかりチェックしてくれる言語の方が、堅牢なプログラムを書きやすいのではないかと思っている。プロじゃないからこそ、言語の機能に頼りたいというか。
学習コストもかかるだろうが、期限がある話ではないので今後の人生を考えると長期的には十分回収できるはず。
というわけで、ゆっくり少しずつでも積み上げていけたらと思うので、調べたことをここにも書いていこうかなと。
千葉で温泉
先週の話。
- 木曜にクロサワから連絡をもらって飯田橋で軽く飲んだ。
- 家族が帰省中で暇してるということで週末にどこかに行こうということになった。
- 金曜にいろいろ調べて千葉にある温泉施設、いわゆるスーパー銭湯的なところに行くことにした。
- クロサワが車を出してくれて、まさかの朝 9 時集合で千葉までドライブ
岩盤浴が最高
- 岩盤浴がとても気持ちよかった。
- サウナと違って湿度が高いのであまり辛くなく、じわ〜っと汗をかく感じ。
- フロントで専用のウェアを受け取って、それに着替えて岩盤の上に大判のバスタオルを敷いて寝そべる。
- しばらくすると全身から汗が出てくるのでほどほどのところで一旦退室し、隣りにある涼むための部屋(エアコンががっつり効いている)に入る。
- そして水分補給してまた岩盤の上に戻る、という感じ。
- 以前 YZ に連れて行ってもらった板橋にあるさやの湯処もよかったな、そういえば。
- 板橋なら岩盤浴のためだけに、月 1 回くらいのペースで通ってもいいかもしれない。
全般的に最高だった
- 気の置けない友人と他愛もない話をしながらゆっくり風呂につかったり、岩盤浴で寝そべったり、ジンギスカンを食べたりして過ごすのはとても楽しかった。
- 行き帰りの運転もぜんぶおまかせだったのでただ乗ってるだけという気楽さ。
- いろいろ話が聞けて面白かった。
- 大企業には大企業の悩みというか、いろいろとアレなところもあるのだなぁと思ったり。
東京に戻って
- 最後は車を置いてから木場のもつ焼き屋さんで軽く飲んで解散。
- クロサワはもともとあまりたくさん食べる感じではなかったけれど二人とも食べる量が減った気がする。
- 少量で少しずつ食べたら満足してしまう。
- でも活気があってよいお店だった。
今日はクロサワ @ku6sa8 と朝からドライブ→温泉→(岩盤浴→涼み)× n 回繰り返し→ジンギスカン→ソフトクリーム→温泉→岩盤浴→温泉→成田山新勝寺→ソフトクリーム→ドライブ→クロサワ邸(車を置いて)→もつ焼き屋さん、という近年まれに見る充実した一日だった
— ryskosn (@ryskosn) 2017年8月12日
log を残していこう
- しばらくご無沙汰してたなーと思ってはいたけれど 1 月から書いてなかったのか、と少しびっくりした。
- 何かしらちょいちょい書いていくと自分でも生活を振り返ることができて有益だし、家族にもこちらの様子が伝わるし、よいのではないか。
- あと、ずっと文章を書かないでいると、そのうち書けなくなりそうな気もする。
- 東京は少し暑くなってきたけれど引き続きがんばろう。
JavaScript, Node.js を始める
JavaScript 熱の高まりというか、やっぱり使えたらいろいろ便利そうだな*1と思い、昨年末あたりから少しずつ調べたりまとめたりしていたので、こちらにも書いておこう。
Node.js をインストール
公式サイトからインストールしてもいいけれど、入れ直したりバージョンを上げたりをやりやすくするためツール経由で入れるほうがよさそうなので nodebrew を使う。
curl
でインストール。
$ curl -L git.io/nodebrew | perl - setup
PATH を通しておく。
$ export PATH=$HOME/.nodebrew/current/bin:$PATH
nodebrew 使い方
バイナリを入れるやり方でいいと思う。
# すでにインストールしていた場合 $ nodebrew selfupdate # インストール可能なバージョンを列挙する $ nodebrew ls-remote # バイナリを入れる場合 $ nodebrew install-binary <version> # ソースからコンパイルする場合 $ nodebrew install <version>
とりあえず stable
を指定したら v7.2.1
が入った。
# <version> の代わりに stable や latest という指定が可能 $ nodebrew install-binary stable # インストール済のバージョンを表示 $ nodebrew ls # 使用するバージョンを指定 $ nodebrew use stable # アンインストールする場合 $ nodebrew uninstall <version>
パッケージマネージャ npm について
Node.js をインストールすると npm コマンドが使えるようになる。パッケージマネージャと書いたけれど、備えている機能はもう少し幅広いようだ。
Node.js で開発する、プロジェクトを作るには以下のコマンドから始める。
$ npm init
プロジェクト名とか作者名とかいろいろ質問されるのでそれに答えていくとそれらの情報を含んだ package.json
が作成される。
npm init
の際にオプション --yes
をつけると全てデフォルトで進めてくれる。
package.json
にはインストールしたパッケージの情報を記載しておけば、そのプロダクトを別な環境でインストールする際に npm install
とするだけで依存するパッケージをインストールしてくれる。
link
- init | npm Documentation
- package.json | npm Documentation
- 2016年版 Node.jsで幸せになれる10の習慣 - Qiita
- package.json のチルダ(~) とキャレット(^) - Qiita
npm でパッケージをインストール
npm install <package_name>
でインストールする。
オプション --save
or --save-dev
をつけるとインストールと同時に package.json
にも記載される。
--save
は実行時に必要なパッケージとして "dependencies:"
に記載される。
--save-dev
は開発時に必要なパッケージとして "devDependencies:"
に記載される。
$ npm install <package_name> --save $ npm install <package_name> --save-dev
オプション
npm i
はnpm install
と等価-D
は--save-dev
と等価-S
は--save
と等価-g
は--global
と等価
以下のようにも書ける
$ npm i -D <package_name>
link
インストールしたパッケージを確認する
# ローカルのパッケージを確認 $ npm list # or ls # グローバルのパッケージを確認 $ npm list --global # or -g
ただ、上記のコマンドだと大量のパッケージが表示されるので以下のようにオプションを指定するのがよい。
$ npm list --depth=0
パッケージのインストール先
ローカルにインストールするとプロジェクトディレクトリ内の node_modules/
に入る。
グローバルにインストールすると <prefix>/lib/node_modules/
に入る。
<prefix>
を確認するコマンドは以下の通り。
$ npm config get prefix
ローカルにインストールしたパッケージを使うために PATH を通す。
$ export PATH=$(npm bin):$PATH
その他
インストールしたパッケージのアップデート
この記事が参考になりそう。まだ必要に迫られていないので試したりしていない。
インストールするパッケージのバージョンを指定
package.json
にはそのパッケージのバージョン番号も指定される。書式については以下の記事が参考になる。
ローカルのパッケージを Git の管理対象から除外
.gitignore
に node_modules/
と書いておこう。
*1:GoogleAppsScript とか Electron とかを用いて生活および仕事のタスクを処理する便利な何かを作れるのではないか的な
fish を導入
(last update: 2017/02/21)
少し気になっていたモダンなシェル fish 、実家の兄も使っていていろいろ見せてもらったらやっぱり便利そうだったので導入してみた。
MacPorts でインストール。Homebrew 派の人は $ brew install fish
で。
$ sudo port install fish
$ fish_config # ブラウザで設定画面が開く
fish をデフォルトのシェルに設定する。まず fish がインストールされているパスを確認して、 /etc/shells
を編集する。その上で、 chsh
コマンドで切り替えれば OK。
$ which fish # -> /opt/local/bin/fish $ sudo emacs /etc/shells # 上記 fish のパスを追加 $ chsh -s /opt/local/bin/fish
プラグインのインストール
oh-my-fish のメンテナの方が作っているというプラグインマネージャ fisherman をインストール。
$ curl -Lo ~/.config/fish/functions/fisher.fish --create-dirs git.io/fisherman
peco 関連のプラグインをインストール。 peco 自体は以前に go get でインストールしていた。
$ fisher omf/plugin-peco $ fisher yoshiori/fish-peco_select_ghq_repository
fish-peco_select_ghq_repository
は ghq で管理しているレポジトリを peco で検索して cd
する拡張。
C-r
でのヒストリ検索に peco を使うように、ghq のやつは C-o
にそれぞれ設定しておく。
function fish_user_key_bindings bind \cr peco_select_history bind \co peco_select_ghq_repository end
参考
- fishシェル普及計画
- 日本語 · fisherman/fisherman Wiki
- 詳解 fishでモダンなシェル環境の構築(fish,tmux,powerline,peco,z,ghq,dracula) - Qiita
- zsh から fish にした。 - yoshiori.github.io
fish-mode をインストール
Emacs で fish スクリプト(設定)を編集するための fish-mode をインストールする。
~/.emacs.d/Cask
に (depends-on "fish-mode")
を追加して以下のように実行すれば OK.
$ cd ~/.emacs.d/
$ cask install
設定ファイルは zsh や bash とはことなり .fishrc
ではなく ~/.config/fish/config.fish
となる。
PATH の設定
.zshrc とは構文が異なる。以下のような感じ。
# PATH set -x PATH /opt/local/bin /opt/local/sbin $PATH set -x PATH $HOME/bin $HOME/.cask/bin $HOME/py35/bin $PATH # Go set -x GOROOT (go env GOROOT) set -x GOPATH $HOME/go set -x PATH $GOPATH/bin $GOROOT/bin $PATH # nodebrew set -x PATH $HOME/.nodebrew/current/bin $PATH
alias の設定など
alias は zsh と同じ書式でもいけるという話もあったかもしれない。
# alias alias rm "rm -i" alias cp "cp -i" alias mv "mv -i" alias mkdir "mkdir -p" alias find "gfind" alias xargs "gxargs" # alias for git alias gst "git status" alias gdif "git diff" alias gdifc "git diff --cached" # alias for Mac alias ql "qlmanage -p $argv[1]" # user defined functions function cd builtin cd $argv ls -a end function fish_user_key_bindings bind \cr peco_select_history end
補完候補の拡充
以下のコマンドで man
などから補完候補を追加してくれるそうな。頼もしい話である。
$ fish_update_completions
現時点の config.fish
Good Bye, 2016
年末年始ということで実家に帰省している。毎年同じことを書いていると思うが、 2016 年もあっという間に過ぎていったように感じている。
学生時代に家庭教師のアルバイトで関わった生徒さんから年賀状をもらって嬉しかったのが 2016 年の 1 月で、そこからいろいろやっていたらもう 12 月。はー、速い。 結局その生徒さんには年賀状は返信して「今度食事でも」と伝えたのだけれど、結局連絡先がわからなくて連絡しないままになっていた。 12 月に入ってから手紙を書いたけれど、「もう知らね」と言われてもまぁ仕方ない。もうちょっと早めにアクションすべきだったな。
速い?早い?
関係ないけれど「時間が経つのがはやい」というときに「早い」か「速い」のどちらなのか、いつも迷う。時間が過ぎていくスピードのことを言うのだから「速い」ではないかと思っていたが、必ずしもそう考える人だけではないようだ。
- 『早い』と『速い』ですが、時間が経つのがはや... - 日本語 | Yahoo! 知恵袋
時間に関する言葉を扱っているので混乱しますが、時間は「九時君が速く移動したから十時君になった」のではなく、「 (自分の感覚よりも) 早く十時君がやってきた」と考えればどうでしょう。
この説明で納得しかけたけれども、時間の進むスピードが変化したわけではないということは十分承知の上で、「はやい、と感じる」ということを言っているのでやはり「速い」で間違ってはいないような気もする。
振り返り
- 昨年から取り組み始めたとあることは細々と続けられている。まだ実を結んではいないが、いずれよい結果に繋げられると思う。
軽い運動(腕立て伏せとスクワットなど)をする習慣もだいぶ定着してきた。
英語の勉強はあまり進んでいなかった。最後に受けた TOEIC で 820 点くらい取れて嬉しかったのだけれど、確認したら 2014 年の話だった。寝る前に DUO 3.0 を開いて例文をシャドウイングすることを毎日の習慣にしたい。
Python はあまり書かなかったのでだいぶ忘れてしまった。
- 夏頃に支出管理シートを作るため GoogleAppsScript (JavaScript) を(自分にしては)たくさん書いた。 TypeScript を使ってみたいと思いつつ環境構築の段階で躓いている。
Go を使ってみようと思ったのはいつからだったっけ。夏の前くらいかな?「スターティング Go 言語」を枕元に置いてちょいちょい読んだり、 A Tour of Go や Go by Example を写経してみたりしたけれど、ちゃんと書くことなく時間が過ぎていった。 12 月下旬に仕事で使えそうなツールを思いつき、 Go で書いてみた。 100 行くらい。今後はもっと使えるようになりたい。
blog を全然書かなくなった。 Markdown で書けるようにとはてなダイアリーからはてなブログへ移行したのだけれど、あまり書かないままだった。
- これからはもっと気軽に駄文を書き散らかしていきたい。何か書いていないと、文章を書く力が落ちると実感し始めた。他の人はどうか知らないが、少なくとも自分に限ってはそのように感じている。
そういや、 Markdown で改行のために行末にスペースを 2 つ入れる仕様って結構一般的な話なの?兄と話していて聞いたんだけど全然知らなかった。 Emacs で保存時に行末のスペースを削除する設定にしているので、全然使えないというか、相容れない感じがする。
;; 保存時に行末のスペースを削除 (add-hook 'before-save-hook 'delete-trailing-whitespace)
- 作者: 松尾愛賀
- 出版社/メーカー: 翔泳社
- 発売日: 2016/05/11
- メディア: Kindle版
- この商品を含むブログを見る
161128 近況
本当にあっという間に 1 日が終わり、1 週間が過ぎて、気づけばもう 11 月末。いやー、速いね。
2016 年のうちにもう少し進歩しているつもりだったような気がするのだけれども、何を言ってもカレンダーは後ろには戻らないので今日から残り 1 ヶ月ちょっとをしっかり過ごしていきたい。
食生活の乱れ
寒くなってくると食事の選択に影響が出る。朝起きた直後に冷蔵庫から出したばかりの冷たいヨーグルトをガツガツ食べる気になるかと言われるとならないし、フルーツグラノーラとかミューズリーとかのシリアル系も同じく冷蔵庫から出したばかりの冷たい豆乳とか牛乳とかをかけることになり、それらを食べられるときと食べるきになれないときがある。
まぁ、パンとかを常備しておいてトーストするなりして温かいものとセットにすればいいのかもしれないけれど。
Golang
結局全然書いていない。会社で使っている Python の小さなスクリプトなどを置き換えていくところからやっていこうかなと思っていたはずなのだけれど、着手できていない。その置き換えはこのままやらない気もする。
ただ Go 自体への興味関心は相変わらずあるので、少しずつ勉強を進めていくと思う。10 月くらいには Go by Example を写経したりしていたのでまたその辺からやっていこうかな。自分で書かないとすぐ忘れる。
支出管理シート
Google Apps Script で書いているやつ。もう少し入力の手間を減らす仕組みを作りたい。カード払いの明細 CSV データを貼り付けて既存の入力データとの差分というか、入力漏れを教えてくれるようなものがあったらいいなと漠然と考えているところ。
アマチュアだからこそ、素の JavaScript を書くのではなく TypeScript とか静的型付けの言語を使ったほうがよりよいものを作れるようになるのではないだろうかということを最近考えたりする。Go に興味を持ち始めたのもそういう動機が根底にあったのかもしれない。
GAS を TypeScript で開発するやり方もあるようなのだけれど、如何せん色々と環境を整える必要がありそうで少々敷居が高いと感じており、まだ踏み出せないでいる。というか時間を捻出できていない。
結局、何をするにしても必要なのは時間と集中力と体力なんだよな。
バール
先日の福島沖あたりでの地震はけっこう長い時間揺れていたので少し怖かった。 地震が起きて、ドアがぶっ壊れて外に出られなくなるかもしれないので、バールを買った。軍手よりも丈夫らしいので革手袋も。
- 出版社/メーカー: バクマ
- メディア: Tools & Hardware
- この商品を含むブログを見る
- 出版社/メーカー: 大中産業?
- メディア:
- この商品を含むブログを見る
concurrent and parallel
すぐ忘れるのでメモ
concurrent 並行
複数の動作が順不同もしくは同時に動作する
concurrent の意味 - 英和辞典 Weblio 辞書
parallel 並列
複数の動作が物理的な時間として同時に動く 物理的に複数のコアなどが必要