clojure cannot apply function via map to list - clojure

I seem to have a difficulty understanding how I should use clojure map. I have a list of objects called in-grids where I wan't to use method getCoordinateSystem. I guess it is important that objects in the list are of some Java class. When I directly define function in clojure then map works.
This works:
(.getCoordinateSystem (first in-grids))
but not this
(map .getCoordinateSystem in-grids)
And the error is: java.lang.RuntimeException: Unable to resolve symbol: .getCoordinateSystem in this context
I'm probably missing something really obvious here, but what exactly?

If you have an expression of the form
(map f sequence)
then f should refer to an instance of IFn which is then invoked for every element of sequence.
. is a special form, and .getCoordinateSystem does not refer to an IFn instance.
(.getCoordinateSystem (first in-grids))
is equivalent to
(. (first in-grids) (getCoordinateSystem))
You can construct a function value directly e.g.
(map #(.getCoordinateSystem %) in-grids)

Another choice which is often a handy alternative to map is the for function:
(for [grid in-grids]
(.getCoordinateSystem grid))
Using for in this manner has the same effect as map but is a bit more explicit in the "one-item-at-a-time" nature of the processing. Also, since you are calling the Java function getCoordinateSystem directly you don't need to wrap it inside a Clojure function literal.

As an alternative to Lee's answer, there's the memfn macro, which expands to code similar to that answer.
(map (memfn getCoordinateSystem) in-grids)
(macroexpand '(memfn getCoordinateSystem))
;=> (fn* ([target56622] (. target56622 (getCoordinateSystem))))

Related

In Clojure, why do you have to use parenthesis when def'ing a function and use cases of let

I'm starting to learn clojure and I've stumbled upon the following, when I found myself declaring a "sum" function (for learning purposes) I wrote the following code
(def sum (fn [& args] (apply + args)))
I have understood that I defined the symbol sum as containing that fn, but why do I have to enclose the Fn in parenthesis, isn't the compiler calling that function upon definition instead of when someone is actually invoking it? Maybe it's just my imperative brain talking.
Also, what are the use cases of let? Sometimes I stumble on code that use it and other code that don't, for example on the Clojure site there's an exercise to use the OpenStream function from the Java Interop, I wrote the following code:
(defn http-get
[url]
(let [url-obj (java.net.URL. url)]
(slurp (.openStream url-obj))))
(http-get "https://www.google.com")
whilst they wrote the following on the clojure site as an answer
(defn http-get [url]
(slurp
(.openStream
(java.net.URL. url))))
Again maybe it's just my imperative brain talking, the need of having a "variable" or an "object" to store something before using it, but I quite don't understand when I should use let or when I shouldn't.
To answer both of your questions:
1.
(def sum (fn [& args] (apply + args)))
Using def here is very unorthodox. When you define a function you usually want to use defn. But since you used def you should know that def binds a name to a value. fn's return value is a function. Effectively you bound the name sum to the function returned by applying (using parenthesis which are used for application) fn.
You could have used the more traditional (defn sum [& args] (apply + args))
2.
While using let sometimes makes sense for readability (separating steps outside their nested use) it is sometimes required when you want to do something once and use it multiple times. It binds the result to a name within a specified context.
We can look at the following example and see that without let it becomes harder to write (function is for demonstration purposes):
(let [db-results (query "select * from table")] ;; note: query is not a pure function
;; do stuff with db-results
(f db-results)
;; return db-results
db-results)))
This simply re-uses a return value (db-results) from a function that you usually only want to run once - in multiple locations. So let can be used for style like the example you've given, but its also very useful for value reuse within some context.
Both def and defn define a global symbol, sort of like a global variable in Java, etc. Also, (defn xxx ...) is a (very common) shortcut for (def xxx (fn ...)). So, both versions will work exactly the same way when you run the program. Since the defn version is shorter and more explicit, that is what you will do 99% of the time.
Typing (let [xxx ...] ...) defines a local symbol, which cannot be seen by code outside of the let form, just like a local variable (block-scope) in Java, etc.
Just like Java, it is optional when to have a local variable like url-obj. It will make no difference to the running program. You must answer the question, "Which version makes my code easier to read and understand?" This part is no different than Java.

How to inherit function options

