Reputation: 6447
As of this writing, CLJX is defunct in Clojure/Clojurescript, having been replaced by CLJC, so this question doesn't have any useful answers anymore.
So here's a stab at a canonical question: How do you use Clojure code in ClojureScript from the same project?
From my research so far, I have the impression there are three types of Clojure/Clojurescript files:
Furthermore, there are two ways of bringing in Clojure code to a CLJS call:
Are these "the" ways to do it? What do these look like on the CLJ/CLJS sides?
Upvotes: 4
Views: 924
Reputation: 4235
This isn't really and answer. I was going to put it in a comment, but it got too long. I think your motivation here is good, but I'm not sure about the terminology. It doesn't make sense to talk about using clojure code in clojurescript. There is the language, clojure, a dialect of lisp. It has different implementations. the 'original' implemented on top of Java and the JVM, one implemented on top of Javascript and one implemented on top of CLR (and others). The code in all of them is clojure (the dialect).
When you have a language which is implemented on different platforms, you will get some platform differences. A common example is the conversion of a string to an integer. In clojure based on the JVM, you use the Java Integer object to parse the string and get back in integer object. On the Javascript platform, you call the standard javascript (js) method parsInt.
If you wanted to write just one function which would work on both platforms, you would put that into the cljc file and use reader conditionals to isolate out the platform differences within the function. both your colure and your clojurescript would load that cljc file and both would end up with a function with the same name and api.
However, there are many other more subtle inconsistencies between the platforms. for example, concurrency primitives and things like extending protocols etc.
The reality is, you cannot run clojure code in clojurescirpt. However, due to the shared syntax across the dialects, you can have situations where your clojure cocde and your clojurescript code 'looks' identical and can compile and run under either dialect.
When writing a proram which uses both clojure and clojurescript, when you have code which looks identical, you really don't want to write it twice and you certainly don't want to be forced to maintain two versions. Where possible, you want one version which can be included in both your clojure and your clojurescript. A common example would be data validation libraries. You would like to have the same validation code used for both the server and the clent and you want to only maintain one set of sources.
At this stage, I think the easiest way of doing this is to just include that common code in the cljc file, even when a defn doesn't include any reader conditional. However, you still want to keep this to the minimum - only the definitions which need to be shared between the two.
The concept isn't that your running clojure code in clojurescript - you can't do that. What you are doing is defining code using the clojure dialect and putting it in a file with a cljc extensions, which can be included by both clojure and clojurescript build processes. The code will be compiled into both JVM bytecode and javascript and wil run in either environment.
The one minor complication is with ClojureScript macros. In clojureScript, unlike clojure, macros must be in a different compilation 'unit', which means they must be in a different file to your other ClojureScript code. This is because they are expanded first. They can be in the same namespace, so you could have mycode.cljs and mycode.cljc for example. You cannot mix your normal ClojureScirpt code and ClojureScript macros in the same file as this would mean it is in the same compilation unit.
Upvotes: 2
Reputation: 70211
That's essentially correct. If your code is in a .cljc file, you can just require that namespace and use the functions normally in your .cljs file (just as if it was a .cljs file). If the .cljc has clj/cljs differences, those can be encoded using reader conditionals in the .cljc file.
Or you can define macros in a .clj file and then require and invoke that from your .cljs file.
Upvotes: 4