EzDevInfo.com

cljx

Write a portable codebase targeting Clojure/ClojureScript

Clojure / ClojureScript Crossovers and cljx

I'm trying to figure out the relationship between ClojureScript crossovers and the cljx pre-processor.

Are they designed to be used together? Or rival solutions to the same problem?

Is one becoming the preferred or more standard way to do things?

In particular what I want to do is to create a single library that can be compiled as Clojure and ClojureScript (with a couple of variations). I'm currently using cljx for this.

But then I want to include the library in further clj and cljx projects. Looking for information about this, I'm largely coming across documentation for crossovers but not cljx.


Source: (StackOverflow)

How do I get cljx to compile clojure files into classes during uberjar?

I'm using cljx to build cli / cljs applications but haven't for the life of me been able to create a self packaged compiled jar.

Here's my project file -> https://gist.github.com/chrispwood/4db33e53555a8e8787d1

When I run lein jar or lein uberjar I get only a packaged jar with the clj files, not the class files. See the output file above ^^.

Does anyone know how to make sure the transpiled clj code gets compiled into class files?


Source: (StackOverflow)

Advertisements

Target-dependent macros with cljx

Problem Description

I have a project that targets both Clojure (JVM) and ClojureScript via CLJX.

I have a macro that takes a thunk and creates an IDeref instance to execute that thunk every time it is dereferenced (with deref or @).

Since it's a macro, it has to go in a .clj file. The problem is that the IDeref interface is different for Clojure and ClojureScript. In Clojure I need to generate this:

(reify clojure.lang.IDeref
  (deref [_] thunk))

In ClojureScript I need to generate this:

(reify IDeref
  (-deref [_] thunk))

Since this a macro I can't use the featuer-expression-like syntax from cljx (e.g. #+cljs -deref) to reconcile the code for my two target platforms. Here's what I ended up doing:

(defmacro make-thunk [exp]
  `(reify ~params/IDeref-interface
     (~params/IDeref-method [_#] ~exp)))

I then have a separate params.clj in both the clj and cljs source trees, each of which has a def for each needed symbol.

This works, but it's really ugly, and it feels like a dirty hack.

My Question

I'd really like to keep all of my macros in the same namespace. I'd rather not have to define every platform-dependent symbol for my macros in a separate file. I already have platform-dependent compat.clj and compat.cljs files in the two source trees. Having to add more files to support platform-dependent macros is starting to make things feel cluttered.

Is there a cleaner solution to this problem?


Source: (StackOverflow)

Is there any support for RPC in ClojureScript?

I have a ClojureScript application and I want to make RPC calls to the server which would look like normal function core.async calls on the client side.

In order to do this for the moment I wrote the code below based on cljx. In the RPC definitions section I would have to add all the server-side functions which I want to expose as RPC to the client side.

Note: the send function is taken from here: https://dimagog.github.io/blog/clojure/clojurescript/2013/07/12/making-http-requests-from-clojurescript-with-core.async/

Is there a way to do this nicer without the boilerplate code?

Thinking about how to improve it the only idea that I have is to write a leiningen plugin which generates server side and client side code needed for RPC i.e. the part that I do at this moment using cljx. Is there a better way?

(ns myapp.shared.rpc
  (:require
     #+cljs [myapp.tools :refer [send log]]
     #+cljs [cljs.reader :as reader]
     #+clj  [clojure.tools.logging :as log]
     #+clj  [noir.response :refer [edn]]
     #+clj  [myapp.rpc :as rpc]
   ))

#+cljs (defn rpc-client [function params]
#+cljs   (log "RPC call: (" function params ")")
#+cljs   (send "POST" "/api"
#+cljs         (str "rpc=" (pr-str {:fun function :params params}))
#+cljs         (fn [x]
#+cljs           (log "RPC response:'" x "'")
#+cljs           (:response (reader/read-string x)))))


#+clj (defmulti rpc-impl #(:fun %))

#+clj (defn rpc-server [{rpc :rpc}]
#+clj    (log/info "RPC call received:" rpc)
#+clj    (let [response (-> rpc read-string rpc-impl)]
#+clj      (log/info "RPC response sent: '" response "'")
#+clj      (edn {:response response})))




;;;;; RPC definitions


#+cljs (defn demo [ & p]  (rpc-client :demo p))
#+clj  (defmethod rpc-impl :demo [{p :params}] (apply rpc/demo p))

Source: (StackOverflow)

Using Clojure macros with cljx

I have a code-base for a graphics program in cljx that gets compiled to Clojure and ClojureScript.

I now want to introduce my first macro.

(defmacro optional-styled-primitive [args body] 
   (let [extra (conj args 'style)] 
     `(fn (~extra (->SShape ~'style ~body))
          (~args (->SShape {} ~body)) 
      )
   )
)

The purpose of this macro is to take a list of arguments, and an expression that uses those arguments to generate a geometry. And to return a function with two arities : one of which takes an optional style parameter. This macro is then to be used within the file where it's defined, to make a number of other functions that optionally take styles. For example :

(def square (optional-styled-primitive [n] [[0 0] [0 n] [n n] [n 0]]))

But introducing this macro, obviously, breaks the ClojureScript stage of the compilation.

What I can't figure out is what to do about it. The online discussions talk about ClojureScript needing to use :require-macros but I never actually export or require this macro anywhere. I just want to use it where it's defined. So how can I, in the middle of a file, tell the compiler to use Clojure to expand this macro, before it gets to the ClojureScript compiler?


Source: (StackOverflow)