I'm learning how to extend Java classes in Clojure, but I don't see a way declare new member variables; I only see a way for methods.
(ns test.aclass
(:gen-class
:methods [[foo [] String]]))
Is there a :members keyword or another way of declaring member variables?
:state name
If supplied, a public final instance field with the given name will be created. You must supply an :init function in order to provide a value for the state. Note that, though final, the state can be a ref or agent, supporting the creation of Java objects with transactional or asynchronous mutation semantics.
There is an example on the website of how it can be used.
I was having some trouble with this too. The example below is not elegant but it's pretty simple for writing dumb little glue classes in Clojure rather than Java. Note all I did for thread safety is to ensure that the field updates are atomic -- I didn't do any other concurrency stuff, and that may make a real difference.
The init method creates the instance variables for the object. The setfield and getfield macros abbreviate the bookkeeping of the atomic update.
(ns #^{:doc "A simple class with instance vars"
:author "David G. Durand"}
com.tizra.example )
(gen-class
:name com.tizra.example.Demo
:state state
:init init
:prefix "-"
:main false
:methods [[setLocation [String] void]
[getLocation [] String]]
)
(defn -init []
"store our fields as a hash"
[[] (atom {:location "default"})])
(defmacro setfield
[this key value]
`(swap! (.state ~this) into {~key ~value}))
(defmacro getfield
[this key]
`(#(.state ~this) ~key))
(defn -setLocation [this ^java.lang.String loc]
(setfield this :location loc))
(defn ^String -getLocation
[this]
(getfield this :location))
You have to compile this, and make sure the stub class produced is on your classpath, and then you can make instances, etc. just like any other java class.
=> (com.tizra.example.Demo.)
#<Demo com.tizra.example.Demo#673a95af>
=> (def ex (com.tizra.example.Demo.))
#'user/ex
=> (.getLocation ex)
"default"
=> (.setLocation ex "time")
nil
=> (.getLocation ex)
"time"
I found the longer summary at this blog quite helpful: http://kotka.de/blog/2010/02/gen-class_how_it_works_and_how_to_use_it.html
The body of a proxy is a lexical closure, so you can just close around whatever variables you need. If, God forbid, you need to mutate them, then close around an atom:
(defn lying-list [init-size]
(let [the-size (atom init-size)]
(proxy [java.util.ArrayList] []
(size [] #the-size)
(remove [idx] (reset! the-size idx), true))))
There's really no need for actual Java fields here.
Related
let suppose, I have var atom-var
(def atom-val (atom []))
Also suppose a standard behaviour of atom:
(swap! atom-val conj {:b "2"})
=> #object[clojure.lang.Atom 0x6500d3fd {:status :ready, :val [{:a "2"}]
(#atom-val)
=> #object[clojure.lang.Atom 0x6500d3fd {:status :ready, :val [{:a "2"}]
I want to create the same behaviour as it would work with nil object, but without actions:
(def atom-val nil)
(swap! atom-val conj "New val")
Of course, I will get a NullPointerException. But I want that nothing happened, supress it. I do not need to write try every time it, I just need the described behavuiour.
I see that swap! is a function, atom is a function, atom returns clojure.lang.IAtom, clojure.lang.IAtom is an interface. I cannot extend interface.
How can I get the described behaviour?
Well, I have a global dynamic variable which is equal to nil
(def ^:dynamic atom-val nil).
Whenever a thread is created (it's ring handler with compojure), I am binding atom-val to
(defn func [handler]
(fn [request]
(binding [atom-val (atom [])]
(handler request)
)
)
So, I have such a form in different functions:
(swap! atom-val conj "New val").
I can run it everywhere lots of times (inside/outside different functions). It's really bad to check every time whether atom-val is null or not. Functions have to make swap!, but sometimes atom-val cannot be initialized properly (when a function makes swap! outside ring handlers, before binding).
So I decided to do it this way: I'd like to extend swap! protocol for Atom and when nil (when atom-val is nil) is passed it mustn't throw NullPointerException.
If you want an atom that does nothing, you can write:
(def noop-atom
(reify clojure.lang.IAtom
(reset [_ _])
(swap [_ _])
(swap [_ _ _])
(swap [_ _ _ _])
(swap [_ _ _ _ _])
(compareAndSet [_ _ _])))
You can then use this atom as the root-value of the dynamic var.
If your goal is to manage state during the lifecycle of a Ring request/response, you can write a custom middleware.
You need to use fnil. See https://clojuredocs.org/clojure.core/fnil
Example:
(def atom-val nil)
(def nil-swap! (fnil swap! (atom [])))
(nil-swap! atom-val conj "New val") => ["New val"]
And don't forget to keep a browser tab open to The Clojure CheatSheet at all times!
So, you want to swap! on a nil? I'm not sure what you meant with actions and doing nothing.
It definitely doesn't make sense (at least to me) to swap! a nil value; if it does to you, you should review what atoms really are. Perhaps you mean that when given a nil instead of an atom reference the swap! wouldn't do anything.
If so then you can just make your own function to do that check for you:
(defn nilable-swap!
[a f]
(when a (swap! a f)))
But I really don't recommend you do that, if this is what you want to do, it's an indication of bad design and control flow. Of course, it does make sense to check if your atom reference is nil if you're not sure, but do you really need to routinely check that? is there truly no point in which you know you got your atom reference?
I think I might have answered your question but if I misunderstood, feel free to clarify and I'll update/delete the answer.
I'm new to Clojure and I've been messed up with ^ in Clojure
I'm currently reading clojure code of Jepsen which is used to test the consistency of distributed database.
You can find the code here.
In row 50 there is a ^MongoDatabase. Or:
(defn ^MongoCollection collection
"Gets a Mongo collection from a DB."
[^MongoDatabase db collection-name]
(.getCollection db collection-name))
I have no idea what it is because ^MongoDatabase or MongoCollection is never used in this function.
Can anyone give me some help. Thanks a lot.
In this context, that's a type hint saying collection should return a MongoCollection instance and db arg should be a MongoDatabase instance. This is useful for performance reasons, to avoid unnecessary reflection.
See this guide for more.
Another use of ^ is for type hints. These are used to tell the compiler what type the value will be and allow it to perform type specific optimizations thus potentially making resultant code faster:
The cap symbol ^ is used in Clojure for two purposes.
The first one is for type hints. When declaring a function, you may mark arguments' types or the result value as follows:
(defn ^String concat-strings
[^String a ^String b]
(str a b))
Type hints help the compiler to perform some optimizations.
The second option of using cap is when declaring metadata. The metadata might be either a boolean flag or a map. For example:
(def ^:private secret "test")
Now the variable above is marked as private so it won't be available from other namespaces.
Here is a meta-map usage example:
(def ^{:private true
:doc "My super secret password"
:added "product-version"}
secret
"test")
Let's try to read the metadata for that variable:
(meta #'secret)
returns
{:private true,
:doc "My super secret password",
:added "product-version",
:line 70,
:column 7,
:file "*cider-repl localhost*",
:name secret,
:ns #namespace[user]}
Another point to beware of is that type hints can be deceptive (i.e. they have no "enforcement" or "warning" utility):
(defn foo [x]
(type x))
(defn bar [^String x]
(type x))
(foo "abc") => java.lang.String
(foo 123) => java.lang.Long
(bar "abc") => java.lang.String
(bar 123) => java.lang.Long
In general, I would avoid type hints as they are rarely necessary (unless dealing with low-level Java code).
I'm trying to use dire to add hooks to multimethods. The author says it might not work.
Here is an example with a normal function:
(ns mydire.prehook
(:require [dire.core :refer [with-pre-hook!]]))
(defn times [a b]
(* a b))
(with-pre-hook! #'times
"An optional docstring."
(fn [a b] (println "Logging something interesting.")))
(times 21 2) ; => "Logging something interesting."
As you can see, with-pre-hook! is passed (var times) (which is the same as #'times).
The problem is that when calling var for a multimethod I'm getting an exception:
clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol
Is there a way to make this work?
Below is my code sample:
(defmulti get-url identity)
(defmethod get-url :stackoverflow
[site]
"http://stackoverflow.com")
(with-pre-hook! (var (get-method get-url :stackoverflow))
(fn [x] (println "getting url for stackoverflow.")))
var is a macro, it does not evaluate its argument. If you give it a list, it will not evaluate the list, it will reject it, because it's a list and not a symbol.
There is no var to attach to with a specific method, because defmethod does not create a var, it modifies the dispatch of the multimethod it is attached to. The value returned by get-method is a function, not a var.
Having looked at dire, it specifically needs a var to act on, and won't work on a specific method of a multimethod without some amount of redesign. So no, you can't use with-pre-hook on a specific method, though it might work on a multimethod itself (including all of its methods).
Here "graph" is higher-order function that returns a function with config set in its scope:
(ns bulbs.neo4jserver.graph)
(defn out1
"Test func that simply returns out1."
[config]
"out1")
(defn graph
[config]
(fn [func & args]
(apply func config args)))
You create an instance of graph, which can then be used to call other functions and automatically pass in the config arg:
(def g (graph {:root-uri "http://localhost"}))
(g out1)
;; => "out1"
This works; however, if you require/import graph into another namespace, then you have to prefix each function call with the graph namespace:
(ns bulbs.neo4jserver.junk
(:require [bulbs.neo4jserver.graph :as graph]))
(def g (graph/graph {:root-uri "http://localhost"}))
;; would rather do (g out1)
(g graph/out1)
Instead, I want to explicitly specify the namespace in the apply function so that users don't have to:
(defn graph
[config]
(fn [func & args]
;; somehow specify the graph namespace here
(apply func config args)))
What's the best way to do this?
Not a direct answer to your question, but the general pattern you're using is more common: having a single stateful data structure that holds connection parameters (to a database or another server). Most frameworks turn this around: instead of calling your functions from within the function holding your connection parameters as you do, they have functions that accept the connection data structure as a parameter.
For example, given a database connetion conn, a typical, fictional database library could look like this (note: examples are simplified for clarity):
(let [conn (make-db-connection :host .... :user ....)]
(read-from-db conn :user))
While using a library for a messaging framework (say, RabbitMQ) could look like this:
(let [conn (make-amqp-connection :host .... :port ...)]
(send-message conn :my-queue "hello world"))
In both situations, there is a single conn data structure that is used for all subsequent calls to the libraries' functions. In OO languages, you would have a global, stateful object holding the connection (a singleton perhaps in Java land). In Clojure, libraries typically handle this using a with-... macro, that binds a particular connection to a dynamic var which is used internally:
(with-db-connection (make-db-connection ....)
(read-from-db :user ....))
(with-rabbit-connection (make-rabbitmq-connection ....)
(send-message :my-queue "hello world"))
Here's a (fictional) example that implements this pattern. Assume that a connection is a Java object:
;; a var to hold the connection
(def ^:dynamic *current-connection* nil)
(defmacro with-connection [conn & body]
`(binding [*current-connection* ~conn]
~#body))
;; send-msg is using the connection object bound to
;; the *current-connetion* var
(defn send-msg [msg]
(.sendMessage *current-connection* msg))
;; usage:
(with-connection conn
(send-msg "hello world!"))
If you want to be fancy, you could support both patterns (accepting a connection as a parameter or using the bound connection) by defining the send-msg function like this:
(defn send-msg [msg & {:keys [connection]
:or {connection *current-connection*}}]
(.sendMessage connection msg))
;; usage with bound connetion:
(with-connection conn
(send-msg "Hello World!"))
;; usage with explicit connection:
(send-msg "Hello World!"
:connection conn)
This version of send-msg uses the supplied connection, or the bound connection if a connection wasn't specified.
You can pass symbol instead of function and resolve it in graph function:
(defn graph
[config]
(fn [func & args]
(apply (ns-resolve 'bulbs.neo4jserver.graph func) config args)))
And call it:
(ns bulbs.neo4jserver.junk
(:require [bulbs.neo4jserver.graph :as graph]))
(def g (graph/graph {:root-uri "http://localhost"}))
(g 'out1)
But g is not an high-order function any more. It takes symbol, not function. Personally I don't like this approach. Why don't you like specifying namespace? May be you can do what you need with macro too, but I don't know macros well.
EDIT
Don't do it. Use regular functions as explained by #Ankur and #Gert in comments.
This is a follow-up to my earlier question.
I came up with a bizarre object scheme from my reading of Let Over Lambda and can think of no advantages over protocols, but want to get opinions. I am just exploring the use of higher-order functions and encapsulation.
(defn new-person
"Construct a new Person object and return a Map of accessor methods."
[init-first-name init-last-name init-age]
(let [first-name (ref init-first-name)
last-name (ref init-last-name)
age (ref init-age)]
{:get-first-name #(#first-name)
:set-first-name #(dosync (ref-set first-name %1))
:get-last-name #(#last-name)
:set-last-name #(dosync (ref-set last-name %1))
:get-age #(#age)
:set-age #(dosync (ref-set age %1))}))
I can use the object like this:
(def fred (new-person "fred" "flintstone" 42))
and retrieve an accessor method this way:
(fred :get-age)
but I can't figure out how to call the accessor.
The object created is thread-safe since all mutation of "instance" variables occurs in the STM.
UPDATE: New and improved version:
(defn new-person
"Construct a new Person object and return a Map of accessor methods."
[init-first-name init-last-name init-age]
(let [first-name (ref init-first-name)
last-name (ref init-last-name)
age (ref init-age)]
{:first-name
(fn
([] #first-name)
([val] (dosync (ref-set first-name val))))
:last-name
(fn
([] #last-name)
([val] (dosync (ref-set last-name val))))
:age
(fn
([] #age)
([val] (dosync (ref-set age val))))}))
Maybe not a 100 % answer to your question, but would you try to do is not very idiomatic for Clojure. The 'standard' solution would be something like:
(defrecord Person [first-name last-name age])
(def fred (Person. "fred" "flintstone" 42))
(fred :age)
It looks like you are forcing OO mutable state into Clojure 'objects'
Its the same as your follow up question, wrap the form in another set of parenthesis. When an inner form returns a function, its the same as a symbol that returns a function. The rule is the first form in a parenthesis will always be looked up as a special form, macro, or function. You need something like quote to prevent this behavior.
user=> (fred :get-age)
#<user$new_person$fn__531 user$new_person$fn__531#c4afc4>
user=> ((fred :get-age))
42
Its the same as
user=> (let [age-getter (fred :get-age)] (age-getter))
42
Clojure philosophy is NOT to encapsulate access to the record fields themselves. Encapsulation should happen on higher levels, for example in the set of functions that work with that records. See Clojure - datatypes:
Encapsulation of information is folly fields are public, use protocols/interfaces to avoid dependencies