2016年1月30日土曜日

[Emacs] org-modeで新しいメモを追加するElisp

ここ数年、Emacsでメモをとるのに、Change Logモードを使ってきた。
メモを書きたいときに、C-x 4 a (add-change-log-entry-other-window) で 、簡単に、新しいエントリをメモの最初に追加できるので便利だった。
最近、orgモードでメモをとり始めたのだけど、長年使ってきた 新エントリの追加ができず不便だったので、作ってみた。

(global-set-key (kbd "C-x 5 a") 'insert-memo-new-headline)

(defvar *memo-file* "~/org/memo.org")

(defun insert-memo-new-headline ()
  (interactive)
  (let ((memo-buffer (find-file-noselect *memo-file*)))
    (unless (eq (current-buffer) memo-buffer)
      (when (one-window-p t)
 (split-window))
      (other-window 1)
      (switch-to-buffer memo-buffer)))
  (goto-char 0)
  (insert "\n\n")
  (goto-char 0)
  (insert "* ")
  (org-insert-time-stamp nil)
  (insert " "))

C-x 5 a で *memo-file*で指定したファイルの最初に移動し、 図のような形式で、新しいメモを追加できるようになる。



久し振りにElispのコードを書いたけど、いろいろ忘れてしまっていた...
こういうときは、るびきちさんのEmacs Lispテクニックバイブルがとても便利。

2015年11月1日日曜日

[R][FX] Debian Jessie で Rのパッケージをインストールできないときの対処法

MetaTraderで自動売買しようと思い、日々、EA(Expert Advisor)を書いていたら、すっかりブログの更新が滞ってしまった。
為替で有効な手法を見つけるのは、なかなか難しい。

EAでいちいちシミュレーションするのは面倒だし、為替データの解析に、Rを使えると便利そうだなと思い、みんなのRを読みながら、例を入力しつつ、Rをいじりはじめた。

この書籍ではR Studioを推奨していたので、 Debian Jessie 標準のR Studioを使っている。

書籍に書いてあった株価データを扱うためのパッケージquantmodをインストールしようとしたら、 エラーになった。

> install.packages("quantmod")
Installing package into ‘/home/satoshi/R/x86_64-pc-linux-gnu-library/3.1’
(as ‘lib’ is unspecified)
Warning in install.packages :
  package ‘quantmod’ is not available (for R version 3.1.1)

CRANにはquantmodはあるようなのだけど、インストールできない。
StackOverflowを見て解決。

 インストールしたままでは、CRANのパッケージが全然見えていないようだ。

> setRepositories()
 --- このセッションで使うリポジトリーを選んでください --- 

1: + CRAN
2:   BioC software
3:   BioC annotation
4:   BioC experiment
5:   BioC extra
6:   CRAN (extras)
7:   Omegahat
8:   R-Forge
9:   rforge.net

 スペースで区切られた 1 つ以上の数を入力するか、キャンセルするには空白行を入力してください 
1: 1 ◆CRANが選択されているが、再度選択してみた。
> ap <- available.packages=""> View(ap) ◆パッケージを表示する。
パッケージが全く表示されない。 以下のコマンドでミラーを選択できる。
> chooseCRANmirror()
CRAN mirror 

  1: 0-Cloud [https]                 2: 0-Cloud                     
  3: Algeria                         4: Argentina (La Plata)        
--略--
 55: Italy (Palermo)                56: Japan (Tokyo)               
 57: Japan (Yamagata)               58: Korea (Seoul 1)             
--略--

Selection: 56 ◆日本のミラーを選択
> ap <- available.packages()
> View(ap) ◆パッケージを表示できた。
> 
> install.packages("quantmod") ◆quantmodをインストール
--略--
* installing *source* package ‘zoo’ ...
--略--
* installing *source* package ‘xts’ ...
--略--
* installing *source* package ‘TTR’ ...
--略--
* installing *source* package ‘quantmod’ ...
--略--
* DONE (quantmod)

The downloaded source packages are in
 ‘/tmp/Rtmp6M7HGP/downloaded_packages’
>
依存パッケージも一緒にインストールできた。 xtsパッケージは時系列データtsを拡張したクラスxtsを提供し、 不規則な間隔を扱うことができるので、 為替や株価データを扱うには最適のようだ。

参考

みんなのR
いくつかRの本を買ってみたが、この本が一番分かりやすかった。
グラフ描画ggplot2の説明も分かりやすいし、実例も多数あるのでおすすめ。

2015年6月23日火曜日

[コンピュータ開発][コンピュータシステムの理論と実践] OCamlでHack assemblerを実装(3)

Nand2tetris Software Suite に含まれている昔懐しピンポンゲーム(Pong.asm)を作成したアセンブラでアセンブルしてみた。

Pong.asmはおおよそ28,000ステップあるが、問題無くアセンブルでき、CPU Emulatorで動作した。


次は、Virtual Machineを実装する予定。楽しいねー。

2015年6月21日日曜日

[コンピュータ開発][コンピュータシステムの理論と実践] OCamlでHack assemblerを実装(2)

前回からずいぶん間隔が空いたが、Hackアセンブラを拡張し、変数とジャンプ先にシンボルを利用できるようにした。

コードはこちら。
https://github.com/takeisa/ocaml-hack-assembler

サンプルコード Test.asm
1から100まで加算し、シンボルiで示すアドレスに計算結果を格納するプログラム。
// sum from 1 to 100
        @i
        M=1     // i=1
        @sum
        M=0     // sum=0
        
(LOOP) // comment(space)
        @i
        D=M     // D=i
        @100
        D=D-A   // D=i-100
        @END
        D;JGT   // if (i-100) > 0 then jump END
        @i
        D=M     // D=i
        @sum
        M=D+M   // sum=sum+i
        @i
        M=M+1   // i=i+1
        @LOOP
        0;JMP
(END)
        @END
        0;JMP

シンボルテーブルを出力するようにしたので、実行すると以下のようになる。
satoshi@jessie: ./assembler Test.asm
=== Symbol table ===
        SP 0000
       LCL 0001
       ARG 0002
      THIS 0003
      THAT 0004
       R00 0000
       R01 0001
       R02 0002
       R03 0003
       R04 0004
       R05 0005
       R06 0006
       R07 0007
       R08 0008
       R09 0009
       R10 000a
       R11 000b
       R12 000c
       R13 000d
       R14 000e
       R15 000f
    SCREEN 4000
       KBD 6000
         i 0010
       sum 0011
      LOOP 0004
       END 0013

2015年5月17日日曜日

[Docker][Debian]JessieにDockerをインストール

Dockerのインストールの解説には、Debian Jessieへインストールする手順が書かれているが、2015/5/17現在、backportsには存在せず、apt-getでインストールするには、sidからインストールしないとできないようだ。

sidは使いたくなかったので、いろいろ調べてみると、
http://linuxconfig.org/package-docker-io-has-no-installation-candidate-debian-jessie
の手順が一番簡単そうだった。

インストール手順

curlが必要なので、あらかじめ入れておく。
# apt-get install curl

Dockerをインストールする。
# curl -sSL https://get.docker.com/ | sh

試す。
# docker run -i -t ubuntu /bin/bash

root以外のユーザでdockerコマンドを使いたい場合は、dockerグループを追加する。
$ sudo usermod -aG docker your-user

注意点

Debianの場合、
docker - KDE3/GNOME2 docklet アプリケーション用システムトレイ
というパッケージがあり、これをインストールすると、dockerコマンドが衝突してしまうかもしれない。
Dockerを動かすVMはX Windowを使わないので、気にしないことにした。

その他

最近、Dockerを使い始めたのだけど、コンテナの起動は早く、いろいろなコンテナを手軽に起動してサービスを動かすことができるのは、非常に便利で、使っていて面白い。


2015年5月3日日曜日

[コンピュータ開発][コンピュータシステムの理論と実践]OCamlでHack assemblerを実装

「コンピュータシステムの理論と実装」
第6章 アセンブラ まで進んだ。

第一段階のシンボルフリーなHackアセンブラをOCamlで実装した。
https://github.com/takeisa/ocaml-hack-assembler

  • 依存ライブラリはCoreとRe2。
  • コマンドラインの解析は、Coreのライブラリを使用。ここを参考に実装した。

実行例

デバッグ用出力がいろいろ出ているが、Add.asmをアセンブルして、Add.hackを出力している。

$ ./assembler Add.asm && echo "----" && cat Add.hack 
ignore :   1 43 [// This file is part of www.nand2tetris.org]
ignore :   2 51 [// and the book "The Elements of Computing Systems"]
ignore :   3 36 [// by Nisan and Schocken, MIT Press.]
ignore :   4 37 [// File name: projects/06/add/Add.asm]
ignore :   5  0 []
ignore :   6 22 [// Computes R0 = 2 + 3]
ignore :   7  0 []
command:   8  2 [@2]
command:   9  3 [D=A]
dest=2 comp=48 jump=0
command:  10  2 [@3]
command:  11  5 [D=D+A]
dest=2 comp=2 jump=0
command:  12  2 [@0]
command:  13  3 [M=D]
dest=1 comp=12 jump=0
----
0000000000000010
1110110000010000
0000000000000011
1110000010010000
0000000000000000
1110001100001000

その他

デバッグ用に、レコード型やバリアント型の値を文字列に変換して表示したかったので、以前、Twitterで教えていただいたmeta_convを使って、変換する関数を自動で生成させようとした。
とりあえず、以下の単純なコードを作成して、

==hello.ml==
open Meta_conv.Open
open Ocaml_conv

type hello =
  | Foo of string
  | Bar of int
with conv(ocaml)

ocamlfindでコンパイルすると、エラーとなった。

$ ocamlfind ocamlc -verbose -package meta_conv,ocaml_conv -syntax camlp4o -package meta_conv.syntax hello.ml 
findlib: [WARNING] Interface topdirs.cmi occurs in several directories: /home/satoshi/.opam/4.02.1/lib/ocaml, /home/satoshi/.opam/4.02.1/lib/ocaml/compiler-libs
Effective set of preprocessor predicates: preprocessor,syntax,camlp4o
Effective set of compiler predicates: pkg_meta_conv,pkg_compiler-libs,pkg_compiler-libs.common,pkg_ocaml_conv,pkg_camlp4,pkg_type_conv,pkg_meta_conv.syntax,syntax,autolink,byte
+ ocamlc.opt -verbose -I /home/satoshi/.opam/4.02.1/lib/ocaml/compiler-libs -I /home/satoshi/.opam/4.02.1/lib/ocaml_conv -I /home/satoshi/.opam/4.02.1/lib/ocaml/camlp4 -I /home/satoshi/.opam/4.02.1/lib/type_conv -I /home/satoshi/.opam/4.02.1/lib/meta_conv -pp "camlp4 '-I' '/home/satoshi/.opam/4.02.1/lib/ocaml/camlp4' '-I' '/home/satoshi/.opam/4.02.1/lib/type_conv' '-I' '/home/satoshi/.opam/4.02.1/lib/meta_conv' '-I' '/home/satoshi/.opam/4.02.1/lib/meta_conv' '-parser' 'o' '-parser' 'op' '-printer' 'p' 'pa_type_conv.cma' 'meta_conv.cmo' 'pa_meta_conv.cma' " hello.ml
+ camlp4 '-I' '/home/satoshi/.opam/4.02.1/lib/ocaml/camlp4' '-I' '/home/satoshi/.opam/4.02.1/lib/type_conv' '-I' '/home/satoshi/.opam/4.02.1/lib/meta_conv' '-I' '/home/satoshi/.opam/4.02.1/lib/meta_conv' '-parser' 'o' '-parser' 'op' '-printer' 'p' 'pa_type_conv.cma' 'meta_conv.cmo' 'pa_meta_conv.cma'  'hello.ml' > /tmp/ocamlpp86694c
File "hello.ml", line 1:
Error: Error while linking hello.cmo:
Reference to undefined global `Ocaml_conv'
ocamlc.opt returned with exit code 2 


Ocaml_convがうまく参照できないようだ。
きっとライブラリの指定の方法か、OCamlの開発環境に原因があるのだろう。
こちらは、そのうち調べてみよう。

2015年4月28日火曜日

[OCaml]正規表現ライブラリRe2を使う

Core Document を眺めていたら、
Re2 OCaml bindings for RE2, Google's regular expression library
があった。
使い方をメモしておく。

インストール

opamでインストールできる。

$ opam install re2

以下はutopでの確認。

utop[11]> #require "re2";;

(* create関数の定義を確認 *)
utop[16]> Re2.Regex.create;;
- : ?options:Re2.Regex.Options.t list -> bytes -> Re2.Regex.t Or_error.t = <fun>

(* 正規表現を作る *)
utop[18]> let re = Re2.Regex.create_exn "aaa(.*)bbb";;
val re : Re2.Regex.t = <abstr>

(* 正規表現のパターンを取得する *)
utop[19]> Re2.Regex.pattern re;;
- : bytes = "aaa(.*)bbb"

(* マッチさせる *)
utop[20]> Re2.Regex.find_all re "aaaほげbbbaaaふがbbb";;
- : bytes list Or_error.t =
Core_kernel.Result.Ok ["aaaほげbbbaaaふがbbb"]

(* .*部分を最長一致さたいので正規表現を作り直し *)
utop[21]> let re = Re2.Regex.create_exn "aaa(.*?)bbb";;
val re : Re2.Regex.t = <abstr>

(* 再度マッチさせる *)
utop[22]> Re2.Regex.find_all re "aaaほげbbbaaaふがbbb";;
- : bytes list Or_error.t =
Core_kernel.Result.Ok ["aaaほげbbb"; "aaaふがbbb"]

(* サブマッチを取り出す *)
utop[23]> Re2.Regex.find_all re ~sub:(`Index 1) "aaaほげbbbaaaふがbbb";;
- : bytes list Or_error.t = Core_kernel.Result.Ok ["ほげ"; "ふが"]

(* マッチした文字列を置換する *)
utop[26]> Re2.Regex.rewrite re ~template:"<replaced>" "aaaほげbbbcccふがddd";; 
- : bytes Or_error.t = Core_kernel.Result.Ok "<replaced>cccふがddd"

(* サブマッチを取り出す(その2) *)
utop[27]> Re2.Regex.find_submatches re "aaaほげbbbaaaふがbbb";;
- : bytes option array Or_error.t =
Core_kernel.Result.Ok [|Some "aaaほげbbb"; Some "ほげ"|]

(* 先頭からマッチさせる *)
utop[28]> Re2.Regex.find_first re "aaaほげbbbaaaふがbbb";;
- : bytes Or_error.t = Core_kernel.Result.Ok "aaaほげbbb"

(* 先頭からのサブマッチ *)
utop[29]> Re2.Regex.find_first re ~sub:(`Index 1) "aaaほげbbbaaaふがbbb";;
- : bytes Or_error.t = Core_kernel.Result.Ok "ほげ"

(* マッチした部分で文字列を分割する *)
(* ~include_matches:true でマッチした文字列を含めることができる *)
utop[30]> let sre = Re2.Regex.create_exn ",";;
val sre : Re2.Regex.t = <abstr>
utop[31]> Re2.Regex.split sre "あい,うえ,おお";;
- : bytes list = ["あい"; "うえ"; "おお"]

マッチしない場合に例外となる関数も用意されている。
これらの関数は後ろに、_exnが付く。
utop[33]> Re2.Regex.find_first re "aaほげbbaaふがbb";;
- : bytes Or_error.t =
Core_kernel.Result.Error
 ("Re2_internal.Exceptions.Regex_match_failed(\"aaa(.*?)bbb\")")
utop[34]> Re2.Regex.find_first_exn re "aaほげbbaaふがbb";;
Exception: Re2_internal.Exceptions.Regex_match_failed("aaa(.*?)bbb").
エンコーディングはデフォルトでUTF-8が使用されるようだ。
オプション指定により、Lantin-1として扱うこともできる。
オプションはRe2.Optionsモジュールに定義されている。

とりあえず、これだけ分かれば、正規表現を使った文字列処理は困らないかな。

参考