Dynamically computing gen-class - clojure

Clojure's java interop is good but often bridging between an object oriented java API (especially one requiring subclassing, annotations, and state) and clojure code is awkward. To make this easier, I had a thought to try to provide a wrapper such that I could write something like this:
(component "Foo"
(handler "bar"))
and by implementing component and handler as macros I could return something uglier but correct like:
(gen-class
[component-name]
:name ^{Component {}} (str "com.foobar." component-name)
:implements [com.foobar.api.SomeInterface]
:main false
:constructors {[com.foobar.data.SomeData]} []}
...
However, while it appears that my component macro would expand to the code above, gen-class appears to be a special form that is sought during compilation and parsed without evaluating its "child forms". This means that forms like (str "com.foobar." component-name) are not evaluated and the generated class is actually ./(str "com/foobar/" name).class
Is there anyway I can create a little DSL to generate java classes like this?

Related

How do I abstract away implementation details in Clojure?

I'd like to hide the details of my persistence layer behind some sort of interface. In Java I would just create an interface and choose the correct implementation in some sort of bootup function. I'm still struggling on how to do that in Clojure. I don't necessarily need any type-safety here, I trust in my unit tests to find any issues there. The best thing I could come up with was to create a map containing anonymous functions with specific keys, like so:
(def crux-db {
:get-by-id (fn [id] (get-obj...))
:save (fn [id obj] (store-obj...))
})
(def fs-db {
:get-by-id (fn [id] (get-obj...))
:save (fn [id obj] (store-obj...))
})
If I'm not missing something, this would allow me to replace the database implementation by def-ing (def db crux-db) or (def db fs-db), as long as all the functions exist in all implementation maps. Somehow I feel like this is not the clojure way but I can't put my finger on it. Is there another way to do this?
Protocols are a way to do that. They let you define what functions should be there. And
you can later implement them for different things with e.g.
a defrecord.
A protocol is a named set of named methods and their signatures, defined using defprotocol:
(defprotocol AProtocol
"A doc string for AProtocol abstraction"
(bar [a b] "bar docs")
(baz [a] [a b] [a b c] "baz docs"))
No implementations are provided
Docs can be specified for the protocol and the functions
The above yields a set of polymorphic functions and a protocol object
all are namespace-qualified by the namespace enclosing the definition
The resulting functions dispatch on the type of their first argument, and thus must have at least one argument
defprotocol is dynamic, and does not require AOT compilation
defprotocol will automatically generate a corresponding interface, with the same name as the protocol, e.g. given a protocol my.ns/Protocol, an interface my.ns.Protocol. The interface will have methods corresponding to the protocol functions, and the protocol will automatically work with instances of the interface.
Since you mentioned crux in your code, you can have a peek at how they
use it
here
and then using defrecords to implement some of
them
There are several ways to achieve this. One way would be to use protocols. The other way would be to just use higher-order functions, where you would "inject" the specific function and expose it like so:
(defn get-by-id-wrapper [implementation]
(fn [id]
(implementation id)
...))
(defn cruxdb-get-by-id [id]
...)
(def get-by-id (get-by-id-wrapper cruxdb-get-by-id))
Also worth mentioning here are libraries like component or integrant which are used to manage the lifecylce of state.

What is reify in Clojure?

