Is there an equivalent of Common Lisp's *features* in Clojure, so you can detect the OS and other environment configuration? Or do I just go through the Java API for that?
Probably use the Java API. It's easy enough, no sense re-inventing the wheel.
user> (System/getProperty "os.name")
"Linux"
user> (System/getProperty "os.version")
"2.6.36-ARCH"
user> (System/getProperty "os.arch")
"amd64"
To add to Brian Carper's answer, you could easily create a map of system properties via the Java API and bind it to the symbol features:
(def *features* {
:name (System/getProperty "os.name"),
:version (System/getProperty "os.version"),
:arch (System/getProperty "os.arch")})
Which gives you this structure, for example:
{:name "Windows 7", :version "6.1", :arch "x86"}
Then access a property in any one of the following ways:
(:name *features*)
(*features* :name)
(get *features* :name)
Whichever floats your boat.
Other answers are handling how to get the system info from Java pretty well. If you want more help interpreting it, here are some examples of how Terracotta did that:
VendorVmSignature
VmVersion
Vm
Related
I am trying to use AWS Amplify Authentication lib in a re-frame app.
The lib provides a higher order component withAuthenticator which is supposed to wrap the main view of your app. I am trying to use reactify-component and adapt-react-class but unfortunately I get the following error:
Uncaught TypeError: Failed to construct ‘HTMLElement’: Please use the ‘new’ operator, this DOM object constructor cannot be called as a function.
(defn main-panel []
[:div
[:h1 "Hello" ]])
(def root-view
(reagent/adapt-react-class
(withAuthenticator
(reagent/reactify-component main-panel))))
(defn ^:dev/after-load mount-root []
(re-frame/clear-subscription-cache!)
(aws-config/configure)
(re-frame/dispatch-sync [::events/initialize-db])
(reagent/render [root-view]
(.getElementById js/document "app")))
Any help is appreciated
I had this issue with reagent + amplify.
Solved it with 2 changes, but I'm unsure if both are needed
#1 Change output of the google closure compiler to es6 (or higher). Amplify seems to use es6 features that Cannot be polyfilled.
This is for shadow-cljs (shadow-cljs.edn), but this should be possible for other build systems as well.
{:builds {:app {:compiler-options {:output-feature-set :es6}}}}
Disclaimer: I switched to shadow-cljs from lein-cljsbuild since I could not get lein-cljsbuild to respect the configuration for es6 output.
#2 Use functional components.
In reagent 1.0.0-alpha1 and up you can change the compiler to produce functional components by default.
(ns core
(:require
[reagent.core :as r]))
(def functional-compiler (r/create-compiler {:function-components true}))
(r/set-default-compiler! functional-compiler)
There are other ways to make functional components. Check the documentation if you don't like, or can't use, this approach.
Perhaps this is bug in Clojure... my question is...
Why when I create a new JLabel in the code below do I get a ClassNotFoundException while creating the JavaFX Stage but when I don't create the JLabel then the JavaFX Stage is created (and the class is found) just fine?
To reproduce this create a new leiningen project with lein new app class-path-fail and replace core.clj with this code:
(ns class-path-fail.core
(:gen-class)
(:import (javafx.stage Stage)
(javafx.application Platform)
(javax.swing JLabel SwingUtilities)
(javafx.embed.swing JFXPanel)))
(JFXPanel.)
(SwingUtilities/invokeAndWait #(new JLabel "ha"))
(defn simple-fn-will-fail []
(let [form `(fn [] (new Stage))]
(eval form)))
(Platform/runLater #(simple-fn-will-fail))
(defn -main
"I don't do a whole lot ... yet."
[& args]
(println "Hello, World!"))
You can verify this doesn't work by running it... but then... comment out the creation of the JLabel and observe it works!!
I'm using Clojure 1.8.0.
Here's my project.clj:
(defproject class-path-fail "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.8.0"]]
:main ^:skip-aot class-path-fail.core
:target-path "target/%s"
:profiles {:uberjar {:aot :all}})
I discovered that if the first two lines of code are reversed then Stage is found on the classpath and loaded. The new first two lines would look like:
(SwingUtilities/invokeAndWait #(new JLabel "ha"))
(JFXPanel.)
I have run into similar issues (albeit in a different context), and I suspect it is due to the class loader configuration of the JavaFX application thread, not necessarily anything specific to Clojure. See for example this similar question: API works with Java application but not JavaFX and: https://community.oracle.com/thread/2564617?start=0&tstart=0
That said, why are you using so many levels of indirection, and so many different mechanisms for scheduling things to happen in the future? The eval function is rarely needed in normal Clojure code.
The line (Platform/runLater #(simple-fn-will-fail)) can be simplified: there is no need for the anonymous function, because simple-fn-will-fail is already a function taking no arguments. So this line is completely equivalent (and fails in exactly the same way): (Platform/runLater simple-fn-will-fail)
Also, simple-fn-will-fail does not actually try to create a new Stage, it just returns a function that will do that (and that function is discarded, never invoked), so if you were not invoking the compiler by calling eval, this problem would not occur.
If we can step back and get a better understanding of what you are actually trying to accomplish, there is probably a way to work around the issues with the class loader on the JavaFX application thread.
Anyway, those are some ideas. Perhaps we will hear more from someone with a deeper understanding of JavaFX and Clojure compilation.
I tinkered a bit more, after making my comment below, and found that even if I pulled the side-effecting forms inside -main, the same exception would be thrown trying to eval the form inside simple-fn-will-fail. So the issue was pointed all the more strongly at the JavaFX class loader.
I was able to get everything to run fine, however, by making sure that compilation occurs on the normal Clojure thread, and then running the resulting function (which, I think, is probably what you wanted to do anyway) using Platform/runLater. Here is my tweaked version:
(ns class-path-fail.core
(:gen-class)
(:import (javafx.stage Stage)
(javafx.application Platform)
(javax.swing JLabel SwingUtilities)
(javafx.embed.swing JFXPanel)))
(defn simple-fn-will-fail []
(let [form `(fn [] (new Stage))]
(eval form)))
(defn -main
"I don't do a whole lot ... yet."
[& args]
(JFXPanel.)
(SwingUtilities/invokeAndWait #(new JLabel "ha"))
(let [stage-creator (simple-fn-will-fail)]
(Platform/runLater stage-creator))
(println "Hello, World!"))
With this version, I can invoke (-main) with no problem.
What is an idiomatic way to handle application configuration in clojure?
So far I use this environment:
;; config.clj
{:k1 "v1"
:k2 2}
;; core.clj
(defn config []
(let [content (slurp "config.clj")]
(binding [*read-eval* false]
(read-string content))))
(defn -main []
(let [config (config)]
...))
Which has many downside:
The path to config.clj might not always be resolved correctly
No clear way to structure config sections for used libraries/frameworks
Not globally accessible (#app/config) (which of course, can be seen as a good functional style way, but makes access to config across source file tedious.
Bigger open-source projects like storm seem to use YAML instead of Clojure and make the config accessible globally via a bit ugly hack: (eval ``(def ~(symbol new-name) (. Config ~(symbol name)))).
First use clojure.edn and in particular clojure.edn/read. E. g.
(use '(clojure.java [io :as io]))
(defn from-edn
[fname]
(with-open [rdr (-> (io/resource fname)
io/reader
java.io.PushbackReader.)]
(clojure.edn/read rdr)))
Regarding the path of config.edn using io/resource is only one way to deal with this. Since you probably want to save an altered config.edn during runtime, you may want to rely on the fact that the path for file readers and writers constructed with an unqualified filename like
(io/reader "where-am-i.edn")
defaults to
(System/getProperty "user.dir")
Considering the fact that you may want to change the config during runtime you could implement a pattern like this
(rough sketch)
;; myapp.userconfig
(def default-config {:k1 "v1"
:k2 2})
(def save-config (partial spit "config.edn"))
(def load-config #(from-edn "config.edn")) ;; see from-edn above
(let [cfg-state (atom (load-config))]
(add-watch cfg-state :cfg-state-watch
(fn [_ _ _ new-state]
(save-config new-state)))
(def get-userconfig #(deref cfg-state))
(def alter-userconfig! (partial swap! cfg-state))
(def reset-userconfig! #(reset! cfg-state default-config)))
Basically this code wraps an atom that is not global and provides set and get access to it. You can read its current state and alter it like atoms with sth. like (alter-userconfig! assoc :k2 3). For global testing, you can reset! the userconfig and also inject various userconfigs into your application (alter-userconfig! (constantly {:k1 300, :k2 212})).
Functions that need userconfig can be written like
(defn do-sth [cfg arg1 arg2 arg3]
...)
And be tested with various configs like default-userconfig, testconfig1,2,3...
Functions that manipulate the userconfig like in a user-panel would use the get/alter..! functions.
Also the above let wraps a watch on the userconfig that automatically updates the .edn file every time userconfig is changed. If you don't want to do this, you could add a save-userconfig! function that spits the atoms content into config.edn. However, you may want to create a way to add more watches to the atom (like re-rendering the GUI after a custom font-size has been changed) which in my opinion would break the mold of the above pattern.
Instead, if you were dealing with a larger application, a better approach would be to define a protocol (with similar functions like in the let block) for userconfig and implement it with various constructors for a file, a database, atom (or whatever you need for testing/different use-scenarios) utilizing reify or defrecord. An instance of this could be passed around in the application and every state-manipulating/io function should use it instead of anything global.
I wouldn't bother even keeping the configuration maps as resources in a separate file (for each environment). Confijulate (https://github.com/bbbates/confijulate , yes - this is a personal project) lets you define all your configuration for each environment within a single namespace, and switch between them via system properties. But if you need to change values on the fly without rebuilding, Confijulate will allow you do that, too.
I've done a fair bit of this over the past month for work. For the cases where passing a config around is not acceptable, then we've used a global config map in an atom. Early on in the application start up, the config var is swap!ed with the loaded config and after that it is left alone. This works in practice because it is effectively immutable for the life of the application. This approach may not work well for libraries, though.
I'm not sure what you mean by "No clear way to structure config sections for used libraries/frameworks". Do you want libraries to have access to the config? Regardless, I created a pipeline of config loaders that is given to the function that setups the config at start up. This allows me to separate config based on library and source.
How can I get the Clojurescript namespace I am in from within a clojurescript program? I want to do this do provide certain debug information (it only needs to work in dev mode)
Namespaces are not first class in ClojureScript as they are in Clojure. There's absolutely no way to get the namespace at runtime. It is possible to get this information at macroexpansion time if you're not afraid of accessing some the ClojureScript compiler internals. There should probably be an API for this - but we're not there yet.
You can get the name of the current namespace with this trick, which takes advantage of :: creating a namespaced symbol for you in the current namespace:
(namespace ::x)
You probably don't want to use that value for anything, because if the code is compiled the internal representation will change. If you want to live dangerously, then in the browser you can then access the js object that holds the namespace like this:
(reduce (fn [ns n] (aget ns n))
js/window
(clojure.string/split (namespace ::x) #"\."))
During macro-expansion you can access &env and retrieve namespace information from the :ns key like this:
(:ns &env)
(:name (:ns &env))
This only works at macro-expansion/compile time and not at runtime.
You can try this
(apply str (drop-last 2 (str `_)))
I've been trying to create a user-defined exception in Clojure, and have been having all sorts of problems. I tried the method outlined here:
http://en.wikibooks.org/wiki/Clojure_Programming/Concepts#User-Defined_Exceptions
(gen-and-load-class 'user.MyException :extends Exception)
But that doesn't seem to work in Clojure 1.2 (or I'm doing something wrong...). My environment is Clojure 1.2, Emacs, and lein swank.
Thanks for your help!
Rather than generating custom classes, there are two much simpler ways to use custom exceptions:
Use slingshot - this provides custom throw+ and catch+ macros that let you throw and catch any object, as well as exceptions.
In clojure 1.4 and above, you can use clojure.core/ex-info and clojure.core/ex-data to generate and catch a clojure.lang.ExceptionInfo class, which wraps a message and a map of data.
Using this is straightforward:
(throw (ex-info "My hovercraft is full of eels"
{:type :python-exception, :cause :eels}))
(try (...)
(catch clojure.lang.ExceptionInfo e
(if (= :eels (-> e ex-data :cause))
(println "beware the shrieking eels!")
(println "???"))))
Or in a midje test:
(fact "should throw some eels"
(...)
=> (throws clojure.lang.ExceptionInfo
#(= :eels (-> % ex-data :cause))))
Make a file src/user/MyException.clj (where src is on CLASSPATH) containing:
(ns user.MyException
(:gen-class :extends java.lang.Exception))
Check the value of *compile-path* at the REPL. Make sure this directory exists and is on CLASSPATH. Create the directory if it doesn't exist; Clojure won't do so for you.
user> *compile-path*
"/home/user/foo/target/classes/"
user> (System/getProperty "java.class.path")
".......:/home/user/foo/target/classes/:......."
Compile your class:
user> (compile 'user.MyException)
user.MyException
If it worked, in *compile-path* you should now have files something like this:
/home/user/foo/target/
/home/user/foo/target/classes
/home/user/foo/target/classes/user
/home/user/foo/target/classes/user/MyException.class
/home/user/foo/target/classes/user/MyException__init.class
/home/user/foo/target/classes/user/MyException$loading__4410__auto__.class
Restart your Clojure REPL / JVM to load these classes. Again, make sure these new class files are on CLASSPATH. Now you should be able to use your class:
user> (user.MyException.)
#<MyException user.MyException>
FWIW, unless you are creating a custom exception for interop reasons you may want to consider using clojure.contrib.condition instead. It comes with a precompiled custom exception that you piggy-back custom data onto using it's API. I've been able to avoid creating many custom exceptions by using it instead. The docs are here:
http://clojure.github.com/clojure-contrib/condition-api.html