Upgrade to Pro — share decks privately, control downloads, hide ads and more …

超変換! Hiccup data structure!!

ayato
August 31, 2017

超変換! Hiccup data structure!!

ayato

August 31, 2017
Tweet

More Decks by ayato

Other Decks in Programming

Transcript

  1. Hiccup Data Structure!!
    Lisp Meet Up presented by Shibuya.lisp #55
    超変換!!

    View full-size slide

  2. –Johnny Appleseed
    ʠ͜͜ʹҾ༻Λೖྗ͍ͯͩ͘͠͞ɻʡ
    –Yusuke Godai
    “こんなやつらのために、
    これ以上誰かの涙は⾒たくない!
    皆に笑顔でいて欲しいんです!
    だから⾒ててください!俺の…変⾝!! ”

    View full-size slide

  3. –Johnny Appleseed
    ʠ͜͜ʹҾ༻Λೖྗ͍ͯͩ͘͠͞ɻʡ
    –@ayato-p
    “HTML Formのために、
    これ以上誰かの涙は⾒たくない!
    Hiccupユーザーに笑顔でいて欲しいんです!
    だから⾒ててください!俺の…変換!! ”

    View full-size slide

  4. あやぴー
    •ayato-p@github
    •Cybozu Startups, Inc.
    •Clojureエンジニア
    •Webアプリを作るお仕事
    •仮面ライダーと言えばクウ○世代
    •ガンダムと言えばS○ED世代

    View full-size slide

  5. 今日の話

    View full-size slide

  6. 今日話すこと
    •そもそもHiccupとは
    •HTMLフォームを書くのが面倒だということ
    •Hiccupデータの変換について
    •ClojureScriptでマクロ展開するときハマった話
    •「仮面ライダーク○ガ」の素晴らしさについて

    View full-size slide

  7. 今日話すこと
    •そもそもHiccupとは
    •HTMLフォームを書くのが面倒だということ
    •Hiccupデータの変換について
    •ClojureScriptでマクロ展開するときハマった話
    •「仮面ライダーク○ガ」の素晴らしさについて

    View full-size slide

  8. そもそもHiccupとは
    •HTMLをClojureのデータ構造で表現するDSL
    •ベクタをタグ、マップを属性として表現する
    •Clojureコミュニティでは人気(?)
    •沢山のライブラリがHiccup-likeなデータでの表現を

    サポートしている
    •例) Enlive, Reagent, Rum, Instaparse, etc

    View full-size slide

  9. そもそもHiccupとは
    [:a#mybtn.button {:href "..."} "..."]
    タグベクター: ベクタで表現したHTMLタグ

    View full-size slide

  10. そもそもHiccupとは
    [:a#mybtn.button {:href "..."} "..."]
    タグ名: CSSセレクターのように書ける

    View full-size slide

  11. そもそもHiccupとは
    [:a#mybtn.button {:href "..."} "..."]
    属性: マップで表現

    View full-size slide

  12. そもそもHiccupとは
    [:a#mybtn.button {:href "..."} "..."]
    コンテンツ: タグベクターや文字列を書ける

    View full-size slide

  13. これであなたも
    ✨Hiccupマスター✨

    View full-size slide

  14. HTMLフォームを
    書くのは面倒だ

    View full-size slide

  15. HTMLフォームは面倒
    •フォームのポスト処理に失敗した場合、入力されていた
    値を入力された状態にして再描画しなければいけない
    •利用しているCSSフレームワークのルールにそって、

    エラーが適切に表示されるようにしなければならない
    •全てのHTMLフォームを全く同じように表示したくない
    ことがある
    •例) ログインフォーム、グリッドスタイル

    View full-size slide

  16. [:div.form-group
    [:label {:for "input-email"} "Email address"]
    [:input#input-email.form-control
    {:type :email :name :email
    :class (when (contains? errors :email) "is-invalid")
    :value (:email values)
    :placeholer "Enter email"}]
    [:div.invalid-feedback (:email errors)]
    [:small.form-text.text-muted
    "We'll never share your email with anyone else."]]
    Bootstrap4の場合

    View full-size slide

  17. [:div.form-group
    [:label {:for "input-email"} "Email address"]
    [:input#input-email.form-control
    {:type :email :name :email
    :class (when (contains? errors :email) "is-invalid")
    :value (:email values)
    :placeholer "Enter email"}]
    [:div.invalid-feedback (:email errors)]
    [:small.form-text.text-muted
    "We'll never share your email with anyone else."]]
    Bootstrap4の場合

    View full-size slide

  18. どうにかしたい…
    1.諦める
    2.小さい関数で面倒なところをラップする

    (hiccup.formみたいな)
    3.Formativeみたいなフォーム用ライブラリを使う

    (jkk/formative)
    4.まだ見たこと無い解決方法

    View full-size slide

  19. OOPな言語のWAFだと…
    •フォームに値をマッピングするのに
    •フォームオブジェクトをつくる
    •ORMのモデルオブジェクトをつかう
    •エラー用クラスを付与するのに
    •カスタムタグをつくる
    •エラー時に固定のCSSクラスを付与する

    View full-size slide

  20. –Johnny Appleseed
    ʠ͜͜ʹҾ༻Λೖྗ͍ͯͩ͘͠͞ɻʡ
    –Yusuke Godai
    “求められた気がしたんです。
    あの蜘蛛みたいな奴と戦えって!”

    View full-size slide

  21. –Johnny Appleseed
    ʠ͜͜ʹҾ༻Λೖྗ͍ͯͩ͘͠͞ɻʡ
    –@ayato-p
    “求められた気がしたんです。
    あのVerbose Hiccupと戦えって!”

    View full-size slide

  22. Kuugaとは
    •Pure Clojureにしか依存していない
    •ユーザーが自由に
    •任意のタグやクラスに対して変換ルールを定義できて
    •マクロ展開時に変換することもできて
    •ClojureScriptもサポートしている
    •Hiccupのようなデータを変換するライブラリ
    •https://github.com/ayato-p/kuuga

    View full-size slide

  23. 変換ルールを書く-その)
    (defmethod growing/transform-by-tag :input
    [_ options tag-vector]
    (let [[tagkw tagopts contents] (tool/parse-tag-vector tag-vector)]
    `[~tagkw
    (update-input-opts ~options ~tagopts)
    ~@contents]))

    View full-size slide

  24. 変換ルールを書く-その*
    (defmethod growing/transform-by-class :form-group
    [_ options tag-vector]
    (let [[tagkw tagopts contents] (tool/parse-tag-vector tag-vector)
    contents
    (reduce (fn [contents' tagvec']
    (let [[tk to _] (tool/parse-tag-vector tagvec')
    [_ t] (tool/parse-tag-keyword tk)]
    (cond-> (conj contents' tagvec')
    (= t "input") (conj `(invalid-fb ~options ~to)))))
    []
    contents))]
    `[~tagkw
    ~tagopts
    ~@contents]))

    View full-size slide

  25. こうすると…

    View full-size slide

  26. これを…
    [:div.form-group
    [:label {:for "input-email"} "Email address"]
    [:input#input-email.form-control
    {:type :email :name :email
    :placeholder "Enter email"}]
    [:small.form-text.text-muted
    "We'll never share your email with anyone else."]]

    View full-size slide

  27. こんな感じで展開できる
    [:div.form-group
    [:label {:for "input-email"} "Email address"]
    [:input#input-email.form-control
    {:type :email :name :email
    :class (when (contains? errors :email) "is-invalid")
    :value (:email values)
    :placeholder "Enter email"}]
    [:div.invalid-feedback (:email errors)]
    [:small.form-text.text-muted
    "We'll never share your email with anyone else."]]
    ※イメージです

    View full-size slide

  28. Kuugaのメリット
    •マクロ展開時に変換できる
    •なので実行時の変換コストがない
    •特別なタグ/記法を覚える必要がない
    •どのくらい変換ルールを書くかもユーザー次第

    View full-size slide

  29. Kuugaのデメリット
    •特にない
    •マクロ展開時に変換するルールを書くのが少し難しい
    •実行時に変換する方法は速度があまり出ない

    View full-size slide

  30. KuugaとClojureScript

    View full-size slide

  31. Kuugaは…
    •マクロ展開時にHiccupデータを変換できる
    •拡張ルールをマルチメソッドで記述する
    •ClojureScriptをサポートしている

    View full-size slide

  32. ClojureScriptでのマクロ
    •ClojureScriptでマクロは書けない
    •セルフホストはとりあえず忘れる
    •マクロ展開はClojureの環境が利用される
    •展開後のフォームに含まれるものはClojureScript上に

    なければならない

    View full-size slide

  33. 問題.
    •マクロ展開時に利用されるマルチメソッドはClojureの

    環境で定義されていなければならない

    View full-size slide

  34. 問題.
    •マクロ展開時に利用されるマルチメソッドはClojureの

    環境で定義されていなければならない
    •ClojureScriptのビルド時に変換ルールを読み込んで
    おかないといけない

    View full-size slide

  35. 解決策
    •cljsbuildなどの既存のツールに任意のClojure libを

    読み込む仕組みがなさそう?
    •自前でスクリプトを書いて、その中で任意のlibを

    読み込みClojureScriptのビルドAPIを直接叩く
    •lein-execはプロジェクトの環境を引き継げる
    •Bootは元々そういう用途で使えるので便利
    https://github.com/ayato-p/kuuga/blob/master/examples/cljs/script/cljsbuild.clj

    View full-size slide

  36. まとめ
    •Kuugaを使うとわりとハッピーになれる(気がした)
    •マクロ展開時に分かっている部分を変換するコンセプト
    を適用できるところは他にもある気がする
    •SQL Builder的なやつとか

    View full-size slide