vim-users.jp

Hack #236: 短期間でVim script力を向上する

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

こんにちは、ujihisaです。この記事はGentoo上で執筆しています。ちなみに来日することが決まりました。こんなカンファレンスや、勉強会を企画してみました。いずれも来月です。

問題

Vim scriptというプログラミング言語の能力を高める効率的な方法はあるのでしょうか?

Vimテクニックバイブルも既に完読してしまい、次にやるべきことを見失っている読者も多いかもしれません。

解決

Project Eulerというオンラインの問題集があります。オンラインで答え合わせもできます。

ぜひこれにVim scriptで挑戦してみましょう。以下に問1の回答例を示します。

(もっと良い回答を思いついた、という方はぜひコメントやトラックバックで示してください。楽しみにしています!)

問1

http://projecteuler.net/problem=1

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.

Find the sum of all the multiples of 3 or 5 below 1000.

回答例1

range()で1から1000までの数値の配列を作り、それをもとにforで加算していきます。

function! s:p1()
  let memo = 0
  for i in range(1, 999)
    if i % 3 == 0 || i % 5 == 0
      let memo += i
    endif
  endfor
  return memo
endfunction

echo s:p1()

これをfiletype=vimなバッファで作成し、最後にquickrunしましょう。そこには答えがでているはずです。

回答例1

filter()を使います。

function! s:p1()
  let memo = 0
  let list = filter(range(1, 999), 'v:val % 3 == 0 || v:val % 5 == 0')
  for i in list
    let memo += i
  endfor
  return memo
endfunction

echo s:p1()

さっきよりも見通しのよいコードになったでしょう。lambdaがなくて文字列になってしまうのがちょっと困りものですが…。

さて、この調子でforを消せると考えた人も多くいるかもしれません。そうです、つい5日前に読んだHack #235を思い出しましょう。vitalを使います。

function! s:p1()
  let L = vital#of('vital').import('Data.List')
  let list = filter(range(1, 999), 'v:val % 3 == 0 || v:val % 5 == 0')
  return L.foldl1('v:memo + v:val', list)
endfunction

echo s:p1()

もうここまできたら一行にしたくなるのが人情ですよね。

echo vital#of('vital').import('Data.List').foldl1('v:memo + v:val', filter(range(1, 999), 'v:val % 3 == 0 || v:val % 5 == 0'))

ほかにも多くの解法があると思います。読みやすくかつ短いコードを高速で書くことができるよう、日々鍛錬あるのみです。

ujihisa

もどる
blog comments powered by Disqus