correct clojure binding of java instances to Vars - clojure

I'm binding an instance to a Var:
(ns org.jb
(:import (java.awt PopupMenu
TrayIcon
Toolkit
SystemTray)
(javax.swing JFrame
Action)))
(def ^:dynamic popupmenu)
(def ^:dynamic image)
(def ^:dynamic trayicon)
(def ^:dynamic tray)
(defn start-app [appname icon]
(binding [popupmenu (new PopupMenu)
image (.. Toolkit (getDefaultToolkit) (getImage icon))
trayicon (new TrayIcon image appname popupmenu)
tray (. SystemTray getSystemTray)]
(. trayicon setImageAutoSize true)
(. tray add trayicon)))
(start-app "escap" "res/escap_icon.png")
Error:
ClassCastException clojure.lang.Var$Unbound cannot be cast to java.awt.Image org.jb/start-app (org\jb.clj:17)
I am predefining the Var with
(def image)
even tried
(def ^:dynamic image)
Unable to understand what is expected from the message.
Using let in place of binding works within the lexical scope however. However want to achieve dynamic binding.

All I see here is an empty binding form with no code. The variable binding goes out of scope once you leave the binding form. Based on your error message, it looks like you're trying to use the image var outside of the binding form. You need to make sure that all code that uses image is placed inside the binding.
So, instead of this:
(binding [*image* (.. Toolkit (getDefaultToolkit) (getImage "icon.png"))])
(display-image *image*)
Do this:
(binding [*image* (.. Toolkit (getDefaultToolkit) (getImage "icon.png"))]
(display-image *image*))
Another possible issue is that the binding expressions are evaluated in parallel whereas expressions in let are evaluated in sequence. This means that if you're binding multiple vars and one depends on the other, it will use the value that was in scope before the binding was evaluated.
So, this will throw an exception:
(def ^:dynamic *a*)
(def ^:dynamic *b*)
(binding [*a* 2
*b* (+ *a* 3)]
(+ *a* *b*)) ; => ClassCastException clojure.lang.Var$Unbound cannot be cast
; to java.lang.Number clojure.lang.Numbers.multiply
; (Numbers.java:146)
Instead you would have to use nested binding forms:
(binding [*a* 2]
(binding [*b* (+ *a* 3)]
(+ *a* *b*))) ; => 8
Note that I've placed "earmuffs" around the var name. This is the naming convention for dynamic vars in Clojure, so other people can easily tell that it's dynamic. Also, if you're able to dynamically bind a var without declaring it with ^:dynamic metadata, that means you're using a pretty old version of Clojure. I'd suggest you upgrade - 1.5.1 is the latest stable release.

