vital.vim
vital.vim copied to clipboard
refinements in import() and load()
vital 本体の API のドキュメントを書こうと思ったけど、import() とか load() の仕様の議論がまだ収束してないことに気付くなど。 えーと、load の as 機能について。現状の load(['Foo']) がわかりづらいとの話だった気がする。 個人的には短く書けて気に入っているのだけど。 仕様整理。
load するとモジュールが V に置かれてそこからアクセスできるようになる。
V.load('Foo.Bar.Buz') -> V.Foo.Bar.Buz
複数同時にロード可能
V.load('Foo.Bar.Buz', 'Hoge', 'Huga') -> V.Foo.Bar.Buz -> V.Hoge -> V.Huga
文字列ではなくリストを渡すと、as として処理される
V.load(['Foo.Bar.Buz', 'FBB']) -> V.FBB
as を空文字列にすればトップレベルに直接ロード可能
V.load(['Foo.Bar.Buz', '']) -> V (Foo.Bar.Buz の関数が直接使える)
空文字列の場合は省略可能
V.load(['Foo.Bar.Buz']) -> V (Foo.Bar.Buz の関数が直接使える)
ふと思ったのだけど、リストじゃなくて辞書を渡す仕様にして 5. の省略可能をなくすのはどうか。 as としては辞書の方が自然な気もするし。
V.load({'Foo.Bar.Buz': 'FBB'}) -> V.FBB
必然的に複数同時に処理可能。 ここらで人の意見が欲しい。
lingrでのthincaさんの提案を引用しつつ整形。
まず一般的な指針として、vitalのimport/loadは記述の短さよりも記述のわかりやすさを優先すべきと思っています。「このファイルはこれとこれをこのように使う」というのはexplicitである方が読みやすいです。複数の箇所に散らばるものは常に記述が短くあるべきですが、ファイルの先頭で宣言するものの場合、記述の短さはあまり重要でないと思います。
というわけで、thincaさんの「5. の省略可能をなくすのはどうか」は大賛成です。が、それだけでなく、「2. 複数同時にロード可能」をなくすべき、あるいは別名の関数にするべきだと思います。
というわけでこんな新仕様はどうでしょう。
-
load
するとモジュールが V に置かれてそこからアクセスできるようになる。これ以外にload()の使い道はない。V.load('Foo.Bar.Buz') -> V.Foo.Bar.Buz
-
load_as
すると第二引数の名前で参照可能。これ以外にload_as()
の使い道はない。V.load_as('Foo.Bar.Buz', 'FBB') -> V.FBB
-
import_extending
すると第1引数の変数を破壊的に書き換え、その中に読み込む関数が注入される。したがって以下のようにすることで、元の提案の4.が実現できる。なお、第二匹数が辞書でなかった場合、エラーとなる。また関数名がかぶった場合、元々存在する関数が上書きされ、あとで読み込ませたものが優先される。なお、import_extending
の第二引数は省略できない、つまりこれ以外にimport_extending
の使い道はない。なお、この関数の名前が長いのは、なるべくimportで別の変数を作ってほしいため。V.import_extending(V, 'Foo.Bar.Buz') -> V (Foo.Bar.Buz の関数が直接使える) let B = V.import('Foo.Bar.Baaaa') V.import_extending(B, 'Foo.Bar.Booo') -> B (Foo.Bar.Booo の関数も直接使える)
-
(導入するとすれば)
load_each
で複数同時にロード可能。名前が長いのは、なるべくload()を並べて使ってほしいという想いから。V.load_each('Foo.Bar.Buz', 'Hoge', 'Huga') -> V.Foo.Bar.Buz -> V.Hoge -> V.Huga
-
(導入するとすれば)
import_extending_each
で複数同時。これも同じく意図的に長い名前で。
-
load_as_each
やuse_each
はなし。前者は元の問題の4. や5. などのため。後者はなにが優先されるのかわかりづらいため。
ところで、上記方法で、lingrでmanga_osyo
さんが要求していたユースケース: Vなどを経由せずいきなりs:から使えるようにしたいというものも自然に解決できます。実装上の黒魔術はなく、explicitで、かつ十分に短いです。
V.import_extending(s:, 'A.B.C')
以下、実装の。擬似コード。実際には厳しめの引数のチェックとエラー処理が入ります。
function! s:load(x)
call s:load_as(a:x, a:x)
endfunction
function! s:load_as(x, y)
...
endfunction
" function! s:load_each(...)
" for x in a:000
" call s:load(x)
" endfor
" endfunction
function! s:import_extending(x, y)
call extend(y, s:import(x))
endfunction
まとめおつです。 いくつか意見があったので書き込んでみます。 まず、上記を見て vital.vim でモジュールを使用する場合 3つに分けられると考えられます。
1.V に展開する
- load 関数
2.モジュールの辞書を返す
- import 関数
3.モジュールを展開する辞書を渡す
- import_extending 関数
2.と3.は違う機能なので import を付けずに extending だけ(もしくは全く別の名前)の方が分かりやすいとかと思います。 あと load_each を用意するのではなくて、thinca さん案の load に複数モジュール名を渡したほうがすっきりしていると思います。 わたしも thinca さんの案ではリストも渡すようになっていたので複雑だと思っていたんですが、それを load_as に分ければ問題ないかなーと。 (もしくは load_each が非推奨であるなら削除してしまったほうがいい。
以下、上記を加味した使用方法の提案
" ---------------------------------------------------------
" V にモジュールを展開する
call V.load("Foo.Bar")
=> V.Foo.Bar
" 複数のモジュール名を渡すことで複数のモジュールを展開
call V.load("Foo.Bar", "Foo.Buz")
=> V.Foo.Bar
=> V.Foo.Buz
" laod_as で参照する名前を変更する
" こちらは複数ロード不可
call V.load_as("Foo.Bar", "FB")
=> V.FB
" ---------------------------------------------------------
" モジュールの辞書を返す
let M = V.import("Foo.Bar")
=> M.Foo.Bar
" こちらも複数のモジュールを指定することが出来る
let M = V.import("Foo.Bar", "Foo.Buz")
=> M.Foo.Bar
=> M.Foo.Buz
" ---------------------------------------------------------
" モジュールを展開する辞書を渡す
" s: にモジュールを展開する
call V.extending(s:, "Foo.Buz")
=> s: から直接使用出来る
" こちらも複数のモジュールを指定することが出来る
call V.extending(s:, "Foo.Bar", "Foo.Buz")
=> s: から Foo.Bar と Foo.Buz 直接使用出来る
とりあえず、わたしの考えはこんな感じです。
関数の数が多すぎる気がします。 微妙に動作の違う関数がたくさんあると、ユーザはどれを使えばいいのかわからず混乱します。 似た機能の関数はまとめた方がわかりやすいのではないか、と言うのが私の意見です。
ユーザはどれを使えばいいのかわからず混乱します
名前が短い順に推奨度が高く、長いほど推奨度が低い、というのを想定して提案してみました。ドキュメントにもそれを明記した方がいいですね。ちなみに、ひとつの関数ができることをひとつにしぼっているので、結果としてすべての仕様を理解するためのコストは小さいと思います。
ひとつの関数で複数のことができると、ユーザはどの方法が推奨されているのかわからず混乱します。異なる機能の関数は分けた方がわかりやすいのではないか、というのが私の意見です。
そもそも、1つの方法を推奨するつもりはないです。 好きなように使っていただければ。
co-meeting の方でも話し合っていたのですが、現在固まっている仕様はこんな感じです。 https://github.com/vim-jp/vital.vim/wiki/load-import%E4%BB%95%E6%A7%98%E3%81%BE%E3%81%A8%E3%82%81 ujihisa.vim を一旦の〆と考えていたので、この仕様で問題がないのであればこれに決めたいかと思います。 どうでしょうか?
あと co-meeting のログはここら辺を参照して下さい。 https://www.co-meeting.com/g/870141505682293#!508352d4ab5c3734390006c1
co-meetingはアカウント持ってないと見れないのがちょっとアレですね。 Lingrみたいに誰にでも公開にできないもんでしょうか。
ぼくもオープンな場所がいいと思います。
確かに公開出来ないのは厳しいですね…。