can someone point me to how I can write this in syntax-parse/case?
[(list e ...) #`(list #,(f #'e) ...)]
basically I'd like each element in the list to be processed individually by f in unsyntax. I don't think the above is the right syntax?
You can use unsyntax-splicing (which can be abbreviated as #,#) to embed result of list returning expression as individual elements of outer list. Then you can use map procedure to apply f over all elements of list returned by (syntax->list #'(e ...)) expression. In the end it will look like this:
#`(list #,#(map f (syntax->list #'(e ...))))
Related
trim-to (symbol list)
Write a function named trim-to that takes a symbol and list as parameters. Return a new list
starting from the first occurrence of the input symbol in the input list. If there is no
occurrence of the symbol, return nil.
For example:
(trim-to ‘c ‘(a b c d e))
This should return the following list:
‘(c d e)
Not quite sure how to start here. If someone could walk me through the steps they take to construct this function I would be forever grateful!
You have a symbol and a list:
if the list is the empty list you have failed;
if the first element of the list is the symbol this is the list you want;
otherwise take the rest of the list – now you have a symbol and a list ...
guys,
look at the code first:
(defmacro map-remove- [v w]
`(dosync
(ref-set ~v (dissoc #~v (keyword ~w)))))
(defmacro set-remove- [v w]
`(dosync
(ref-set ~v (disj #~v ~w))))
(defmacro clean- [v]
`(dosync
(ref-set ~v (empty #~v))))
They work fine now , but I want write a more general macro to combine "map-remove-" and "set-remove-" in one. according my C/Java experience I chose "case" but obviously the case can't use in macro defination cause "The test-constants are not evaluated. They must be compile-time literals", the following code won't work:
(defmacro [x]
(case (type x) ;;;;;;;;;;; This will never work!directly reach to default clause
....))
anybody has any suggestion? very appreciate.
You can use the functions map? and set? to test whether a value is a map or a set respectively.
I'm not sure I have enough perspective on what you're trying to do here though - I've substituted a macro instead of a function, because I can't see the necessity for a macro in the sample you've given.
;; Create a function to remove in a different way when given a map/set and a string
(defn remove- [v w]
(dosync
(cond
(map? #v)
(ref-set v (dissoc #v (keyword w)))
(set? #v)
(ref-set v (disj #v w)))))
;; Set up some mutable refs
(def m (ref {:a 1 :b 2}))
(def s (ref #{"a" "b" "c"}))
;; Remove from the refs
(remove- m "b") => {:a 1}
(remove- s "b") => #{"a" "c"}
On a side note - are you sure you need to use refs? I know that coming from a C/Java background, mutability is the default, but I've never actually had to use it in Clojure so far. Clojure places a lot of emphasis on immutability, and most things can be done (often very elegantly) just by using functions on immutable values.
The macro, transform!, as defined below seems to work for => (transform! ["foo" 1 2 3]). The purpose is to take in a list, with the first element being a string that represents a function in the namespace. Then wrapping everything into swap!.
The problem is that transform! doesn't work for => (transform! coll), where (def coll ["foo" 1 2 3]). I am getting this mystery exception:
#<UnsupportedOperationException java.lang.UnsupportedOperationException: nth not supported on this type: Symbol>
The function:
(defmacro transform!
" Takes string input and update data with corresponding command function.
"
[[f & args]] ;; note double brackets
`(swap! *image* ~(ns-resolve *ns* (symbol f)) ~#args))
I find it strange that it works for one case and not the other.
Macros work at compile-time and operate on code, not on runtime data. In the case of (transform! coll), the macro is being passed a single, unevaluated argument: the symbol coll.
You don't actually need a macro; a regular function will suffice:
(defn transform! [[f & args]]
(apply swap! *image* (resolve (symbol f)) args)))
Resolving vars at runtime could be considered a code smell, so think about whether you really need to do it.
You're passing a symbol to the macro, namely coll. It will try to pull that symbol apart according to the destructuring statement [f & args], which won't be possible of course.
You can also use (resolve symbol) instead of (ns-resolve *ns* symbol).
I am currently developing a small CMS using the wonderful Enlive as templating engine. Enlive has a macro called at that takes a node (a map) specifying the HTML snippet and an arbitrary number of tuples each consisting of a selector (a vector) and a transformation (a closure).
(at a-node
[:a :selector] a-transformation
[:another :selector] another-transformation
...)
Now I want to generate the tuples depending upon incoming data/context. I have tried a lot of different things without success. For example
(let [this (repository/u "http://example.com/ACMECorp")
statements (repository/find-by-subject this)
context {:depth 1}]
`(at (snippet-for 'this 'context)
[root] (set-attr :about (str 'this))
~#(loop [rules []
st statements]
(if-not (seq st)
rules
(recur (conj rules
`[:> (attr= :property ~(str (repository/predicate (first st))))]
`(content (renderit ~(repository/object (first st)) 'context)))
(rest st))))))
Any help is highly appreciated.
-Jochen
Clojure is a Lisp, so you can always fallback to building the code you'd want as a list, and call eval on it. I'm not 100% sure about the code you gave, but I'd guess you just want to enclose your whole syntax-quote in an eval call.
(let [this (repository/u "http://example.com/ACMECorp")
statements (repository/find-by-subject this)
context {:depth 1}]
(eval `(at (snippet-for 'this 'context)
[root] (set-attr :about (str 'this))
~#(loop [rules []
st statements]
(if-not (seq st)
rules
(recur (conj rules
`[:> (attr= :property ~(str (repository/predicate (first st))))]
`(content (renderit ~(repository/object (first st)) 'context)))
(rest st)))))))
Not sure if they are interchangeable, but take a look at the at* function. Seems to me that your problem is at being a macro.
EDIT: They're not. Call it like this:
(at* a-node
[[:a :selector] a-transformation
[:another :selector] another-transformation
...])
I tried to query data from database with jdbc. The problem is some column is array type.
;get that particular column
(def jdbc-array (with-connection *db*
(with-query-results rs ["select * from refgene limit 5"]
(:exonstarts (first rs)))))
;Check if it has a value
(print jdbc-array)
;#<Jdbc4Array {67075873,67078739,67085754,67100417,67109640,67113051,67129424,67131499,67143471,67162932}>nil
;check class
(class jdbc-array)
;org.postgresql.jdbc4.Jdbc4Array
How to convert this array to seq/vector in clojure ? I tried (seq jdbc-array) and (seq (.getArray jdbc-array) but both doesn't work...
If the with-connection option seems clunky to you (it does to me), you can extend the IResultSetReadColumn protocol to convert Jdbc4Array objects into regular or vectors:
Here's one way to do that:
(extend-protocol clojure.java.jdbc/IResultSetReadColumn
org.postgresql.jdbc4.Jdbc4Array
(result-set-read-column [pgobj metadata i]
(vec (.getArray pgobj))))
this will convert all array types into vectors when reading
this approach can also help with the JSON datatype as in this example
Ok, I got it. I need to called getArray before clojure close the connection, or it'll give a nil.
Not sure why... My guess is clojure's laziness.
;work
(with-connection *db*
(with-query-results rs ["select * from refgene limit ?" 5]
(seq (.getArray (:exonends (first rs))))))