2011/11/22


この記事はsuginoy氏のブログ杉風呂2.0 - A Lifelog -の記事"あなたはJavaScriptを知らない"をパロったものです。suginoyさんの許可を得て公開します。原文は2011年11月17日にポストされました。私自身のVim scriptの学習は適当で、ネタ仕込みの指摘等はコメントを下さると助かります。

あなたはJavaScriptを知らない

この記事はMichael Woloszynowicz氏のブログWeb 2.0 Development And Business Lessonsの記事"You Don’t Know JavaScript"を翻訳したものです。本人の許可を得て公開します。原文は2011年4月16日にポストされました。私自身のJavaScriptの学習が浅く、誤訳の指摘等はコメントを下さると助かります。

http://d.hatena.ne.jp/suginoy/20111117/p1
Web 2.0 Development and Business Lessons: You Don't Know JavaScript

Over the last year or so I've noticed an irritating phenomenon developing. I've seen a repetitive pa...

http://www.w2lessons.com/2011/04/you-dont-know-javascript.html

去年ぐらいから、いらいらする現象が目に留まるようになった。プログラマが、少ししか触っていないVim scriptでありながら、それでブログを脚色するパターンに何度も出会った。多くの言語で起こることではあるが、最も冒涜を受けている言語がVim scriptだ。

あなたは自分が知らないということを知らない

この理由は、だいたいすべてのvimmerが1度ぐらいはvimrcを扱う必要に出くわすからだ。理解もしないでVim scriptを憶える最もありふれたアプローチとして、その場しのぎにサンプルコードを探してきてコピペするのだ。この手の'学習'で問題なのは、開発者が実際にはその言語を学んでおらず、その上、自分がそれを知っている錯覚してしまうことだ。何年もvimでネタ記事を書いてきて学んできた過程でわかったのは、本当に理解するようになってはじめて、知らないということがわかるということだ。このことはある種、循環した話であり、あなたに本当に必要なのは、自分がわかっていないということを教えてくれる人であり、本当の学習だ。サンプルコードをつなぎあわせただけの単純なキーマップやコマンドしかやったことがないのに、誇らしげにVim scriptをブログ記事にアップした誰かさんにたくさんソーシャルブックマークを付けすぎている。webapi-vimやvitalのようなフレームワークを使い知るということはいいことだが、それらの背後にあるVim scriptを正しく理解することなしには、それらのツールキットをマスターすることはないだろう。Vim scriptの多くの要素を表現するのに、私が基本レベル、中級レベル、上級レベルの知識だと思う考えを以下に示す。

Vim script理解の基本レベル

  • 基本的なプログラミングのツール、例えば、ループやifステートメント、try/catchなどを知る。
  • 関数定義と適用に様々な方法があることを知る。無名関数がVim scriptにはない。
  • g: s: l: という変態的なスコープ定義の原則、グローバルスコープ(g:) 対スクリプトスコープ(s:)を理解する。
  • ディクショナリの役割とself変数の使い方を理解する。
  • deepcopyによるディクショナリのなんちゃってインスタンス化と宣言の様々なやり方を理解する。s: で取得する際の関数リファレンスがユニークなスコープを含んでいないということも同様。
  • Vim scriptの比較演算子、例えば、'=#'、'=~'で何がfalseになるか、数値とstringが節操なく比較されている事を理解する。キャスト?なにそれ。
  • 文字列の添え字アクセスが文字列を返すという気持ち悪さと、コードから配列と見分けが付きにくいという言語本来の設計思想の誤りを認識する。
  • 文字列結合とディクショナリのメンバアクセスが同じ「.」を使っているという致命的な言語仕様を改めて認識する。
  • 2行に渡るコードを示すマークが前の行の最終文字に与えられるのでは無く、後続する行の先頭に付くという、残尿感に似た感覚を覚える。

Vim script理解の中級レベル

  • タイマーなんてない世界でどうやって遅延動作を生むか、CursorHoldの発火を制御するupdatetime設定値がグローバルであり、1つのVim scriptで設定を弄れば他のプラグインに迷惑をかけるという事を理解する。
  • スレッドを使うと頻繁に落ちる事もしかり。
  • 安全なスレッド間、プロセス間通信を行う為にはremote-expr等を使うしかないが、Linux版はX11プロトコルに依存してしまっている為、CUIでは動作しないという至らなさを知る。

Vim scriptの理解の上級レベル

  • 引数へのアクセスにいちいち a: をつけなければいけないという、いかにも跡付けサクサクな仕様を学ぶ。
  • GCの仕様が中途半端な為、lambdaが実装しづらい事を学ぶ。
  • true/falseが無く自分でs:true/s:falseを宣言しなければならないむなしさ知る。
  • evalにスコープ指定が使えないのでユーザからの文字列指定によりスクリプト変数にアクセスし放題であることを学ぶ。
