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を読み込むことができます。
もどる
blog comments powered by Disqus