vim-users.jp

Hack #235: リストの要素の総和や総乗を簡単に求める

Posted at 2011/10/10
このエントリーをはてなブックマークに追加

こんにちは、ujihisaです。無事引っ越しが完了しましたが、インターネット回線の確保にはもうしばらく時間がかかるらしく、しばらく家でオフラインな状態です。ちなみに来日することが決まりました。こんなカンファレンスや、勉強会を企画してみました。いずれも来月です。ふるってプレゼンに応募ください。

問題

リストlistの和は、他の言語ならば以下のようにして求めることが一般的です。

  • Ruby
    • list.inject(:+)
    • これは list.inject {|i, j| i + j }の意。Enumerable#injectの特殊用法
    • list.inject(0, :+)
    • 同じくこれは list.inject(0) {|i, j| i + j }の意。
  • Haskell
    • foldl1 (+) list
    • これはfoldl1 (\i j -> i + j) listの意。言語仕様として演算子は括弧でくくるだけで2引数関数のような振る舞いになる(*1)。
    • sum list
  • Python
    • reduce(lambda a, b: a + b, list)
    • sum(list) と、sumといった直接的な方法がサポートされているかは別にして、なんらかの「リストと関数を受け取り、(リストに限らない)なんらかの値を返す」関数が提供されるのが一般的であることがわかります。

Vim scriptには残念ながらそういった関数が標準では提供されていないようです。どうすればよいでしょうか。

解決

vital.vimという、プラギン埋め込み型の汎用ライブラリを使います。

前述の問題を解決するには、vitalのData.Listモジュールを用いるのがよいでしょう。Data.Listの上記要件を満たす関数は以下の4つで、意味はそれぞれHaskellのPreludeに定義されているものと同じです。

  • foldl
  • foldl1
  • foldr
  • foldr1

たとえばfoldl1を用いると、以下のようにしてリストlistの要素の値の総和を求めることができます。

let L = vital#of('プラギン名').import('Data.List')
echo L.foldl1('v:memo + v:val', list)

非常に書きやすく読みやすく、理想的です。なお、実験的にvitalを用いる場合は、vitalを&rtpに入れた上でvital#of('vital')とするとそのvitalを読み込むことができます。

ujihisa

もどる
blog comments powered by Disqus