switch inside arrow operator - clojure

i am learning clojure. My question is it posible to use (case) inside (-> ).
For example, i want something like this (this code dont work):
(defn eval-xpath [document xpath return-type]
(-> (XPathFactory/newInstance)
.newXPath
(.compile xpath)
(case return-type
:node-list (.evaluate document XPathConstants/NODESET)
:node (.evaluate document XPathConstants/NODE)
:number (.evaluate document XPathConstants/NUMBER)
)
))
Or will be better to use multimethods instead? What is the right 'clojure way for this?
Thank you.

The arrow macro (->) just rewrites its arguments so that the value of the nth form is inserted as the first argument to the n+1th form. What you are writing is equivalent to:
(case
(.compile
(.newXPath (XPathFactory/newInstance))
xpath)
return-type
:node-list (.evaluate document XPathConstants/NODESET)
:node (.evaluate document XPathConstants/NODE)
:number (.evaluate document XPathConstants/NUMBER)
In a general case you can pick one of the three forms to be your tail form ahead of time using let, and then thread that in at the end of the threading macro. Like so:
(defn eval-xpath [document xpath return-type]
(let [evaluator (case return-type
:node-list #(.evaluate % document XPathConstants/NODESET)
:node #(.evaluate % document XPathConstants/NODE)
:number #(.evaluate % document XPathConstants/NUMBER))]
(-> (XPathFactory/newInstance)
.newXPath
(.compile xpath)
(evaluator))))
However what you are really trying to do is map a keyword to a constant on XPathConstants. This can be done with a map. Consider the following:
(defn eval-xpath [document xpath return-type]
(let [constants-mapping {:node-list XPathConstants/NODESET
:node XPathConstants/NODE
:number XPathConstants/NUMBER}]
(-> (XPathFactory/newInstance)
.newXPath
(.compile xpath)
(.evaluate document (constants-mapping return-type)))))
You have a mapping of keywords to constants, so use Clojure's data structures to express that. Additionally the real value of the threading macro is helping you compile the xpath. Don't be afraid to give the data you're using locally scoped names to help you keep track of what you are doing. It also helps you avoid trying to shoehorn things into the threading macro that really don't want to fit.

Check out the following clojure library for working with xpath expressions: https://github.com/kyleburton/clj-xpath

Related

Modyfing higher order functions output in ClojureScript

I want to create helper function that modifies output returned by higher-order function.
Example of higher-order function:
(def use-meta-sub (make-app-fn (make-sub :meta)))
The problem is that when using this in let like this:
(let [meta-sub (use-meta-sub props :get-me-meta-of-this)])
returns map of key-value pairs like this:
{:key-we-almost-never-need-1 nil
:key-we-almost-never-need-2 nil
:key-we-almost-never-need-3 nil
:key-we-almost-never-need-4 nil
:meta-data {:something-useful "foo"
:more-usefull "bar"
:and-so-on "baz"}}
I would like to target only this :meta-data key
I tried this and some other variations:
(defn use-meta-data-sub [props ctrl]
(:meta-data (use-meta-sub props ctrl))) ;; both with get
It does not work because (I think, that returns lazy sequence and I do not know how to actually firs evaluate it and then extract the key from output).
Is this possible without editing 1st higher-order function, and other two it contains?
(I read all documentation on clojure site and clojure-unraveled, either I do not understand them, or they do not cover this)

Create a keyword from a number

tl;dr
How can I derive a keyword from a number in ClojureScript:
(keyword 22)
;;=> :22 but in fact returns nil.
Background
In my ClojureScript/Hoplon application I make HTTP requests via cljs-http. Parts of the response I receive look like this:
{:companies
{:22 {:description ... } ; A company.
:64 {:description ... }
... }
{:offers
[{:description ... } ; An offer.
{:description ... }
... ]
Each offer within the vector behind :offers has a :companyId which represents a key in :companies. As soon as I receive the response, I reset! a cell (similar to an atom) query.
Now, I'd like to iterate over each offer and call a function offer-tpl that creates the corresponding HTML. In order to do so, offer-tpl needs the offer itself as well as the related company:
(for [offer (:offers #query)]
(offer-tpl offer (get-in #query [:companies (keyword (:companyId offer))]))))))
Despite the fact that this surely can be done more elegant (suggestions very appreciated), the get-in doesn't work. (:companyId offer) returns a number (e.g. 22) but (keyword (:companyId offer)) returns nil. Calling (keyword (str (:companyId offer))) does the trick, but aren't there any other ways to do this?
(keyword "22") or (keyword (str 22)) returns :22
The reason you are getting :22 is likely because of the keywordize-keys option of a JSON translation. For example:
cljs-http defaults to keywordize-keys for jsonp:
https://github.com/r0man/cljs-http/blob/1fb899d3f9c5728521786432b5f6c36d1d7a1452/src/cljs_http/core.cljs#L115
But you can (and should) in this case pass in a flag to disable keywordization.
Not all keys in JSON are appropriate for Clojure keywordization. For example spaces in a JSON key are valid, but not in Clojure.
Please be aware that numeric keywords are probably incorrect.
https://clojuredocs.org/clojure.core/keyword#example-542692cec026201cdc326d70
It seems like that caveat has been removed from the current Clojure website, so perhaps that means something but I'm not sure what.
http://clojure.org/reference/reader Currently states that
Keywords - Keywords are like symbols, except: They can and must begin
with a colon, e.g. :fred. They cannot contain '.' or name classes.
Like symbols, they can contain a namespace, :person/name A keyword
that begins with two colons is resolved in the current namespace: In
the user namespace, ::rect is read as :user/rect
and that
Symbols begin with a non-numeric character and can contain
alphanumeric.
This definition of a keyword excludes :22 and :with spaces
The keyword function returns a result for invalid input, but this is not an endorsement, it is simply because checking for incorrect input would be a performance overhead in a core part of Clojure.
In short, not all JSON keys translate to keywords, so you should avoid keywordize-keys unless you know the keyspace and/or doing so provides some conveniences.

Clojure struggling to visualise how the arrow macros work

I am struggling to understand how the -> and ->> expand.
If I have the following:
(-> query
(write-query-to-excel db csv-file)
(archiver archive-password)
(send-with-attachment send-to subject body)
(clean-up))
How does this expand, I understand that -> is a thread-first macro which inserts the the value as the second item as the first form, and after looking at examples I'm still unsure.
Also how does ->> differ, I know it inserts the item as the last argument of the function but again the wording confuses me.
(->> query
(write-query-to-excel db csv-file)
(archiver archive-password)
(send-with-attachment send-to subject body)
(clean-up))
When expanded how would these two macros look?
-> and ->> always remind me of Matryoshka dolls because they nest all expressions passed to them.
Let's consider (-> a (b c d) (e f g)). We can now visually cut them (with a pipe) at the 1st argument position in each expression but the first: (-> a (b | c d) (e | f g)). Now that the expressions are cut in halves we can nest them: first (-> (b a c d) (e | f g)) and then (-> (e (b a c d) f g)) which simplifies to (e (b a c d) f g).
->> works in a very similar manner except the insert point is at the end (last argument position): (-> a (b c d |) (e f g |)) which successively expands to (-> (b c d a) (e f g |)), (-> (e f g (b c d a))) and (e f g (b c d a)).
Using clojure.walk/macroexpand to expand the macros:
(clojure.walk/macroexpand-all '(-> query
(write-query-to-excel db csv-file)
(archiver archive-password)
(send-with-attachment send-to subject body)
(clean-up)))
... produces
(clean-up (send-with-attachment (archiver (write-query-to-excel query db csv-file) archive-password) send-to subject body))
Whereas
(clojure.walk/macroexpand-all '(->> query
(write-query-to-excel db csv-file)
(archiver archive-password)
(send-with-attachment send-to subject body)
(clean-up)))
... produces
(clean-up (send-with-attachment send-to subject body (archiver archive-password (write-query-to-excel db csv-file query))))
Since the result doesn't have to make sense, we can use simpler examples to illustrate the difference:
(clojure.walk/macroexpand-all '(-> a b c d))
;(d (c (b a)))
, the same with -> or ->>. But if there are arguments:
(clojure.walk/macroexpand-all '(-> a (b 1 2 3)))
;(b a 1 2 3)
whereas
(clojure.walk/macroexpand-all '(->> a (b 1 2 3)))
;(b 1 2 3 a)
The answer from #cgrand is good, but I would like to add a bit more.
You could achieve something very similar by putting your thread-first example into a (let...) form as:
; better if descriptive names used for intermediate results
(let [tmp1 (write-query-to-excel db csv-file)
tmp2 (archiver tmp1 archive-password)
tmp3 (send-with-attachment tmp2 send-to subject body)
tmp4 (clean-up tmp3) ]
<process result in tmp4>
...)
This is often the best solution since you can use descriptive variable names for the intermediate results. If, however, you won't really benefit from naming the intermediate results, you can use a generic variable it as a placeholder and still see exactly where each intermediate result is used in the next form. This is how the it-> macro from the Tupelo Core library works:
Imagine using a variable it to mark the location in each form where the result of the previous expression is inserted. Then in your -> example, we get:
(ns my.proj
(:require [tupelo.core :refer [it->]]
... ))
(it-> (write-query-to-excel db csv-file)
(archiver it archive-password)
(send-with-attachment it send-to subject body)
(clean-up it))
Then in your ->> example we would have:
(it-> (write-query-to-excel db csv-file)
(archiver archive-password it)
(send-with-attachment send-to subject body it)
(clean-up it))
However, what do we do if the expressions do not all chain together in either the first or last argument position? Consider this code:
(it-> 1
(inc it)
(+ it 3)
(/ 10 it)
(str "We need to order " it " items." )
;=> "We need to order 2 items." )
In this case, we have expressions where the previous result is chained into the only, first, last, and middle argument positions. In this case, neither -> nor ->> will work, and one must use something like it-> or a generic (let ...) form.
So for simple expression pipelines, using it-> (or the similar as->) can make the code more explicit about how the expressions are chained together. It also allows you to chain expressions that are not all "thread-first" or "thread-last". For more complicated processing chains, using a let form (possible nested) is the best answer as you can name the intermediate results and then combine them in arbitrarily complicated ways.
Would you mind taking a little tour around programming languages?
Ruby
In the world of Ruby there is a common practice of making so-called "method chains". What it is, essentially, is:
calling a method
calling a method on its result
calling a method on that method's result
etc.
Ruby is object-oriented, and such chains look like this:
(-5..5).map(&:abs)
.select(&:even?)
.count
.to_s
take a range of integers from -5 to 5 inclusive
map them into their absolute values
only select those that are even
count how many you have
convert the resuling number into a string
In Ruby, collections are objects, methods like map, count and select are their methods. map returns a collection, on which you can call select. On the result of select we call count that outputs an integer. Then we call to_s on that integer to convert it into a string. The dot-call of object.method calls a method on an object. Familiar stuff.
In some languages you may be exposed to terrible truth that object's methods may be nothing but a simple function that takes an object it acts upon and arguments. Some languages thoroughly hide that fact as an implementation detail, but could that convention actually be a limitation?
Lua
Lua is a nice little and honest language that doesn't hide from you what object's methods are. Consider these two equivalent lines:
obj.increase(obj, 5)
obj:increase(5)
It's a convention enforced on language-level: a method is a function that takes its owner object as a first argument.
...and some others with "static extension"
Defining all the possibly needed methods in a type has proven to be impossible, so some languages have adopted "static extension": it allows you to create a function that takes an "object acted upon" as its first argument (without access to sources of the type itself!). Then with some syntactic sugar you can use x.ext(y) calls instead of ext(x, y):
C# has that.
Haxe has that.
C++ doesn't have that, but there are proposals to add this, that highlight the semantic similarities of x.f(y) and f(x, y)
That feature allows us to chain operations a slightly cleaner way.
g(f(x, y), z) # Before
x.f(y).g(z) # After
Clojure
And we're back! So what does all this have to do with -> and ->>? They provide similar-looking syntax that looks good in longer chains.
We know for sure that our map and filter (same as Ruby's select) are just functions that take collections they act upon as their last (oops, that was unexpected!) argument.
(->> (range -5 6) (map #(Math/abs %)) ; 6 not included
(filter even?)
(count)
(str))
Oh, so we see a bit different way here: functions we treat as methods here take an object they act upon as their last argument. But we just make the "chain" using ->> and that fact becomes less noticeable.
If we had functions that took "object acted upon" as their first argument, as we've seen in Lua, we'd use ->. Depending on the functions you're chaining, -> might make more sense.
We can have it both ways, we can even mix them with a tad more verbose as->.

Clojure: java.lang.Integer cannot be cast to clojure.lang.IFn

I know there are a lot of questions out there with this headline, but I can't glean my answer from them, so here goes.
I'm an experienced programmer, but fairly new to Clojure. I'm trying to parse a RTF file by converting it to a HTML file then calling the html parser.
The converter I'm using (unrtf) always prints to stdout, so I need to capture the output and write the file myself.
(defn parse-rtf
"Use unrtf to parse a rtf file"
[#^java.io.InputStream istream charset]
(let [rtffile (File/createTempFile "parse" ".rtf" (File. "/vault/tmp/"))
htmlfile (File/createTempFile "parse" ".ohtml" (File. "/vault/tmp/"))
command (str "/usr/bin/unrtf "
(.getPath rtffile)
)
]
(try
(with-open [rtfout (FileOutputStream. rtffile)]
(IOUtils/copy istream rtfout))
(let [ proc (.exec (Runtime/getRuntime) command)
ostream (.getInputStream proc)
result (.waitFor proc)]
(if (> result 0)
(
(println "unrtf failed" command result)
; throwing an exception causes a parse failure to be logged
(throw (Exception. (str "RTF to HTML conversion failed")))
)
(
(with-open [htmlout (FileOutputStream. htmlfile)]
(IOUtils/copy ostream htmlout))
; since we now have html, run it through the html parser
(parse-html (FileInputStream. htmlfile) charset)
)
)
)
(finally
(.delete rtffile)
(.delete htmlfile)
)
)))
The exception points to the line with
(IOUtils/copy ostream htmlout))
which really confuses me, since I used that form earlier (just after the try:) and it seems to be OK there. I can't see the difference.
Thanks for any help you can give.
As others have correctly pointed out, you can't just add extra parentheses for code organization to group forms together. Parentheses in a Clojure file are tokens that delimit a list in the corresponding code; lists are evaluated as s-expressions - that is, the first form is evaluated and the result is invoked as a function (unless it names a special form such as if or let).
In this case you have the following:
(
(with-open [htmlout (FileOutputStream. htmlfile)]
(IOUtils/copy ostream htmlout))
; since we now have html, run it through the html parser
(parse-html (FileInputStream. htmlfile) charset)
)
The IOUtils/copy function has an integer return value (the number of bytes copied). This value is then returned when the surrounding with-open macro is evaluated. Since the with-open form is the first in a list, Clojure will then try to invoke the integer return value from IOUtils/copy as a function, resulting in the exception that you see.
To evaluate multiple forms for side-effects without invoking the result from the first one, wrap them in a do form; this is a special form that evaluates each expression and returns the result of the final expression, discarding the result from all others. Many core macros and special forms such as let, when, and with-open (among many others) accept multiple expressions and evaluate them in an implicit do.
I didnt try to run your code, just had a look at it, and after the if (> result 0) you have ((println ...)(throw ...)) without a do. Having an extra parens causes the returned value from the inner parens to be treated as a function and get executed.
try to include it, like this (do (println ...) (throw ...))

What are the usages for ^ and how can I get more information on it?

found this on a blog : (def x ^{:type ::my-class} {})
apparently it adds meta data to a map
user=> (meta x)
{:type :user/my-class}
what else does ^ do ? does it have any other uses ? can it be used as a getter for meta data (not just to set meta data) ?
how can i find out information about some shortcuts in clojure ? like ^, ', `, ~. is it possible to get that from the repl ?
Look at the documentation for the Clojure reader, specifically the section on macro characters:
The Reader
Edit: Metadata has documentation too :-)