Vim 8.0 で強化された機能 辞書関数
さて、以前の辞書関数は次のように call()
と辞書を経由して呼び出す必要がありました。
let s:dict = { "value" : 0 } function! s:dict.up() let self.value += 1 return self.value endfunction let s:f = s:dict.up echo call(s:f, [], s:dict) " => 1 echo call(s:f, [], s:dict) " => 2 echo call(s:f, [], s:dict) " => 3
Vim 8.0 ではこの縛りが緩和されて、辞書関数を直接呼び出すことができるようになりました。
let s:dict = { "value" : 0 } function! s:dict.up() let self.value += 1 return self.value endfunction let s:f = s:dict.up echo s:f() " => 1 echo s:f() " => 2 echo s:f() " => 3
めちゃくちゃ便利…。
RSpec で not_change マッチャを定義する
通常、Rspec で『変更されないことを検証する』場合、change
マッチャを使用します。
# subject を呼び出しても hoge が変更されないことを検証する
it { is_expected.not_to change{ hoge } }
[not_change
マッチャを定義する]
上記のコードでも問題ないのですが、 RSpec::Matchers.define_negated_matcher
を使用すると書き方を変えることができます。
# change マッチャの否定を定義する RSpec::Matchers.define_negated_matcher :not_change, :change # to を呼び出し、マッチャの名前を変更する it { is_expected.to not_change{ hoge } }
おもしろい
Ruby の ObjectSpace を利用して、オブジェクト名からクラスオブジェクトを探す
Ruby で例えば "String"
という文字列からその名前のクラスオブジェクトを取得したい場合があるとします。
そういう場合は ObjectSpace
から逆算して検出することができます。
# クラスオブジェクトの一覧を取得する classes =ObjectSpace.each_object(::Class) # クラスオブジェクトの一覧から該当するクラスオブジェクトを探す target = "String" result = classes.find { |klass| klass.name == target } p result == String # => truk
また、Rails では String#constantize
というメソッドが定義されており、上記と同等の機能があります。
"String".constantize # => String
[参照]
Vim 8.0 で追加された Vim script の機能 Lambda
Vim 8.0 ではついに Vim script に Lambda が追加されました!
Lambda を定義する場合は { args -> expr }
という構文を使用します。
" Lambda は関数参照を返す " epxr にはその名の通り "式" のみ書くことができる let F = { a, b -> a + b } echo F(1, 2) " => 3
また filter()
関数などに直接 Lambda を渡すことも出来ます。
echo filter(range(1, 10), { index, val -> val % 2 == 0 }) " => [2, 4, 6, 8, 10]
[変数のキャプチャ]
次のように Lambda 外のローカル変数もキャプチャされます。
function! s:main() let value = 10 let F = { a -> value + a } echo F(5) " => 15 endfunction call s:main()
[Lambda 内では式しか定義できない]
Lambda 内では式のみ定義できるので、コマンドなどを直接呼び出すことは出来ません。
" このような使い方は出来ない let Nonumber = { -> set nonumber }
この場合は、同じく Vim 8.0 で追加された execute()
関数を使用します。
execute()
は引数のコマンドを実行する関数になります。
" execute() を経由してコマンドを呼び出す let Nonumber = { -> execute("set nonumber") }
このように execute()
を経由することでコマンドを式として呼び出すことが出来ます。
[引数に a:
をつける必要はない]
Lambda 内で使用する引数には a:
をつける必要はありません。
ですので次のように外部の引数を参照することも出来ます。
function! s:main(arg) let F = { a -> a:arg + a } echo F(5) " => 15 endfunction call s:main(10)
Vim 8.0 で追加された新しいシンタックス
Vim 8.0 では新しく以下の言語に対応しました。
New Syntax/Indent/FTplugin files: AVR Assembler (Avra) syntax Arduino syntax Bazel syntax and indent and ftplugin Dockerfile syntax and ftplugin Eiffel ftplugin Euphoria 3 and 4 syntax Go syntax and indent and ftplugin Godoc syntax Groovy ftplugin HGcommit ftplugin Hog indent and ftplugin Innovation Data Processing upstream.pt syntax J syntax and indent and ftplugin Jproperties ftplugin Json syntax and indent and ftplugin Kivy syntax Less syntax and indent Mix syntax Motorola S-Record syntax R ftplugin ReStructuredText syntax and indent and ftplugin Registry ftplugin Rhelp indent and ftplugin Rmd (markdown with R code chunks) syntax and indent Rmd ftplugin Rnoweb ftplugin Rnoweb indent Scala syntax and indent and ftplugin SystemVerilog syntax and indent and ftplugin Systemd syntax and indent and ftplugin Teraterm (TTL) syntax and indent Text ftplugin Vroom syntax and indent and ftplugin
メジャーどころだと Go
、Json
、Scala
、Groovy
あたりですかねえ。
Vim 8.0 で追加された機能 function() 関数
Vim 8.0 では function()
関数の引数が新たに追加されました。
[引数の束縛]
function()
の第二引数に第一引数に渡す関数の引数を渡すことで、引数の束縛を行うことができるようになりました。
function! Plus(a, b) return a:a + a:b endfunction " 第一引数を束縛 let s:Plus3 = function("Plus", [3]) echo s:Plus3(2) " => 5 echo s:Plus3(-5) " => -2
[関数が参照する辞書を指定]
第三引数に辞書を渡すことで、関数が参照する辞書を指定することが出来ます。
function! Disp() dict return self.name . " : " . self.age endfunction let s:data = { "name" : "homu", "age" : 14 } let s:Disp = function("Disp", [], s:data) echo s:Disp()
関数の束縛がかなり便利。
Vim 8.0 で追加された機能 uniq() 関数
Vim 8.0 で『配列の隣り合う同じ値の要素を削除する』uniq()
関数が追加されました。
echo uniq([1, 1, 3, 2, 2, 3, 3, 1]) " => [1, 3, 2, 3, 1]
また、重複する要素をすべて削除したい場合は、 sort()
と併用して使用します。
" sort() してから uniq() する echo uniq(sort([1, 1, 3, 2, 2, 3, 3, 1])) " => [1, 2, 3]