Im lost at how to best translate the following Java code to ideomatic Clojure
var lsClient = new LightstreamerClient(...);
lsClient.connectionDetails.setUser(...);
lsClient.connectionDetails.setPassword(...);
lsClient.addListener(...);
lsClient.connect();
I have tried multiple things and have ended up with something that does not even compile
(defn create-connection-and-subscriptions!
[{:keys [identifier cst token ls-endpoint]} callback]
(let [password (str "CST-" cst "|XST-" token)
client (LightstreamerClient. ls-endpoint nil)
connection-listener (client-listener-adapter/create callback)]
(doseq [c [client]]
(.setPassword (.-connectionDetails c) password)
( .setUser (.-connectionDetails c) identifier)
(.addListener connection-listener c)
(.connect c))
))
How should I change this for things to work as the Java code. OBS ... in java code is just that I have have removed the input.
What you've written is weird (why doseq over a single item?), but should work. I'd replace (doseq [c [client]] with (let [c client] if you want to do it that way, or just rename the existing variable to c.
If you want to avoid re-typing the variable name, then doto is the tool for performing multiple side-effecting effects with the same first argument. It's not super clear that this is worth it for objects you only call two methods on, but you could write
(doto (.-connectionDetails client)
(.setPassword password)
(.setUser identifier))
(doto client
(.addListener connection-listener)
(.connect))
If you are truly devoted to doing it all as one expression with no new variables, and don't mind some labyrinthine macro rewriting, you can write this instead:
(doto (LightstreamerClient. ls-endpoint nil)
(-> (.-connectionDetails)
(doto
(.setPassword password)
(.setUser identifier)))
(.addListener connection-listener)
(.connect))
I find this rather cute, but code should be written to be readable, not cute, so I don't recommend it. You may enjoy puzzling through how it works, though.
Related
I have a list of I/O functions to run in a game, but need to collect the value from a function somewhere in the middle of the do
(defn setup-steps [game-state]
(do (io/clear-screen)
(print-welcome-message)
(initial-setup) ;; value to be collected
(io/clear-screen)
(io/print-board game-state)))
Is there a smart way to return the value from somewhere in the middle of a do?
Down the line, I am using the return value of setup-steps to update an atom, like so:
(defn game-loop [game]
(while (:game-in-progress? #game)
;; Here is where I am using the results
(->> (s-io/setup-steps #game) (state/updater game))
(while (:game-in-progress? #game)
(->> (m-io/turn-steps #game) (state/updater game)))
(->> (eg-io/end-game-steps #game) (state/updater game)))
(eg-io/exit-game))
Where
(defn updater
"Updates the game state.
This is the only place where the game atom is modified."
[game update-params]
(swap! game merge update-params))
I'm sure you could write a macro for this, but I don't really understand macros yet.
And maybe I am thinking about this the wrong way... Is it more idiomatic to dow the swap!ing inside setup-steps?
Any reason you can't assign the result in a let and return it at the end of the function?
(defn setup-steps [game-state]
(io/clear-screen)
(print-welcome-message)
(let [v (initial-setup)] ;; value to be collected
(io/clear-screen)
(io/print-board game-state)
v))
EDIT: Got rid of the redundant do that Ryan Asensio mentioned.
Fundamentally the only way to do this is with let, as clartaq shows. But if you find this distasteful there are a number of ways you could wrap this up in a macro to make it prettier to look at and also more clear about what you're doing. Here is the simplest one, which I like to call returning:
(defmacro returning [x & more]
`(let [x# ~x]
(do ~#more)
x#))
(defn foo []
(x)
(y)
(returning (z)
(a)
(b)))
The do in returning is of course superfluous, but I think it's still useful to emphasize that more is evaluated only for side effects.
I have had an issue with my code due to a very twisted behaviour of a function.
I use google-api to stream data in BigQuery. In Java, you create an object called Bigquery.Tabledata.InsertAll (a request) and then you execute it
TableDataInsertAllResponse response = request.execute();
(sample code from Google)
But as you can see, the execution is something that has side effect while returning a response.
I reproduced it in Clojure (in a chunked fashion)
(defn load-bq
[client project-id dataset-id table-id data & {:keys [chunk-size] :or {chunk-size 500}}]
(let [chunks (partition-all chunk-size data)
_ (str "Now streaming data into table : [" project-id ":" dataset-id "." table-id "]")]
(map (partial atomic-load-bq client project-id dataset-id table-id) chunks)))
If I try to stream in repl, it works fine. But surpinsingly a doall does not work in code like in a let or with a do.
Here a function to illustrate the principle
(def load-this-table
[... data]
(let [_ (doall (load-bq ... data))]
(load-bq ... data)
(do (load-bq ...data))))
Here, nothing will be loaded.
I found a trick that works though it is a bit far-fetched :
(def load-this-table
[... data]
(let [_ (println (load-bq ... data))]
(println (load-bq ... data))))
Here both line will execute. of course i need only one streaming so I chose a single solution here.
How to force evaluation of this code without having to use println ?
I could use what force evaluation behing println or any more general core function.
I have the impression that the difference is not really linked to lazyness but more to a more fundamental difference bewteen Clojure and Java. And maybe that the response have to be "taken" by the client.
Thanks !
I'm still learning this alien functional paradigm...
How would I write the following code in Clojure, and in a functional way?
assume this missing parts are defined elsewhere and behave as described in the comments.
Here it is in Python, which I am familiar with.
usernames = []
# just the usernames of all the connections I want to open.
cancelfunctions = {}
# this global contains anonymous functions to cancel connections, keyed by username
def cancelAll():
for cancel in cancelfunctions.values():
cancel()
def reopenAll():
cancelfunctions = {}
for name in usernames:
# should return a function to close the connection and put it in the dict.
cancelfunctions[name] = openConnection()
All I really need to know is how to build up a new dict of callbacks, like in the reopenAll function, but I'm including some more context here because chances are I'm committing some kind of functional paradigm atrocity, and you will most likely want to fix the whole program. :)
Building data structures in Clojure often involves reduce, which feeds a sequence of inputs to a function which accumulates a final return value. Here are two ways to write a function which constructs a map (i.e. dictionary) of username to the return value of open-connection.
;; Using reduce directly
(defn reopen-all [usernames]
(reduce
(fn [m name] (assoc m name (open-connection)))
{} usernames))
;; Using into, which uses reduce under the hood
(defn reopen-all [usernames]
(into {} (for [name usernames]
[name (open-connection)])))
Note that these two functions return a value and do not mutate global state, as your Python code does. Global state isn't inherently bad, but it's good to separate value-generation from state manipulation. For state, you'll probably want an atom:
(def usernames [...])
(def cancel-fns (atom nil))
(defn init []
(reset! cancel-fns (reopen-all usernames)))
And here's cancel-all for completeness' sake:
(defn cancel-all []
(doseq [cancel-fn (vals #canel-fns)]
(cancel-fn)))
Here's a functional approach in python:
def reopen(usernames):
return dict((name, openConnection()) for name in usernames)
You may find it easier to "translate" to a functional style in python before attempting to use a primarily functional language.
I have an incoming lazy stream lines from a file I'm reading with tail-seq (to contrib - now!) and I want to process those lines one after one with several "listener-functions" that takes action depending on re-seq-hits (or other things) in the lines.
I tried the following:
(defn info-listener [logstr]
(if (re-seq #"INFO" logstr) (println "Got an INFO-statement")))
(defn debug-listener [logstr]
(if (re-seq #"DEBUG" logstr) (println "Got a DEBUG-statement")))
(doseq [line (tail-seq "/var/log/any/java.log")]
(do (info-listener logstr)
(debug-listener logstr)))
and it works as expected. However, there is a LOT of code-duplication and other sins in the code, and it's boring to update the code.
One important step seems to be to apply many functions to one argument, ie
(listen-line line '(info-listener debug-listener))
and use that instead of the boring and error prone do-statement.
I've tried the following seemingly clever approach:
(defn listen-line [logstr listener-collection]
(map #(% logstr) listener-collection))
but this only renders
(nil) (nil)
there is lazyiness or first class functions biting me for sure, but where do I put the apply?
I'm also open to a radically different approach to the problem, but this seems to be a quite sane way to start with. Macros/multi methods seems to be overkill/wrong for now.
Making a single function out of a group of functions to be called with the same argument can be done with the core function juxt:
=>(def juxted-fn (juxt identity str (partial / 100)))
=>(juxted-fn 50)
[50 "50" 2]
Combining juxt with partial can be very useful:
(defn listener [re message logstr]
(if (re-seq re logstr) (println message)))
(def juxted-listener
(apply juxt (map (fn [[re message]] (partial listner re message))
[[#"INFO","Got INFO"],
[#"DEBUG", "Got DEBUG"]]))
(doseq [logstr ["INFO statement", "OTHER statement", "DEBUG statement"]]
(juxted-listener logstr))
You need to change
(listen-line line '(info-listener debug-listener))
to
(listen-line line [info-listener debug-listener])
In the first version, listen-line ends up using the symbols info-listener and debug-listener themselves as functions because of the quoting. Symbols implement clojure.lang.IFn (the interface behind Clojure function invocation) like keywords do, i.e. they look themselves up in a map-like argument (actually a clojure.lang.ILookup) and return nil if applied to something which is not a map.
Also note that you need to wrap the body of listen-line in dorun to ensure it actually gets executed (as map returns a lazy sequence). Better yet, switch to doseq:
(defn listen-line [logstr listener-collection]
(doseq [listener listener-collection]
(listener logstr)))
(use '[clojure.contrib.trace])
(dotrace [str] (reduce str [\a \b]))
In a nutshell:
That's because trace-fn-call, which is the thing dotrace uses to wrap the functions to be traced, uses str to produce the nice TRACE foo => val output.
Extended explanation:
The dotrace macro does its magic by installing a thread binding for each Var holding a function to be traced; in this case, there is one such Var, clojure.core/str. The replacement looks roughly like so:
(let [f ##'str]
(fn [& args]
(trace-fn-call 'str f args)))
The trace-fn-call, to quote its docstring, "Traces a single call to a function f with args.". In doing so, it calls the traced function, takes note of the return value, prints out a nice informative message of the form TRACE foo => val and returns the value obtained from the traced function so that regular execution may continue.
As mentioned above, this TRACE foo => val message is produced used str; however, in the case at hand, this is actually the function being traced, so a call to it leads to another call to trace-fn-call, which makes its own attempt to produce the tracing output string using str, which leads to another call to trace-fn-call... ultimately leading to the stack blowing up.
A workaround:
The following modified versions of dotrace and trace-fn-call should work fine even in the presence of weird bindings for core Vars (note that futures may not be scheduled promptly; if that's a problem, see below):
(defn my-trace-fn-call
"Traces a single call to a function f with args. 'name' is the
symbol name of the function."
[name f args]
(let [id (gensym "t")]
#(future (tracer id (str (trace-indent) (pr-str (cons name args)))))
(let [value (binding [*trace-depth* (inc *trace-depth*)]
(apply f args))]
#(future (tracer id (str (trace-indent) "=> " (pr-str value))))
value)))
(defmacro my-dotrace
"Given a sequence of function identifiers, evaluate the body
expressions in an environment in which the identifiers are bound to
the traced functions. Does not work on inlined functions,
such as clojure.core/+"
[fnames & exprs]
`(binding [~#(interleave fnames
(for [fname fnames]
`(let [f# #(var ~fname)]
(fn [& args#]
(my-trace-fn-call '~fname f# args#)))))]
~#exprs))
(Rebinding trace-fn-call around a regular dotrace apparently doesn't work; my guess is that's because of clojure.* Var calls still being hard-wired by the compiler, but that's a separate matter. The above will work, anyway.)
An alternative would be to use the above my-dotrace macro together with a my-trace-fn-call function not using futures, but modified to call custom replacements for the clojure.contrib.trace functions using the following in place of str:
(defn my-str [& args] (apply (.getRoot #'clojure.core/str) args))
The replacements are straightforward and tedious and I omit them from the answer.