I could not understand the usage of reify function in Clojure.
What is it used for in clojure?
Could you provide examples?
reify is to defrecord what fn is to defn.
"Ah right...... so what's reify"
Put simply, protocols are lists of functions a datatype should support, records are datatypes and reifications are anonymous datatypes.
Maybe this is long-winded, but reify can't be understood concretely without understanding protocols and types/records: Protocols are a way to use the same name for a function such as conj that actually acts differently when given different arguments ((conj [:b :c] :a) => [:b :c :a] but (conj '(:b :c) :a) => (:a :b :c)). Records are like objects or types (but they act like maps making them awesomer).
More fundamentally, the goal is to solve "The Expression Problem" that is to have the ability to seamlessly add new types of data that work with existing functions, and new functions that work seamlessly with existing data.
So one day you say to yourself, "Self, you should learn what it means to be a duck!" so you write a protocol:
(defprotocol Quacks
(quack [_] "should say something in ducky fashion"))
But it's all too abstract so you 'realify' it:
(def donald (reify Quacks
(quack [_] "Quacks and says I'm Donald")))
Now at last you can experience your creation:
(quack donald) => "Quacks and says I'm Donald"
Then you remember about Daffy:
(def daffy (reify Quacks
(quack [_] (str "Quacks and says I'm Daffy"))))
(quack daffy) => "Quacks and says I'm Daffy"
But by the time you remember about Huey, you realize your mistake and define what a duck is in a reusable way:
(defrecord Duck [name]
Quacks
(quack [_] (str "Quacks and says I'm " name)))
And make new ducks (there are several ways to do it):
(def huey (->Duck "Huey"))
(def duey (Duck. "Duey"))
(def louie (new Duck "Louie"))
(quack huey) => "Quacks and says I'm Huey"
Remember that records act like maps (thank to protocols!):
(:name huey) => "Huey"
But then you remember that ducks must quack and walk so you write another protocol:
(defprotocol Walks
(walk [_] "should walk like a duck"))
And extend the definition of duck
(extend-type Duck
Walks
(walk [_] "waddle waddle"))
(walk louie) => "waddle waddle"
Now we can extend other types to implement the same protocol (teach the same function how to work with other things):
So let's say we want programmers to quack too :-)
(defrecord Programmer [] Quacks
(quack [_] "Monads are simply monoids in a category of endofunctors..."))
(quack (Programmer.)) => "Monads are simply monoids in a category of endofunctors..."
I recommend this great explanation of protocols, an explanation of reify and a chapter on protocols in "Clojure for the Brave and True".
Disclaimer: This is only meant to give an initial understanding of what protocols are, not best practices on how to use them. "Psst! I answered this question largely to teach myself, because until yesterday I had never actually written my own protocol/interface!"
So while I hope that it enhances someone else's learning, I'll heartily welcome criticism or edit-suggestions!".
reify macro allow to create an anonymous class extending java.lang.Object class and/or implementing specified interfaces/protocols. The API docs don't describe the purpose clearly but rather provide the technical details what that macro does. Java interop documentation provides a brief description of the purpose:
As of Clojure 1.2, reify is also available for implementing
interfaces.
Even more information can be found in datatypes documentation where you can find a very detailed description what it does and how it compares to proxy:
While deftype and defrecord define named types, reify defines both an
anonymous type and creates an instance of that type. The use case is
where you need a one-off implementation of one or more protocols or
interfaces and would like to take advantage of the local context. In
this respect it is use case similar to proxy, or anonymous inner
classes in Java.
The method bodies of reify are lexical closures, and can refer to the
surrounding local scope. reify differs from proxy in that:
Only protocols or interfaces are supported, no concrete superclass.
The method bodies are true methods of the resulting class, not
external fns. Invocation of methods on the instance is direct, not
using map lookup. No support for dynamic swapping of methods in the
method map. The result is better performance than proxy, both in
construction and invocation. reify is preferable to proxy in all cases
where its constraints are not prohibitive.

How to have clojure support related values in binding?

I am using binding as a means to make it easier to pass around state within a call. I currently have something like the following
(binding [*private-key-path* "/Users/dcapwell/.ssh/id_dsa"]
(binding [*session* (session "localhost")]
...
The reason that I need to do this is that the session function requires private-key-path to be defined. Since binding doesn't allow related values, is there any simpler way to do the above without the needed nesting?
EDIT:
Currently prototyping using clj-ssh.ssh. The plan is to make most of my current usage of binding to be a static config (most are static values already, so read once on boot). Was using binding as a way to make prototyping easier so I didn't have to keep passing things around while seeing how the API worked.
I was just curios how I can get the bindings to be dependent on each other. When I use let, the second binding has access to the first one, but it seems that when I do this that the second binding doesn't have access to the first. I would assume there would be another function that acts like binding but would allow the second binding to have access to the first. I can also see this not existing in the default since its more of state than anything else.
Edited: some experiment in the REPL
(def ^:dynamic *a* "a not bound")
(def ^:dynamic *b* "b not bound")
(defn show-a! []
*a*)
(binding [*a* 1 *b* (show-a!)] *b*) ;; => "a not bound"
(binding [*a* 1]
(binding [*b* (show-a!)]
*b*)) ;; => 1
I was surprised to know the given code is NOT the same as:
(binding [*private-key-path* "/Users/dcapwell/.ssh/id_dsa"
*session* (session "localhost")]
...)
so Clojure tends to have less parentheses than other Lisps in let forms cases but not binding.
Please think about your overall code (and/or API design?) again and again. Dynamic bindings are bad. You will suffer soon. Tip: make more and more code unit-testable.
I'm not sure what you are trying to do, so I recommend this:
A feature called "Graph" for structural computation. Never worry about dependencies between functions again!
https://github.com/Prismatic/plumbing

How to get an Fn which calls a Java method?

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.

Clojure multimethods global hierarchy

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.