上級レベルの最後のポイントはとりわけ重要であり、最も到達するのが難しい。Vim scriptの変態的で怠慢な性質を考えれば、バージョンにより使える機能が大きく異なるvimプラグインをメンテナンスするという事は、時間の無駄にもつながる。いったんVim scriptという言語自身に足を踏み込んでしまうと、それが体系化されていないこと、大きなアプリケーションのリファクタリングが大変である事を理解出来る様になって、真にVim scriptの仕様の駄目さがマスターできるだろう。それには数年間の訓練と失敗と鍛錬が必要であり、vimテクニックバイブルという本1冊では精通することができない。私自身は、Vim scriptを日常的に毎日数時間、数年間使用していて、自分のコードを書くのにより良い方法を見つけようとし続けているところだ。 こういった理由で、誰かのコードを単純にコピペするという行為ことは危険であるし、vitalのコードに誰も寄与しようとしなくなる傾向がある。 Vim scriptは至らない仕様を後方互換性を維持し続けた事で、無秩序に浸透しているので、上に挙げた要件は、言語特有の知識から分離することにした。言語の側面(例えばlet命令により代入が式に出来ない)はVim scriptに悪い習慣を与え、すべてのVim scriptプログラマを震え上がらせ、くらくらさせてきた。Vim scriptを言語のコンテキストで使おうとするならば、すべての良い開発者が知るべき追加事項が存在する。
  • 諦めるということ。つまり、もう言わなくても分かるよね。
  • 関数リファレンスを含む可能性のあるディクショナリから値を変数に代入する場合は、予め変数名を大文字にしておく。
  • マルチプラットフォームを考えるなら、パスを正規表現で置換すべきではないし必ずfnamemodify()でフルパスに変換して行うべきだ。

上記のリストからわかることは、Vim scriptには、関数リファレンスを代入する変数名は大文字でなければならない事や、文字列結合識別「.」とディクショナリのメンバアクセス「.」が同じである等という、言語仕様の地獄が存在するということだ。コピペできる以上のことがかなり多く存在するし、人のブログを読み訓練し我慢することでしか本物のVim scriptプログラマになることことはできない。これらすべてのトピックをカバーする偉大な書籍が『Vimテクニックバイブル ~作業効率をカイゼンする150の技』だ。思い出してほしい。Vim scriptがvimrcを記述する為の言語で、Linuxユーザの誰しもがvimを持っていて、セットアップの時間すらかからないということを。シンプルなif分岐を作って、上に挙げた概念(concepts)と戯れ始めよう。ブログ記事の脚色についてだが、初心者レベルをカバーして、中級レベルに飛び込んでいれば、Vim scriptをリストに加えてもよいと認めよう。コピペしないで、自分が望んだ機能(function)を開発していることに気づいたなら、Vim scriptを知っていると主張できる。それまではVim scriptを知っているなどと宣伝しないでほしい。

私が書き損じたvimscriptの側面があっても、コメント欄には書かないでほしい。また、JSや他の言語と比べる等というキチガイ染みた行動もおこさないで欲しい。

付け加えておくと、私はWebフロントエンド・バックエンド開発者でもあるが、もともと制御系システムの開発者であり、何でも屋の開発者へと進化してきた。今日では、ほとんどすべての開発でvimが無いと手が震えるという中毒症状であり、それがこの記事の意図するところだ。見下そうという意図はなく、Vim scriptにあるものすべてを知れと主張するわけではない。私の希望は、Vim scriptは至らない仕様の山に埋め尽くされそうな中においてもパワフルな言語で、見た目以上のものがあるのだと、より多くの人が気づいてほしいということだ。

もし、このポストを気に入ったら、はてなブックマークしてほしい。

Posted at by



2011/11/18


この記事見てたら、「vimscriptでも書けるさ!」と悔しくなったので勢いだけで書いた。
Simple Scheme interpreter in Perl - Life is very short

Simple Scheme interpreter in Perl perl , scheme | 21:52 昨日 Brainfuck を書いてみたので、今日は Scheme( Lisp )の 処理...

http://d.hatena.ne.jp/syohex/20111116/1321447925
後悔していない。

mattn/lisper-vim - GitHub

This vim plugin provide lisp environments for vimmers.

https://github.com/mattn/lisper-vim
見ての通り、vimscriptだけでlispエンジンが動きます。syohexさんのはスクリプト的でしたが、autoloadでしかもインスタンスを起こせるのでLISPマシンとして使えます。

使い方は何個かあってまず
:echo lisper#eval('(+ 1 2 3 4 5)')
ワンライナーで書けます。ただこれは毎回エンジンを起動させてるだけです。

次にエンジンを作る方法。
:let engine = lisper#engine()
:echo engine.eval("(+ 1 2 3 4 5)")
15
:echo engine.eval("(+ 1 (length (quote abc)))")
4
一応、エンジン1つに対して環境を一つ持っているので、エンジン2個同士が干渉する事は無い様にしたつもりです。
lambdaも書けるし、defineも出来るので (define myadd (lambda (a b) (+ a b)))
(myadd 10 20)
こんな風にエンジン内に関数作る事も出来ます。

で、やっぱりReplだよねーって事で :LisperRepl
と起動すると、vimのコマンドラインでlispが出来る様になります。楽しいですね!
lisper-vim
良かったら遊んで下さい。lispの仕様はあまり詳しくないので、間違ってたら教えて下さい!

今後はこのlispから別のvimscriptが呼べたら楽しいなーとか思ってます。
Posted at by



2011/11/15


let [s:i,s:t]=[0,system("curl -L -s http://hackertyper.net/kernel.txt")]
funs:hacker_typing()
  let c=s:t[s:i]
  let s:i=s:i+1
  retu c
endfun
new|on!|setl ft=c noci noai nosi cink= |imapc
for c in range(1,255)|exe "inoremap <buffer> <expr> <char-".c."> <SID>hacker_typing()"|endfor
star!
ファイル開いて :so % で開始してね!
終了するには、「おっぱいおっぱい」と入力して下さい。
Posted at by