Clojure/ClojureScript and .cljc how they all interact together? - clojure

I am confused about the .cljc file format. I was wondering if inside a .cljc source file can Clojure and ClojureScript functions interact together. Also I was wondering if I can call from cljc to clj, cljs source file. For example if I define a function inside a .cljc source file can I call that function from the ClojureScript source file?

I was wondering if inside a .cljc source file can Clojure and
ClojureScript functions interact together.
Yes, that's possible and especially trivial if the common code is platform independent, for example:
(defn my-reduce [xs]
(reduce + xs))
All of the functions and forms in the above code exist in both ClojureScript and Clojure, so you don't need to do anything extra to make it work.
It is also possible to include platform dependent sections of code, by using reader conditionals:
(ns my-namespace.foo
(:require
[clojure.string :refer [split]]
#?(:clj [clojure.data.json :as json])))
(defn to-json [x]
#?(:cljs (clj->js x)
:clj (json/write-str x)))
In the above code, the standard reader conditional #? is used.
if I define a function inside a .cljc source file can I call that
function from the ClojureScript source file?
Yes, absolutely, but just be careful to ensure that the code that you call doesn't include any JVM-specific code.
In my code example, you could call to-json, from either ClojureScript or Clojure because I've been careful to isolate the platform differences inside reader conditionals.

Related

How to reference a function within a macro in clojurescirpt?

I have a macro defined like so in macros.cljh file:
(defmacro db-event [event-key params & body]
`(do
(re-frame.core/reg-event-db ~event-key
(fn [~'db [_# ~#params]]
(deep-merge ~'db ~#body)))
(defn ~(symbol event-key) ~params (re-frame.core/dispatch [~event-key ~#params]))))
which references a function deep-merge. This macro is defined in the namespace myapp.macros. Yet when I use the macro in a cljs file, I get the error:
Use of undeclared Var myapp.macros/deep-merge
even though deep-merge is also defined in the myapp.macros namespace
I have the macro required in macros.cljs file like so too:
(ns myapp.macros
(:require-macros [myapp.macros]))
I tried adding this to the cljs namespace declaration:
(:require [myapp.macros :refer [deep-merge]])
But that gives a circular dependency error. What am I doing wrong in refereeing the deep-merge function?
Macros in ClojureScript are more complicated, and must adhere to a 2-stage compilation process.
See these links for starters, then search out other blog postings & docs as well
https://clojurescript.org/about/differences#_macros
https://blog.fikesfarm.com/posts/2016-03-01-clojurescript-macro-sugar.html
In particular, the macro must be defined in a *.cljc or *.clj file, then used in the *.cljs file. You can see some examples in action in this template project:
https://github.com/cloojure/cljs-template
I just checked and it still works, although it uses the old version of Figwheel and has not yet been upgraded to Figwheel-Main (aka Figwheel 2.0).
You should be able to define the macro in the macros.clj file with deep-merge in macros.cljs. As you’ve seen, you can’t introduce circular dependencies. Your goal is to require the namespace, with the macros. :require-macros ensures that if you require the namespace, the macros are included. You should be able to use the macro by requiring the namespace normally:
(ns myapp.core
(:require [myapp.macros :as macros]))
(db-event …)
An alternative solution, instead of calling :require-macros in macros.cljs, is to :require the namespace with :include-macros true. As an example,
In macros.clj:
(ns myapp.macros)
(defmacro twice
[& body]
`(twice-helper (fn []
~#body)))
In macros.cljs:
(ns myapp.macros)
(defn twice-helper
[f]
(f)
(f))
Then we can use the macro in core.cljs:
(ns myapp.core
(:require [myapp.macros :as macros :include-macros true]))
(macros/twice (println "hello!"))

How to make symbol(s) from namespace accessible in all namespaces w/o qualifier?

I have namespace with debug utilities that are used only in development. I'd like to make them accessible in all namespaces without qualifier (same as symbols from clojure.core).
Let's say my project structure is as follows:
dbg_utils.clj:
(ns project.dbg-utils)
(defmacro dbg ...)
db.clj
(ns project.db)
(defn create-entity [...]
...)
After I'd like to fire up REPL and type something like this:
> (require 'project.db)
> (require 'project.dbg-utils)
> (globalize-symbol 'project.dbg-utils/dbg)
And after use dbg macro without qualifier:
(ns project.db) ;; no require of project.dbg-utils
(defn create-entity [...]
(dbg ...) ;; and no qualifier here
...)
Is anything like globalize-symbol (or close to this) available?
Leiningen provides the :injections feature and the :user profile for that.
This article shares some pointers on how to do that. It basically works by adding the debugging functions you want to clojure.core and since all public vars from this namespace are always included when using the ns macro (unless you specify otherwise), you will have them available in all your namespaces.

Using variables declared in another namespace

I have a dictionary of words stored in a vector in one ns (ns dictionary.core) and I want to have access the vector in another namespace, for example, (ns clojure-project.core) How should I do it? I have been researching the concept of namespaces for some time and I am still confused as to how I can "import" variables defined in another file into my current project.
(ns clojure-project.core
(:require [dictionary.core :as dict]))
(defn choose-a-word []
(rand-nth (dict/words)))
Namespace declarations have many options, so it can be very confusing! Limiting yourself to the above form is in my opinion good style.

Difference in Clojure between use and require

I recently started learning Clojure and I'm having a bit of difficulty wrapping my head around namespaces. As the creator of Clojure said, newcomers often struggle to get the concept right. I don't clearly understand the difference between (use ...) and (require ...). For example playing around in the REPL if I say (use 'clojure.contrib.str-utils2) I get warnings about functions in clojure.core namespace being replaced by the ones in clojure.contrib.str-utils2, but that doesn't happen when I use (require 'clojure.contrib.str-utils2). I'm not sure that I will always want to replace what's in clojure.core, so can someone point some best practices for importing external stuff and managing namespaces in Clojure?
Oh and also, when should I use :use and :require? Only inside (ns ....)?
Thanks in advance.
The answer lies in the docstrings:
user> (doc use)
-------------------------
clojure.core/use
([& args])
Like 'require, but also refers to each lib's namespace using
clojure.core/refer. Use :use in the ns macro in preference to calling
this directly.
'use accepts additional options in libspecs: :exclude, :only, :rename.
The arguments and semantics for :exclude, :only, and :rename are the same
as those documented for clojure.core/refer.
nil
And the long one for require:
user> (doc require)
-------------------------
clojure.core/require
([& args])
Loads libs, skipping any that are already loaded. Each argument is
either a libspec that identifies a lib, a prefix list that identifies
multiple libs whose names share a common prefix, or a flag that modifies
how all the identified libs are loaded. Use :require in the ns macro
in preference to calling this directly.
Libs
A 'lib' is a named set of resources in classpath whose contents define a
library of Clojure code. Lib names are symbols and each lib is associated
with a Clojure namespace and a Java package that share its name. A lib's
name also locates its root directory within classpath using Java's
package name to classpath-relative path mapping. All resources in a lib
should be contained in the directory structure under its root directory.
All definitions a lib makes should be in its associated namespace.
'require loads a lib by loading its root resource. The root resource path
is derived from the lib name in the following manner:
Consider a lib named by the symbol 'x.y.z; it has the root directory
<classpath>/x/y/, and its root resource is <classpath>/x/y/z.clj. The root
resource should contain code to create the lib's namespace (usually by using
the ns macro) and load any additional lib resources.
Libspecs
A libspec is a lib name or a vector containing a lib name followed by
options expressed as sequential keywords and arguments.
Recognized options: :as
:as takes a symbol as its argument and makes that symbol an alias to the
lib's namespace in the current namespace.
Prefix Lists
It's common for Clojure code to depend on several libs whose names have
the same prefix. When specifying libs, prefix lists can be used to reduce
repetition. A prefix list contains the shared prefix followed by libspecs
with the shared prefix removed from the lib names. After removing the
prefix, the names that remain must not contain any periods.
Flags
A flag is a keyword.
Recognized flags: :reload, :reload-all, :verbose
:reload forces loading of all the identified libs even if they are
already loaded
:reload-all implies :reload and also forces loading of all libs that the
identified libs directly or indirectly load via require or use
:verbose triggers printing information about each load, alias, and refer
Example:
The following would load the libraries clojure.zip and clojure.set
abbreviated as 's'.
(require '(clojure zip [set :as s]))
nil
They both do the same thing, but use goes the extra step and creates mappings for the stuff in the require'd namespace in the current namespace. That way, rather than doing some.namespace/name you're just referring to it as name. While this is convenient sometimes, it's better to use require or select the individual vars that you want rather than pull in the entire namespace. Otherwise, you could have issues with shadowing (where one var is preferred over another of the same name).
If you don't want to use require, but you know what vars you want out of the namespace, you can do this:
(ns whatever
(:use [some.namespace :only [vars you want]]))
If you don't know which vars you're going to need, or if you need a lot, it's better to use require. Even when you require, you don't always have to type the totally qualified name. You can do this:
(ns whatever
(:require [some.namespace :as sn]))
and then you can use vars from some.namespace like this: (sn/somefunction arg1 arg2)
And to answer your last question: try to only use :require and :use inside of (ns ...). It's much cleaner this way. Don't use and require outside of (ns ..) unless you have a pretty good reason for it.

difference between use and require

Can anyone explain the difference between use and require, both when used directly and as :use and :require in the ns macro?
require loads libs (that aren't already loaded), use does the same plus it refers to their namespaces with clojure.core/refer (so you also get the possibility of using :exclude etc like with clojure.core/refer). Both are recommended for use in ns rather than directly.
It's idiomatic to include external functions with require and refer. You avoid namespace conflicts, you only include functions you actually use/need, and you explicitly declare each function's location:
(ns project.core
(:require [ring.middleware.reload :refer [wrap-reload]]))
I do not have to invoke this function by prefixing it with its namespace:
(wrap-reload) ; works
If you don't use refer you'll need to prefix it with the namespace:
(ring.middleware.reload/wrap-reload) ; works if you don't use refer in your require
If you choose use instead, (pretty much) always use only:
(ns project.core
(:use [ring.middleware.reload :only [wrap-reload]]))
Otherwise you're including everything, making it both an unnecessarily large operation and very confusing for other programmers to find where the functions live.
Also, I highly recommend this blog as a resource for learning more about Clojure namespaces.
Use sure does make it easier by not requiring you to spell out the namespace every time you want to call a function though it can also make a mess of things by creating namespace conflicts. A good middle ground between "use" and "require" is to only 'use' the functions from a namespace that you actually use.
for instance:
(use '[clojure-contrib.duck-streams :only (writer reader)])
or even better, specify it at the top of the file in the namespace definition:
(ns com.me.project
(:use [clojure.contrib.test-is :only (deftest is run-tests)]))
As has been mentioned the big difference is that with (require 'foo), you then refer to names in the lib's namespace like so: (foo/bar ...) if you do (use 'foo) then they are now in your current namespace (whatever that may be and provided there are no conflicts) and you can call them like (bar ...).