Following code:
(set! (.. e -target -dataset -some-field) "some-value")
is compiled into:
return a.target.dataset.Qh=Yf(b)
some_field is compressed into Qh. And I need it to be exactly some_field.
I understand this is due to compression optimization. But is there a way to hint, or to bypass this behavior?
PS: simple optimization gives the desired output
return a.target.dataset.some_field=cljs.core.name.call(null,b)}
You may also be interested in the cljs-oops library: https://github.com/binaryage/cljs-oops
Then you can say:
(oset! el "innerHTML" "Hi!")
More examples below, and also on the CLJS Cheatsheet:
The problem is that some-field (or is it some_field or someField?) gets simplified to Qh. This is because the compiler does not know that the dataset object has a some-field property.
One solution is to write extern files so that the Google Closure Compiler will know that the given field must not be renamed.
An other solution is to use aset function or call goog.object.set function. This way you reference the field of the object with a string value and the string values do not get simplified.
Second example:
cljs.user=> (def a (clj->js {"a" 1}))
#'cljs.user/a
cljs.user=> a
#js {:a 1}
cljs.user=> (aset a "b" 2)
2
cljs.user=> a
#js {:a 1, :b 2}
Related
I'm trying to create a Clojure function, that returns another function with a custom name. My attempts so far:
(defn function-with-custom-name [name] (fn name [] 42))
(function-with-custom-name "hello")
# --> #object[lang.main$function_with_custom_name$name__4660 0xa6afefa "lang.main$function_with_custom_name$name__4660#a6afefa"]
# syntactically ok, but its name is 'name' and not 'hello'
(defn function-with-custom-name [name] (fn (symbol name) [] 42))
# --> CompilerException java.lang.IllegalArgumentException: Parameter declaration symbol should be a vector, compiling:(/tmp/form-init3365336074265515078.clj:1:40)
(defn function-with-custom-name [name] (fn '(symbol name) [] 42))
# --> CompilerException java.lang.IllegalArgumentException: Parameter declaration quote should be a vector, compiling:(/tmp/form-init3365336074265515078.clj:1:40)
I understand that fn is a macro, and therefore proper quoting is probably important for the parameter, but as per above, I could not get it right, but I'm 99% sure there is a way, since (looking at the source of fn), the only criteria is that the first parameter should be recognized as a symbol.
Any hints on how to do this?
EDIT: Use-case, as asked in the comment: I'm writing a simple language interpreter in Clojure, which (among other things) lets you create functions. The functions from my language are currently represented by anonymous Clojure functions. However, it would make debugging the interpreter much easier, if the Clojure functions also did have a name.
EDIT2: The first edit made me think, and I came to the conclusion that I cannot use macro-based solutions for this problem, since I need to create the functions run-time (and, as far as I remember, macros can only work at compile-time). --> Changed the question title for clarity. Still, please don't delete the macro-based answers, since they give helpful insight.
You can use defmacro.
(defmacro function-with-custom-name [name]
`(fn ~(symbol name) ([] 42)))
you can also do it in runtime, without using macros, using namespace functions instead. It can give you the way to register functions from some input for example (i can't really find any good reason for this though, but maybe it's just me)
user> (defn runtime-defn [f-name f]
(intern (ns-name *ns*) (symbol f-name) f))
#'user/runtime-defn
user> (runtime-defn "my-fun" #(* 100 %))
#'user/my-fun
user> (my-fun 123)
;;=> 12300
user> (runtime-defn (read) #(* 200 %))
#input "danger!!!"
#'user/danger!!!
user> (danger!!! 1)
;;=> 200
Update:
For the simple version, you can use defmacro. For a more complicated version (such as used by the potemkin library) you need to mess around with creating a var and "intern-ing" it into the clojure namespace. This is accomplished via clojure.core/intern:
(ns tst.demo.core
(:use demo.core tupelo.test )
(:require [tupelo.core :as t] ))
(t/refer-tupelo)
(defmacro make-fn-macro-unquote [name]
(spyxx name)
`(defn ~name [] 42))
(defn make-fn-func-quote [name2]
(spyxx name2)
(intern 'tst.demo.core (symbol name2) (fn [] 43)))
(dotest
(make-fn-macro-unquote fred)
(spyxx fred)
(is= 42 (spyx (fred)))
(let [wilma-var (make-fn-func-quote "wilma")]
(spyxx wilma-var)
(is= 43 (spyx (wilma-var)))))
Look at the output:
name => clojure.lang.Symbol->fred
fred => tst.demo.core$fn__38817$fred__38818->#object[tst.demo.core$fn__38817$fred__38818 0x5f832a1 "tst.demo.core$fn__38817$fred__38818#5f832a1"]
(fred) => 42
name2 => java.lang.String->"wilma"
wilma-var => clojure.lang.Var->#'tst.demo.core/wilma
(wilma-var) => 43
Note that fred is a clojure function, while wilma-var is a clojure var. Please see this post on the relationship between a symbol like foo and a var and a function.
Note also that the macro version takes an unquoted symbol fred as input, while the function version takes a plain string in double-quotes as input.
So fred is a symbol pointing to a function, while wilma-var is a symbol pointing to a var (which then points to a function). In either case, Clojure allows us to type (fred) or (wilma-var) to make a function call, and we get either 42 or 43 as a result.
I want to get a list of public functions from another namespace so they can be exposed as commands.
A similar question for Clojure seemed close, but does not seem to work on ClojureScript.
Another question has answers for Clojurescript, but they either only show how to print them to the REPL, or return all members instead of only the publicly exposed ones.
ClojureScript does not have a resolve function. It is possible to mimic the behavior using hacks, e.g., this one:
(defn ->js [var-name]
(-> var-name
(clojure.string/replace #"/" ".")
(clojure.string/replace #"-" "_")))
(defn invoke [function-name & args]
(let [f (js/eval (->js function-name))]
(apply f args)))
The second question you linked has an answer that refers to the clojure.repl/dir function which prints
a sorted directory of public vars in a namespace.
If you can print them, you can turn them into a string with with-out-str.
Now let's assume we have a namespace called demo.core with one public function called add:
(ns demo.core)
(defn add [a b]
(println "hello from add")
(+ a b))
We can retrieve the public fns from demo.core as strings as follows:
(defn public-fns
"Returns coll of names of public fns in demo.core"
[]
(as-> (with-out-str (clojure.repl/dir demo.core)) public-fns
(clojure.string/split public-fns #"\n")
(map (fn [s] (str "demo.core/" s)) public-fns)))
So with with-out-str we turn them into a list of strings, then split on newline, then prepend the names of public functions with "demo.core".
Then, using our earlier created invoke function, we can obtain add and invoke it with the arguments 1 and 2:
(invoke (first (public-fns)) 1 2)
;; "hello from add"
;; => 3
This is all very hacky, and it might break in advanced compilation, but it works.
Post updated to make it relevant to the course of events (responses and eliminating clutter).
Thank you very much for your time and help !
In some previous version of Clojure every var could be bound with a "binding" form.
Nowadays you get "Can't dynamically bind non-dynamic var" if not defined as dynamic.
In some contexts making a function var dynamic after definition could be useful (stubbing/mocking in testing).
Don't try:
(def ^{:dynamic true} log-call #'log-call)
It will eventually cause StackOverflowError since you are defining a function that calls itself (thank you for your explanation).
The updated question:
The approach suggested does not seem to work.
Forms called from the binding form don't get the binding defined.
Could you please help to figure out what I'm missing??
Here is the updated code:
(def all-expenses [{:amount 33.0 :date "today"}
{:amount 44.0 :date "yesterday"}])
(defn fetch-all-expenses [])
(defn fetch-expenses-greater-than [threshold]
(let [all (fetch-all-expenses)]
;calling from a nested form does not see the dynamically bound definition!
(println "2) from fetch-expenses-greater-than:" (fetch-all-expenses))
all))
(defn wrap [f]
(fn [& args] (apply f args)))
(def ^{:dynamic true} fetch-all-expenses (wrap fetch-all-expenses))
(binding [fetch-all-expenses (constantly all-expenses)]
(let [filtered (fetch-expenses-greater-than 15.0)]
(println "1) from inside binding:" (fetch-all-expenses))));calling from binding form OK!
The result of executing the in the repl is:
2) from fetch-expenses-greater-than: nil
1) from inside binding: [{:date today, :amount 33.0} {:date yesterday, :amount 44.0}]
nil
If I change the definition of fetch-all-expenses to
(defn ^:dynamic fetch-all-expenses [])
The result is as expected:
2) from fetch-expenses-greater-than: [{:date today, :amount 33.0} {:date yesterday, :amount 44.0}]
1) from inside binding: [{:date today, :amount 33.0} {:date yesterday, :amount 44.0}]
nil
It is possible to make a Var dynamic after it's been defined, but this will have no effect on code compiled before this change (it will still use the root binding). Use with-redefs to install custom replacements for functions during tests and the like.
The reason for this is that whether a Var is marked dynamic or not determines the way code using this Var is compiled. If it is not dynamic, such code will just get the root binding directly, saving some work; if it is dynamic, it will go through the somewhat more complex process of checking whether there is a thread-local binding in place for it.
So, there is no way to cause already compiled code use a custom function installed with binding after marking the Var holding the function dynamic. However, those calls still go through the Var, they just happen to go directly to the root binding, so you can use custom replacement functions for testing and the like if you install them as root bindings for the appropriate Vars. with-redefs encapsulates all the necessary logic for doing this cleanly.
Let's see how this works at the REPL:
;; define a non-dynamic Var:
(def foo 0)
;; this will throw an exception complaining about the attempt
;; to bind a non-dynamic Var:
(binding [foo 1]
foo)
;; let's define a function using foo;
;; we'll use it further down:
(defn bar []
foo)
;; now let's mark the Var dynamic:
(.setDynamic #'foo)
;; this will now evaluate to 1:
(binding [foo 1]
foo)
;; however, this will still return 0:
(binding [foo 1]
(bar))
(def ^{:dynamic true} log-call #'log-call) This statement says: "Create a var log-call and bind it to the var log-call. So when you try to use log-call var it will keep refering itself forever and hence StackOverflow exception.
You can try something like this:
(defn wrap [f]
(fn [& args] (apply f args)))
(def ^{:dynamic true} log-call (wrap log-call))
(def ^{:dynamic true} fetch-all-expenses (wrap fetch-all-expenses))
Thank you very much for your answer #MichaĆMarczyk. That explains it.
With code using the var before making it dynamic:
(def foo 0)
(defn bar []
foo)
(.setDynamic #'foo)
(binding [foo 1]
;; prints foo 1 . bar 0
(println "foo" foo ". bar" (bar)))
With code using the var after making it dynamic:
(def foo 0)
(.setDynamic #'foo)
(defn bar []
foo)
(binding [foo 1]
;; prints foo 1 . bar 1
(println "foo" foo ". bar" (bar)))
And yes!....with with-redefs instead of binding everything works as expected. That's exactly what I was needing.
Is there a reader function in clojure to parse clojure data structure? My use case is to read configuration properties files and one value for a property should be a list. I'd like to be able to write this as:
file.properties:
property1 = ["value1" "value2"]
and in clojure:
(load-props "file.properties")
and get a map with value {property1, ["value1" "value2"]
Right now,m I'm doing the following, with the same input file "file.properties":
(defn load-props [filename]
(let [io (java.io.FileInputStream. filename)
prop (java.util.Properties.)]
(.load prop io)
(into {} prop)))
;; returns:
;; {"property1" "[\"valu1\", \"valu2\"]"}
(load-props "file.properties")
But I cannot get a way to parse the result to a clojure's vector. I'm basically looking for something like Erlang's file:consult/1 function. Any idea how to do this?
If you want to read java-style properties files, look at Dave Ray's answer - though properties files have many limitations.
If you are using Clojure 1.5 or later, I suggest you use edn, the extensible data notation used in Datomic - it's basically clojure data structures, with no arbitrary code execution, and the ability to add tags for things like instances or arbitrary types.
The simplest way to use it is via read-string and slurp:
(require 'clojure.edn)
(clojure.edn/read-string (slurp "filename.edn"))
That's it. Note that read-string only reads a single variable, so you should set up your configuration as a map:
{ :property1 ["value1" "value2"] }
Then:
(require 'clojure.edn)
(def config (clojure.edn/read-string (slurp "config.edn")))
(println (:property1 config))
returns
["value1" "value2"]
java.util.Properties implements Map so this can be done very easily without manually parsing properties files:
(require 'clojure.java.io)
(defn load-props
[file-name]
(with-open [^java.io.Reader reader (clojure.java.io/reader file-name)]
(let [props (java.util.Properties.)]
(.load props reader)
(into {} (for [[k v] props] [(keyword k) (read-string v)])))))
(load-props "test.properties")
;=> {:property3 {:foo 100, :bar :test}, :property2 99.9, :property1 ["foo" "bar"]}
In particular, properties files are more complicated than you think (comments, escaping, etc, etc) and java.util.Properties is very good at loading them.
Is there a reader function in clojure to parse clojure data structure?
Yes. It's called read. You can also use it to read configuration data.
A file props.clj containing
{:property1 ["value1" 2]
:property2 {:some "key"}}
can be read like this:
(ns somens.core
(:require [clojure.java.io :as io])
(:import [java.io PushbackReader]))
(def conf (with-open [r (io/reader "props.clj")]
(read (PushbackReader. r))))
When reading untrusted sources it might be a good idea to turn of *read-eval*:
(def conf (binding [*read-eval* false]
(with-open [r (io/reader "props.clj")]
(read (PushbackReader. r)))))
For writing configuration data back to a file you should look at print functions such as pr and friends.
contrib has functions for reading writing properties,
http://richhickey.github.com/clojure-contrib/java-utils-api.html#clojure.contrib.java-utils/as-properties
If this is for your own consumption then I would suggest reading/writing clojure data structures you can just print them to disk and read them.
(use '[clojure.contrib.duck-streams :only (read-lines)])
(import '(java.io StringReader PushbackReader))
(defn propline->map [line] ;;property1 = ["value1" "value2"] -> { :property1 ["value1" "value2"] }
(let [[key-str value-str] (seq (.split line "="))
key (keyword (.trim key-str))
value (read (PushbackReader. (StringReader. value-str)))]
{ key value } ))
(defn load-props [filename]
(reduce into (map propline->map (read-lines filename))))
DEMO
user=> (def prop (load-props "file.properties"))
#'user/prop
user=> (prop :property1)
["value1" "value2"]
user=> ((prop :property1) 1)
"value2"
UPDATE
(defn non-blank? [line] (if (re-find #"\S" line) true false))
(defn non-comment? [line] (if (re-find #"^\s*\#" line) false true))
(defn load-props [filename]
(reduce into (map propline->map (filter #(and (non-blank? %)(non-comment? %)) (read-lines filename)))))
In Clojure, given a class name as a string, I need to create a new instance of the class. In other words, how would I implement new-instance-from-class-name in
(def my-class-name "org.myorg.pkg.Foo")
; calls constructor of org.myorg.pkg.Foo with arguments 1, 2 and 3
(new-instance-from-class-name my-class-name 1 2 3)
I am looking for a solution more elegant than
calling the Java newInstance method on a constructor from the class
using eval, load-string, ...
In practice, I will be using it on classes created using defrecord. So if there is any special syntax for that scenario, I would be quite interested.
There are two good ways to do this. Which is best depends on the specific circumstance.
The first is reflection:
(clojure.lang.Reflector/invokeConstructor
(resolve (symbol "Integer"))
(to-array ["16"]))
That's like calling (new Integer "16") ...include any other ctor arguments you need in the to-array vector. This is easy, but slower at runtime than using new with sufficient type hints.
The second option is as fast as possible, but a bit more complicated, and uses eval:
(defn make-factory [classname & types]
(let [args (map #(with-meta (symbol (str "x" %2)) {:tag %1}) types (range))]
(eval `(fn [~#args] (new ~(symbol classname) ~#args)))))
(def int-factory (make-factory "Integer" 'String))
(int-factory "42")
The key point is to eval code that defines an anonymous function, as make-factory does. This is slow -- slower than the reflection example above, so only do it as infrequently as possible such as once per class. But having done that you have a regular Clojure function that you can store somewhere, in a var like int-factory in this example, or in a hash-map or vector depending on how you'll be using it. Regardless, this factory function will run at full compiled speed, can be inlined by HotSpot, etc. and will always run much faster than the reflection example.
When you're specifically dealing with classes generated by deftype or defrecord, you can skip the type list since those classes always have exactly two ctors each with different arities. This allows something like:
(defn record-factory [recordname]
(let [recordclass ^Class (resolve (symbol recordname))
max-arg-count (apply max (map #(count (.getParameterTypes %))
(.getConstructors recordclass)))
args (map #(symbol (str "x" %)) (range (- max-arg-count 2)))]
(eval `(fn [~#args] (new ~(symbol recordname) ~#args)))))
(defrecord ExampleRecord [a b c])
(def example-record-factory (record-factory "ExampleRecord"))
(example-record-factory "F." "Scott" 'Fitzgerald)
Since 'new' is a special form, I'm not sure there you can do this without a macro. Here is a way to do it using a macro:
user=> (defmacro str-new [s & args] `(new ~(symbol s) ~#args))
#'user/str-new
user=> (str-new "String" "LOL")
"LOL"
Check out Michal's comment on the limitations of this macro.
Here is a technique for extending defrecord to automatically create well-named constructor functions to construct record instances (either new or based on an existing record).
http://david-mcneil.com/post/765563763/enhanced-clojure-records
In Clojure 1.3, defrecord will automatically defn a factory function using the record name with "->" prepended. Similarly, a variant that takes a map will be the record name prepended with "map->".
user=> (defrecord MyRec [a b])
user.MyRec
user=> (->MyRec 1 "one")
#user.MyRec{:a 1, :b "one"}
user=> (map->MyRec {:a 2})
#user.MyRec{:a 2, :b nil}
A macro like this should work to create an instance from the string name of the record type:
(defmacro newbie [recname & args] `(~(symbol (str "->" recname)) ~#args))