Skip to content

Conversation

tomconnors
Copy link

I'm just opening this to further the discussion in #15. I don't think this is production-ready code.

With this impl, datastar expressions compose more easily. The two new public API macros I added are d*js and d*js-str. d*js is like ->expr but it returns a JSExpression object. Note that Chassis automatically calls str on these objects, so if using Chassis we can use code like:

[:div {:data-on-click (d*js (set! $signal (.. evt -target -value)))}]

That's just like what we'd do with ->expr. For usage in contexts that don't automatically coerce to string, you could expose the d*js-str macro, which is just (str (d*js ~@forms)). Or callers could just call str directly.

The important change vs the current implementation of this lib is that expressions compose easily:

(def my-d*js (let [x (d*js (.. evt -target -value))
                   num 55
                   y (d*js (+ ~num ~x))]
                 (d*js (set! $signal ~y)
                       (set! $other-signal "no"))))

  (clj my-d*js) ;; => (do (set! $signal (do (+ 55 (do (.. evt -target -value))))) (set! $other-signal "no"))
  (js my-d*js)  ;; => "$signal = (55) + (evt.target.value); $other-signal = \"no\""
  (str my-d*js) ;; => "$signal = (55) + (evt.target.value); $other-signal = \"no\""

The main problems I have with this impl are:

  • bad names
  • using postwalk at runtime, not just macroexpand time. That can probably be solved?

@Ramblurr
Copy link
Collaborator

This is brilliant, thanks tom!

With regards to names: we can sort that out.

It seems to me that d*js should be the default behavior of the current ->expr, so that expressions are composable by default.

As for the use of walk, your example code in the linked issue didn't use walk, but I guess it only processed the top level forms. Hm will have to noodle on this. It might be ok to eat the cost and provide an escape hatch to the current ->expr behavior. What do you think?

@tomconnors
Copy link
Author

Just added a commit which removes the runtime walk. The basic changes are:

  • use pr-str rather than str before passing to squint
  • implement print-method and print-dup for JSExpression type, with impl using (pr-str (clj js-expression-object)).

I'm sure you noticed squint doesn't give us an api that takes data, just a string api, so in this impl I'm just making use of the traversal that already has to happen when serializing the forms we pass to squint.

@Ramblurr
Copy link
Collaborator

I'm on vacation, so I won't be able to get back to this until next week. But I think its great! Excited to try it myself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants