vimの正規表現
vimの正規表現はこのページにまとめてあり、大変参考になる。
vimでプログラムを編集する際に注意していることをメモしておく。
角カッコ[]
対応している角カッコがあると正規表現として扱われる。
角カッコそのものを書くときはエスケープする。
対応するカッコ閉じはエスケープしなくていいようだ。
:s/[3]/[4]/g before: int a[3] after: int a[[4]] :s/\[3]/[4]/g before: int a[3] after: int a[4]
後方参照
丸カッコを後方参照で使うときはエスケープしなければならない。
エスケープされた丸カッコで括った内容を、\1や\2などで参照できる。
:s/(\(.*\))/\1/g before: "Snow (Hey Oh)" after: "Snow Hey Oh"
non-greedyなマッチング
*を使うと0回以上の繰り返しの最大マッチになる。
non-greedyにするには0回以上の繰り返しの最小マッチ\{-}を用いる。
:s/(3.*)/3/g before: (1 2 (3 nil nil) 4) after: (1 2 3 :s/(3.\{-})/3/g before: (1 2 (3 nil nil) 4) after: (1 2 3 4)
便利な記法
\<で単語の最初にマッチする。
:s/king/man/g before: "The king is streaking." after: "The man is streaman." :s/\<king/man/g before: "The king is streaking." after: "The man is streaking."
Perlの正規表現が書けるeregex.vimを使ったほうが良いかもしれない。
vimで操作の記録・再生(キーボードマクロ)
vimで操作の記録・再生を行うには次のようにする。
- 記録する操作の名前を決める(英数字1文字、ここではaとする)
- ノーマルモードでqaと入力する(aは1.で決めた文字)
- 記録したい操作を行う(この間、最下部にrecordingと表示される)
- ノーマルモードでqと入力して、操作の記録を終了する
- ノーマルモードで@a(aは1.で決めた文字)と入力して、現在のバッファに対して操作を適用する
ただし、操作名の大文字小文字は区別されない。
同じ操作を複数の対象に適用したいときに、これを使うのと使わないのでは効率がかなり違ってくる。
カーソル移動コマンド(ggや検索)と一緒に使うと良さそうだ。
初歩的な機能だが、今まであまり使っていなかった。
lazy val
Scalaで結構嵌ったこと。
trait A { val a: Int } trait B extends A { val b: Int; val a = b } object C extends B { val c = 3; val b = c }
こういう風に定義すると、
scala> C.a
res17: Int = 0
となる。しかし、C.a=3となってほしい。
コップ本第20章「抽象メンバー」に答えが書いてあった。ポイントは、スーパークラスから順番に初期化されるということ。
trait Bでval a = bとした時点では、bはデフォルト値0をとるからa=0になるようだ。
正解は、次のようにする。
trait A { val a: Int } trait B extends A { val b: Int; lazy val a = b } object C extends B { val c = 3; val b = c }
スーパークラスから継承したフィールドを初期化する際にlazyをつける。これで、
scala> C.a
res20: Int = 3
となり、期待する動作になる。lazyをつけると、定義時ではなく初めて参照される時点で初期化される。
結論は、traitまたはabstract classで他の値を参照してvalを初期化する際はlazyをつけること。
第20章では他にも、抽象型、パス依存型、構造的サブ型という重要な概念が紹介されている。
コップ本、ちゃんと読まなきゃね・・・