There is alter-var-root in clojure. Why there isn't it in cljs?
Clojurescript doesn't have vars. They're just globals you can set! like any other object property.
Related
I would like to understand difference between with-redefs and with-redefs-fn.
Concrete examples would be great to understand the fns behaviours.
They're basically the same, the main difference is that with-redefs lets you write out the body explicitly (like in a let), while with-redefs-fn requires a function as the argument, so you may need to wrap what you want in a lambda. Additionally, with-redefs lets you provide bindings using a vector (again, like let), while with-redefs-fn wants a map. I'd argue that both of these differences are just superficial.
e.g.
(with-redefs [http/post (fn [url] {:body "Goodbye world"})]
(is (= {:body "Goodbye world"} (http/post "http://service.com/greet"))))
vs
(with-redefs-fn {#'http/post (fn [url] {:body "Goodbye world"})}
(fn [] (is (= {:body "Goodbye world"} (http/post "http://service.com/greet")))))
In fact, with-redefs is defined in terms of with-redefs-fn, and basically just wraps the body in an anonymous function before passing everything to with-redefs-fn: https://github.com/clojure/clojure/blob/e3c4d2e8c7538cfda40accd5c410a584495cb357/src/clj/clojure/core.clj#L7404
I would ignore with-redefs-fn and use only with-redefs since it is simpler and has the same abilities. Also, beware that the notation #'http/post requires you to use the var for http/post, not the function itself.
For a description of how a Clojure var works, please see this question: When to use a Var instead of a function? It is similar to a C pointer.
In clojure, when you see foo, it is a symbol. When you see #'foo, it is a shortcut for (var foo) which is a "special form" (i.e. a Clojure built-in, not a regular function), which returns the var that foo points to. The var in turn points the the value of foo.
I wish to know what is the idiomatic way to achieve data encapsulation
in Clojure. Below I describe my particular use case to motivate the example
code I provide.
I have code in a dbaccess module that performs a complex
database query to fetch some
data from a database. I also have a number of functions that operate
on the returned, raw, data. These functions then provide more
processed, refined views of the data and are invoked numerous
times with different arguments from
other modules in the system. Let's call them "API functions".
The query is heavy and should execute only once at the beginning,
the API functions will then operate on the raw-data
from memory without having to perform another DB query.
Here's my approach using closures:
dbaccess module
(ns dbaccess)
(let
[raw-data (complex-database-query)]
(defn create-client-names []
(fn [some-args] raw-data))
(defn create-client-portfolio []
(fn [some-args] raw-data))
(defn create-client-stocks []
(fn [some-args] raw-data)))
some other client module
(def client-names (create-client-names))
(doall (map println (client-names "Baltimore")))
I dislike having to name the created functions that have
captured the raw-data.
More importantly, the code above doesn't allow
the client modules to configure aspects of the query before it executes
(e.g. the database connection information).
If, on the other hand, closures are not used I will have to
explicitly pass the raw-data
back and forth between the dbaccess module and the other modules that need to invoke API functions.
Is there a better way? Should I perhaps use mutable state in the dbaccess module?
I will have to explicitly pass the raw-data back and forth between the
dbaccess module and the other modules that need to invoke API
functions
You should do this, pass the data the function need explicitly, because:
This will lead to loose coupling between how the data is created and how it is processed.
Functions will be more clear to understand while reading it.
Testing of the individual function will be easy as you can mock data easily.
I guess you don't need let in this case:
(def ^:private raw-data (promise))
(future (deliver raw-date (complex-database-query))) ;; A. Webb mentioned this
(defn create-client-names []
(fn [some-args] #raw-data))
...
Why aren't create-client-names and other functions just
(defn create-client-names [some-args]
#raw-data)
...
?
And IMO It's better to use doseq instead of map if there is imperative body:
(doseq [name (client-names "Baltimore")]
(println name))
I'm learning Clojure. I wrote this code to recursively walk a directory.
(tree-seq #(.isDirectory %1) #(.listFiles %1) (File. "/my-directory"))
Why can't I use .isDirectory as a first-class function in Clojure? Is there a better way to rewrite this code?
Joost is spot on about Java methods not being first class functions.
As an approach to dealing with this, I usually like to wrap Java functions in a Clojure function (or find a library that does this already), then it is easy to use them in an idiomatic first-class way:
(defn directory? [^java.io.File file]
(.isDirectory file))
(defn list-files [^java.io.File file]
(.listFiles %1))
(tree-seq directory? list-files (File. "/my-directory"))
This is a few more lines of code, but has the following advantages:
You can add type hints in your functions to avoid reflection (as above)
The final code is cleaner and more idiomatic
You have abstracted away from the underlying Java interop
Java methods aren't clojure functions because you can't call a method on its own; you have to call a method on an object, and it has to be an object of the type that the method expects. In other words, in java, a method cannot be fully separated from its defining class (at least not efficiently).
An alternative to #(.foo %) would be (memfn foo), which hardly anyone uses anymore after #(...) was introduced.
You could have a look at the sourcecode of file-seq (which uses a tree-seq) to see how it works.
By the way: your code works perfectly well for me. I just have to use java.io.File instead of File in the REPL so it knows the Java class.
You've already been given the correct answers, but just to add a bit more Clojure idiomatic code, I'd also use
#(.foo %)
as Joost Diepenmaat did (yet I believed it might've been overlooked).
I would also suggest reading Listing files in a directory in Clojure.
In the docs it says
All of the examples above use the global hierarchy used by the multimethod system
What is the global hierarchy ?
Check out core.clj and look for (def ^{:private true} global-hierarchy (make-hierarchy)). The doc string for make-hierarchy says
"Creates a hierarchy object for use with derive, isa? etc."
The relationship of this with multimethod system can be find out by doing a macroexpand on defmulti which results in a call to clojure.lang.MultiFn constructor with the method name as string and also the var #'clojure.core/global-hierarchy. You can look into clojure.lang.MultiFn source if you want but that is "under the hood" of multimethods.
I wish to make a clojure deftype which implements Clojure Hashmaps. I realise that I can implement the Clojure Interfaces to make my deftype Hashable and Sequable, but what do I need to include to get my deftype to play nice with the Clojure STM so that I can do:
(def a (ref (MyType.)))
and then to perform dosync operations such as conj and cons in an STM safe manner?
You problem is allready solved by records they are what you describe a type/class but with interfaces like Hashable and Sequable (and more).
You can just put your record in a ref like anyother hashmap. Don't see the problem here.
(def a (ref MyType)) doesn't make much sense because you are putting the class MyType in a ref.
The type that you put into a ref should ideally be an immutable type as the body of dosync should be free of side effects.