kakk11
kakk11

Reputation: 918

clojure cannot apply function via map to list

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?

Upvotes: 1

Views: 95

Answers (3)

madstap
madstap

Reputation: 1552

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))))

Upvotes: 0

Alan Thompson
Alan Thompson

Reputation: 29958

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.

Upvotes: 2

Lee
Lee

Reputation: 144126

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)

Upvotes: 5

Related Questions