I wrote this function that gets an element out of a tree. It's just this:
(defn at [address tree] (reduce nth tree address))
Now the problem with this is that nth has 2 overloads; one that throws an exception if the index is out of range, and one that takes a not-found argument to return instead of throwing and exception.
Now I could make an overload for my function to add this option like so:
(defn at [address tree not-found]
(reduce (fn [curr-tree index] (nth curr-tree index not-found))
tree address))
I could complain about how I have to explicitly make a new function instead of the nice nth by itself.
This isn't the real problem though. I shouldn't have to make an overload for every overload that nth has.
nth only has two overloads, but for other times when I want to write a wrapper-like function, how can I defer decisions to the user. In this example, I'm just wrapping nth; to be consistent, I want at to imitate the behavior of nth. How do I inherit the options of other functions?
I'm asking this from a clojure point of view, but it may or may not apply to other languages.
Why do you design at in terms of nth's design? Whoever calls at shouldn't be thinking about nth's overloads.
at can be passed a function like in #amalloy's answer. But I would suggest starting with a simpler design and refactoring later if need be:
(defn at
([address tree]
(reduce nth tree address))
([address tree not-found]
(reduce #(nth %1 %2 not-found) tree address)))
My rationale is passing a not-found value is easier to understand than passing a function:
(def maybe-x (at addr tree :bummer))
;; See #amalloy's answer
(def maybe-x (at' addr tree #(nth %1 %2 :bummer))))
In fact if I need to pass some other function later, I would make a new at-by function (see group-by).
Maybe something like this?
(defn at [address tree & more]
(reduce (fn [a i] (apply nth a i more)) tree address))
The & more picks up whatever extra arguments the user might supply, and the apply sticks them on to the end of the call to nth, without you having to worry about what nth is going to do with them.
Stylistically, though, I'd prefer to write out the overloads. It will make for better documentation of what options your function supports, and it will be easier to maintain down the road.
You can take a function argument to call instead of nth, and then you don't care how many overloads it has, because the caller will handle the one overload they actually want to use.
(defn at
([address tree]
(at address tree nth))
([address tree f]
(reduce f tree address)))
(at [whatever] some-tree #(nth % %2 nil))

calling a library function of arbitrary name

say there's a library l, which has two functions (a and b).
Calling both functions and merging the results into a vector could be done like this:
(concat (l/a) (l/b))
Is there a way to make this more generic? I tried something like this, but it threw an exception:
(apply concat (map #(l/%) ['a 'b]))
of course, this would work:
(apply concat [l/a l/b])
Calling both functions and merging the results into a vector could be done like this:
(concat (l/a) (l/b))
No, you will not get a vector. And you will only get a sequence if those functions return sequences. Otherwise, definitely not, you will get a runtime exception with this code and your assumption.
It sounds like you have a bunch of functions and you want to concatenate the results of them all together? There is no need to quote them, just make a sequence of the functions:
[l/a l/b l/c ...]
And use apply with concat as you already are, or use reduce to accumulate values.
Call vec on the result if you need it to be a vector rather than a sequence.
Your other solutions are definitely making your code much much more complex, unnecessary, and difficult to read. (also, you almost never need to quote vars as you are doing)
It looks like you want a general way of invoking a function inside a namespace. You can construct a symbol and dereference it to find the functions, then combine the results using mapcat e.g.
(mapcat #((find-var (symbol "l" %))) ["a" "b"])
alternatively you could first find the namespace and use ns-resolve to find the vars e.g.
(let [ns (find-ns 'l)]
(mapcat #((ns-resolve ns %)) ['a 'b]))

How to pass a list to clojure's `->` macro?

I'm trying to find a way to thread a value through a list of functions.
Firstly, I had a usual ring-based code:
(defn make-handler [routes]
(-> routes
(wrap-json-body)
(wrap-cors)
;; and so on
))
But this was not optimal as I wanted to write a test to check the routes are actually wrapped with wrap-cors. I decided to extract the wrappers into a def. So the code became as follows:
(def middleware
(list ('wrap-json-body)
('wrap-cors)
;; and so on
))
(defn make-handler [routes]
(-> routes middleware))
This apparently doesn't work and is not supposed to as the -> macro doesn't take a list as the second argument. So I tried to use the apply function to resolve that:
(defn make-handler [routes]
(apply -> routes middleware))
Which eventually bailed out with:
CompilerException java.lang.RuntimeException: Can't take value of a
macro: #'clojure.core/->
So the question arises: How does one pass a list of values to the -> macro (or, say, any other macro) as one would do with apply for a function?
This is an XY Problem.
The main point of -> is to make code easier to read. But if one writes a new macro solely in order to use -> (in code nobody will ever see because it exists only at macro-expansion), it seems to me that this is doing a lot of work for no benefit. Moreover, I believe it obscures, rather than clarifies, the code.
So, in the spirit of never using a macro where functions will do, I suggest the following two equivalent solutions:
Solution 1
(reduce #(%2 %) routes middleware)
Solution 2
((apply comp middleware) routes)
A Better Way
The second solution is easily simplified by changing the definition of middleware from being a list of the functions to being the composition of the functions:
(def middleware
(comp wrap-json-body
wrap-cors
;; and so on
))
(middleware routes)
When I began learning Clojure, I ran across this pattern often enough that many of my early projects have an freduce defined in core:
(defn freduce
"Given an initial input and a collection of functions (f1,..,fn),
This is logically equivalent to ((comp fn ... f1) input)."
[in fs]
(reduce #(%2 %) in fs))
This is totally unnecessary, and some might prefer the direct use of reduce as being more clear. However, if you don't like staring at #(%2 %) in your application code, adding another utility word to your language is fine.
you can make a macro for that:
;; notice that it is better to use a back quote, to qoute function names for macro, as it fully qualifies them.
(def middleware
`((wrap-json-body)
(wrap-cors))
;; and so on
)
(defmacro with-middleware [routes]
`(-> ~routes ~#middleware))
for example this:
(with-middleware [1 2 3])
would expand to this:
(-> [1 2 3] (wrap-json-body) (wrap-cors))

Lazyness and stackoverflow

I wrote the following:
(fn r [f xs]
(lazy-seq
(if (empty? xs)
'()
(cons (f (first xs)) (r f (rest xs))))))
to solve 4clojure.com's problem #118: http://www.4clojure.com/problem/118
which asks to reimplement map without using map etc. and that solution passes the tests (I don't know if it's correct or not: it's very close to other solutions that said).
Because the problem stated that it had to be lazy I wrote the code above by "wrapping" my solution in a lazy-seq... However I don't understand how lazy-seq works.
I don't understand what is "lazy" here nor how I could test it out.
When I ask (type ...) I get, unsurprisingly, a clojure.lang.LazySeq but I don't know what's the difference between that and what I get if I simply remove the lazy-seq "wrapping".
Now of course if I remove the lazy-seq I get a stackoverflow why trying to execute this:
(= [(int 1e6) (int (inc 1e6))]
(->> (... inc (range))
(drop (dec 1e6))
(take 2)))
Otherwise (that is: if I let the lazy-seq wrapping in place), it seems to work fine.
So I decided to try to somehow "debug" / trace what is going on to try to understand how it all works. I took the following macro (which I found on SO IIRC):
(defmacro dbg [x] `(let [x# ~x] (println "dbg: " '~x "=" x#) x#))
And wrapped the working version inside the dbg macro and tried to execute it again. And now kaboom: the version which worked fine now throws a stackoverflow too.
Now I'm not sure: maybe it's an unwanted effect of the macro that would somehow force the evalution of stuff that otherwise wouldn't be evaluated?
It would be great if anyone could explain, using this simple function and the simple test, how lazyness does work here, what exactly gets called when, etc.
The whole magic lies in clojure.lang.LazySeq java class. Which itself implement the ISeq interface and the s-expressions parameter to the lazy-seq macro are converted to a function without any parameter and is passed to the constructor of clojure.lang.LazySeq (to the constructor which take IFn object as parameter) and because in the end you have called r function again (which is returning a ISeq and not the complete list) this allows the LazySeq to evaluate items lazily.
So basically the flow goes something like this:
LazySeq calls the Fn passed to it (i.e the rest body of the code)
This Fn call returns a ISeq because Lists implements ISeq. This return ISeq (list) with first value as a concrete value and second is a LazySeq object due to recursive call to r. This returned ISeq is stored in a local variable in the class.
The ISeq implementation of LazySeq on calling next item does call the next of ISeq (list) that it stored in local class variable in above step and check if it is of type LazySeq (which it will be in 2nd item due to r call), if it is LazySeq then evaluate that and return then item else return the item directly (the first concrete value that you passed to cons)
I know it is a little mind bending thing :). I also went through the Java code just now and was able to figure out after I realized that the magic is possible because the recursive call to r itself return a lazy sequence. So there you have it, kind of custom delimited continuations :)