vimでvim-fireplaceをインストールしてreplで式を評価するまでの手順
新しく配属された人がvim使いだったので
replを使って式を評価するってところまでを調べてやってみた。
まぁそうそう使うことは無いだろうけど、必要になった時のためにということで。
plug.vimインストール
curl -fLo ~/.vim/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
.vimrcを編集
if has('vim_starting') set rtp+=~/.vim/plugged/vim-plug if !isdirectory(expand('~/.vim/plugged/vim-plug')) echo 'install vim-plug...' call system('mkdir -p ~/.vim/plugged/vim-plug') call system('git clone https://github.com/junegunn/vim-plug.git ~/.vim/plugged/vim-plug/autoload') end endif call plug#begin('~/.vim/plugged') Plug 'tpope/vim-fireplace', { 'for': ['clojure'] } call plug#end()
:PlugInstall
いったんVimを閉じる
サンプル用のプロジェクトをひとつ作ってREPLを立ち上げる
mkdir ~/vim-test cd ~/vim-test lein new test cd test lein repl
vimでファイルを開く
vim src/test/core.clj ※ barという関数をここに新しく作る(strとかを返すものだとわかりやすい)
式を評価
; もしかしたらこれも必要かも ; :%Eval :Eval (test.core/bar)
参考にしたサイト
d.hatena.ne.jp github.com hifistar.hatenablog.com haiju.hatenablog.com
flash-get!を使っているページがreplで動かない
ログイン用の簡単なHTMLを出すページをreplとかで動かそうとしたんだけど
ClassCastException clojure.lang.Var$Unbound cannot be cast to java.util.concurrent.Future clojure.core/deref-future (core.clj:2184)
こんなエラーが出て動かなかった。
print-stack-traceでコードを追っかけてみると
どうやらnoir-sessionのflash-getしてるとこで落ちてる模様
user=> (print-stack-trace *e 30) java.lang.ClassCastException: clojure.lang.Var$Unbound cannot be cast to java.util.concurrent.Future at clojure.core$deref_future.invoke (core.clj:2184) clojure.core$deref.invoke (core.clj:2207) noir.session$flash_get.invoke (session.clj:151) noir.session$flash_get.invoke (session.clj:149) sample01.page$base_layout.doInvoke (page.clj:115) clojure.lang.RestFn.invoke (RestFn.java:442) sample01.page$login_page.invoke (page.clj:146) ...
ググって調べてみるとStackOverflowに
「REPLで動かすときはこうすりゃ動くぜ!でもプロダクションには使わないでね(自分解釈)」
と書いてあったので
(binding [sesh/*noir-session* (atom {:somekey "somevalue"})] (sesh/put! :user "borkdude"))
試してみるもエラーは変わらず。
(binding [sesh/*noir-session* (atom {})] (p/login-page {} {}))
仕方ないので、flash-getのコードを眺めてみると
... (declare ^:dynamic *noir-flash*) (defn flash-put! "Store a value that will persist for this request and the next." [k v] (clojure.core/swap! *noir-flash* assoc-in [:outgoing k] v)) (defn flash-get "Retrieve the flash stored value." ([k] (flash-get k nil)) ([k not-found] (let [in (clojure.core/get-in @*noir-flash* [:incoming k]) out (clojure.core/get-in @*noir-flash* [:outgoing k])] (or out in not-found)))) (defn ^:private noir-flash [handler] (fn [request] (binding [*noir-flash* (atom {:incoming (:flash request)})] (let [resp (handler request) outgoing-flash (:outgoing @*noir-flash*)] (if (and resp outgoing-flash) (assoc resp :flash outgoing-flash) resp))))) ...
あれ、もしかして*noir-session*
じゃなくて*noir-flash*
なんじゃね?
と感じたのでやってみるとうまくいった。
(binding [sesh/*noir-flash* (atom {})] (p/login-page {} {}))
今日はエスパー力高かった。
Clojureの内包表記
こんなテーブルから
+--------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------------+--------------+------+-----+---------+----------------+ | id | bigint(20) | NO | PRI | NULL | auto_increment | | display_name | text | NO | | NULL | | | email | varchar(255) | NO | UNI | NULL | | | user_name | varchar(32) | NO | UNI | NULL | | +--------------+--------------+------+-----+---------+----------------+
idとdisplay_nameだけを取り出した
[[1 "user_name_1"] [2 "user_name_2"] [3 "user_name_3"]]
こんな形のデータを作りたくて(hiccupのdrow-downに渡すデータ)調べたんだけど
なかなかいいサンプルが見つからなかったので結局REPLでガチャガチャやって解決。
; usersにselect * from userの結果が入っている (for [user users] [(:display_name user) (:id user)])
こんな感じでいけた
for - clojure.core | ClojureDocs - Community-Powered Clojure Documentation and Examples
ここのサンプルを見ると、:whenを使うことでフィルタリングする条件とかもつけられるらしい。
これは便利そう。
ちなみに、持ってきたデータの先頭に「選択してください」みたいな
valueが空のデータを追加したい場合はconsを使うと出来た
(cons ["選択してください" ""] (for [user users] [(:display_name user) (:id user)]))
Clojureは表現力が高く、とても良い言語なんだけどまだ慣れないなー。
PythonのワンライナーでWebサーバーを立ち上げる
webサーバーがすでに立ち上がってるときなんかに超便利
カレントディレクトリがドキュメントルートになる
# python 2.6.6で確認 python -m SimpleHTTPServer
Windowsのコマンドラインからzipファイルを作る
20個くらいのファイルを加工してからzip圧縮する といった処理で使った。
#cygwin上から実行 $ 7z a test_file.zip test_file.csv
参考: d.hatena.ne.jp
MySQLでCSVの指定のフィールドをロードする
フィールド名を書くところに@dummyのような
捨てる変数を割り当てるとうまくいった。
こんなことも出来たんだな。
これだとわざわざcsvを編集しなくてもいいから便利。
mysql> LOAD DATA LOCAL INFILE '/tmp/test_table.csv' INTO TABLE test_table FIELDS TERMINATED BY ',' IGNORE 1 LINES ( @dummy, field1, @dummy, field2, @dummy, );
ちなみに、最近のバージョンではLOAD DATA LOCAL INFILEはログイン時に
パラメータを渡さないと使えないらしい。
$ mysql -u user -puser db1 --local-infile=1
非推奨なのかな?あとでちゃんと見るか。
参考:
SQL脳向けのmongodbの集計クエリ
mongodbのaggregateフレームワークに全然なれることが出来ない。
10年以上かけて出来たSQL脳にはハードルが高いよねコレ。
SELECT group_key1, group_key2, group_key3, sum(num_field1) as num_field1_sum, min(num_field2) as num_field2_sum, max(num_field3) as num_field3_sum FROM data_table GROUP BY group_key1, group_key1, group_key1
こんなSQLと等価なクエリを書くには
db.data_table.aggregate([ { $match: {"xxx": "xxx"}} , // 必要なら絞り込みの条件を追加 { $group: { _id: { "group_key1": "$group_key1", "group_key2": "$group_key2", "group_key3": "$group_key3" }, // _idのとじカッコに注意。 "num_field1_sum":{"$sum": "$num_field1"}, "num_field2_sum":{"$min": "$num_field2"}, "num_field3_sum":{"$max": "$num_field3"} } } ]);
こうするみたい。