There is no point using binding in your example. You should use binding only when you want to rebind global variable to create some context. In your case you don't need global variables, so you should use let instead:
(ns org.jb
(:import (java.awt PopupMenu
TrayIcon
Toolkit
SystemTray)
(javax.swing JFrame
Action)))
(defn start-app [appname icon]
(let [popupmenu (new PopupMenu)
image (.. Toolkit (getDefaultToolkit) (getImage icon))
trayicon (new TrayIcon image appname popupmenu)
tray (. SystemTray getSystemTray)]
(. trayicon setImageAutoSize true)
(. tray add trayicon)))
(start-app "escap" "res/escap_icon.png")
But if you'll decide to stick with binding then Alex's answer shuld help you with your problem.
But you should avoid using things like binding unless they are absolutely necessary.
Update
If your goal is to save some state for future calculations then binding won't be able to help you. It only binds variables with new values inside its body, leaving them intact for the rest of your app.
So, when you want to change a global state you should use alter-var-root instead:
(def ^:dynamic *app-state* {})
(defn set-state! [new-state]
(alter-var-root #'*app-state* (constantly new-state)))
(defn update-state! [mixin]
(alter-var-root #'*app-state* merge mixin))
You should also try to keep the most of your functions as close to "functional paradigm" as you can:
(defn start-app
"Creates new app with given appname and icon and returns it"
[appname icon]
(let [popupmenu (new PopupMenu)
image (.. Toolkit (getDefaultToolkit) (getImage icon))
trayicon (new TrayIcon image appname popupmenu)
tray (. SystemTray getSystemTray)]
(. trayicon setImageAutoSize true)
(. tray add trayicon)
{ :popupmenu popupmenu
:image image
:trayicon trayicon
:tray }))
(update-state! (start-app "escap" "res/escap_icon.png"))

Related

Casting DynamicLabel to Label in Clojure for Neo4j Embedded

I am trying to rewrite the neo4j sample code located here in clojure. But when I try to create a node, I get the following error
ClassCastException Cannot cast org.neo4j.graphdb.DynamicLabel to [Lorg.neo4j.graphdb.Label; java.lang.Class.cast (Class.java:3094)
Here is my code:
(ns neotest.handler
(:import (org.neo4j.graphdb
DynamicLabel
GraphDatabaseService
Label
Node
ResourceIterator
Transaction
factory.GraphDatabaseFactory
schema.IndexDefinition
schema.Schema)))
(def db
(let [path "C:\\Users\\xxx\\code\\neotest\\resources\\db1"]
(. (new GraphDatabaseFactory) (newEmbeddedDatabase path))))
(defn create-node []
(try (let [tx (. db beginTx)
l (. DynamicLabel (label "User"))]
(. db (createNode l))
(. tx success))))
I have tried type-hinting of all kinds and in all places, and I still get the same error.
It's because of the varargs Label... parameter. This was a bit of Clojure/Java interop I didn't know about: you have to pass the parameter in as an array (even if there's only one), so you need to do something like:
(. db (createNode (into-array Label [l])))
to make it work. There's another afternoon I won't be getting back!
the calls to dynamicLabel in the example java code look like:
DynamicLabel.label( "User" )
which would translate to:
(DynamicLabel/label "user")
because label is a static method of the class org.neo4j.graphdb.DynamicLabel which has the signature:
static Label label(String labelName)

clojure gen-class generated classes invocation issue

I defined the following MyCache.clj
(ns abcd.MyCache
(:gen-class
:name "abcd.MyCache"
:init "init"
:constructors { [java.text.DateFormat][] }
:methods [ [now [] void] [myformat [long] String] ]
:state "state"
:main false))
(defn -init[format]
([[] (atom {:format format})]))
(defn -now[this] ( (:format #(.state this)) (System/currentTimeMillis)))
(defn -myformat[this time]
( (:format #(.state this) (new java.util.Date time))))
I compiled the above file using (compile 'abcd.MyCache) successfully.
When I am trying to use the generated classes as shown below..I am getting errors. Please help.
user=> (new abcd.MyCache (new java.text.SimpleDateFormat "mmDDyyyy"))
IllegalArgumentException Key must be integer clojure.lang.APersistentVector.invoke (APersistentVector.java:265)
I don't feel well about this:
(defn -init[format]
([] [atom {:format format}]))
You are trying to get an element from a vector and it is expects an index (number).
What is correct is to deref the atom and get its value as the index of the vector. But again in your case, you are trying to query an empty vector.
Notice also, that [atom {:format format}] isn't the correct way to create an atom. You should use:
(atom {:format format})
And by the way, the following form is the preferred one to create Java objects (nothing wrong with (new) of course):
(Date.)
(DateFormat.)

How do you explicitly specify a namespace when using "apply" on a function in Clojure?

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.

Clojure Agent question - using send-off

I have a couple of questions about the following code:
(import
'(java.awt Color Graphics Dimension)
'(java.awt.image BufferedImage)
'(javax.swing JPanel JFrame))
(def width 900)
(def height 600)
(defn render
[g]
(let [img (new BufferedImage width height
(. BufferedImage TYPE_INT_ARGB))
bg (. img (getGraphics))]
(doto bg
(.setColor (. Color white))
(.fillRect 0 0 (. img (getWidth)) (. img (getHeight)))
(.setColor (. Color red))
(.drawOval 200 200 (rand-int 100) (rand-int 50)))
(. g (drawImage img 0 0 nil))
(. bg (dispose))
))
(def panel (doto (proxy [JPanel] []
(paint [g] (render g)))
(.setPreferredSize (new Dimension
width
height))))
(def frame (doto (new JFrame) (.add panel) .pack .show))
(def animator (agent nil))
(defn animation
[x]
(send-off *agent* #'animation)
(. panel (repaint))
(. Thread (sleep 100)))
(send-off animator animation)
In the animation function - why is #' used before animation in send-off?
Why does send-off at the start of animation function work? Shouldn't it just go the start of animation function again and never execute the repaint and sleep methods?
Is there any disadvantage, as compared to the original, in writing the animation function as:
(defn animation
[x]
(. panel (repaint))
(. Thread (sleep 100))
(send-off *agent* animation))
In the animation function - why is #' used before animation in send-off?
To demonstrate Clojure's dynamic nature.
The form #'animation is a Var, one of Clojure's mutable reference types. The defn macro creates a Var. For convenience, invoking a Var which refers to a function is the same as invoking the function itself. But a Var, unlike a function, can change! We could redefine #'animation at the Clojure REPL and immediately see the effects.
Using (send-off *agent* #'animation) forces Clojure to look up of the current value of the #'animation Var every time. If the code had used (send-off *agent* animation) instead, then Clojure would look up the value only once, and it would not be possible to change the animation function without stopping the loop.
1. This is a little unclear to me as well but seems to be a design decision by Rich. If you notice:
user=> (defn x [y] (+ y 2))
#'user/x
user=> ((var x) 3)
5
If a var is in the function/macro location, it will eventually resolve to the function or macro.
2. One important thing to understand here is the agent model. Agents can be thought of as a worker that operates on a single mutable cell. There is a queue of work (a queue of functions) for that agent to do. send-off and send add work to that queue. Since send-off is only adding work to the queue, it immediately returns. Since the agent only executes the functions serially, the first animation call must finish before executing the next one. Therefore, you achieve basically the same thing regardless of putting send-off first or last.
3. There should be no noticeable difference between the two.

Is this a closure? If so, why?

While preparing an answer to another question, I created one for myself. Consider the following short program.
(ns net.dneclark.JFrameAndTimerDemo
(:import (javax.swing JLabel JButton JPanel JFrame Timer))
(:gen-class))
(defn timer-action [label counter]
(proxy [java.awt.event.ActionListener] []
(actionPerformed
[e]
(.setText label (str "Counter: " (swap! counter inc))))))
(defn timer-fn []
(let [counter (atom 0)
label (JLabel. "Counter: 0")
timer (Timer. 1000 (timer-action label counter))
panel (doto (JPanel.)
(.add label))]
(.start timer)
(doto (JFrame. "Timer App")
(.setContentPane panel)
(.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
(.setLocation 300 300)
(.setSize 200 200)
(.setVisible true))))
(defn -main []
(timer-fn))
In the action listener, 'timer-action', the value of the 'counter' argument is altered. The actual variable is declared in the 'timer-fn' function, but is altered in the listener. In my earlier experience with languages like Pascal, I would have considered 'counter' to be passed by reference. Is that the case here or is this an example of a closure? Something else?
Thanks for the help.
Yes, it's a closure. The lexical context of the handler function definition is preserved, and when it is later invoked it can access and update variables that "live" there.
I'm not sure how to answer the question, "why?" other than to point out that it's simply the way the language is defined to work.