Clojure function evaluation - java

I was searching for a Clojure logarithm function and concluded there really isn't one for v1.3+. What took me so long to invoke Math/log was this:
user=> Math/log
CompilerException java.lang.RuntimeException: Unable to find static field: log in class java.lang.Math, compiling:(NO_SOURCE_PATH:0:0)
I tried variations like (use 'java.lang.Math) and so forth. It wasn't until I tried an example that I found it's there after all:
user=> (Math/log 10)
2.302585092994046
This must be by design, but what is the reason?

A static method imported from Java is not a Clojure function or any other kind of Clojure object. The compiler reports any misfit as a missing field, even where the context is looking for a function. All of these ...
Math/log
(Math/log)
(map Math/log (range 1 5))
... produce such errors.
For a corresponding Clojure function:
inc returns the function;
(inc) reports ... wrong number of args(0) ...;
(map inc (range 1 5)) returns (2 3 4 5).
You can wrap a Java method as a Clojure one:
(defn log [x] (Math/log x))
... getting the expected result:
(map log (range 1 5))
;(0.0 0.6931471805599453 1.0986122886681098 1.3862943611198906)
The Clojure Java Interop page recommends
(map #(Math/log %) (range 1 5))
... in such cases.

Clojure provides some forms for interoperating with Java classes, methods, and fields. When you access static field in a class, you can do it like this:
user=> Integer/MAX_VALUE
;=> 2147483647
user=> Math/PI
;=> 3.141592653589793
And when you want to invoke static method, you can use the following form
user=> (Math/log 10)
;=> 2.302585092994046
user=> (Math/sin 1)
;=> 0.8414709848078965
When you try to evaluate just Math/log, clojure think it's static field, which is not true.
user=> Math/log
;=> CompilerException java.lang.RuntimeException: Unable to find static field: log in class java.lang.Math, compiling:(/private/var/folders/jh/q738l9dn0hxg0vvwbty7m5hw0000gp/T/form-init145007798854806400.clj:1:5845)
You can see it from the error message(Unable to find static field:...) that the clojure REPL try to find static field log from Math class, then failed.

In Java, one uses parentheses to invoke a function:
println("hi");
Clojure also uses parentheses to invoke a function, but with a different placement:
(println "hi")
In either Java or Clojure, just typing:
println
is an error, because you don't have the parentheses to indicate a function call.
In your first example, you use the name of the function Math/log, but you had no parentheses to tell the REPL that you wanted to invoke a function.
Also, in Java, parentheses can indicate either a function call or a grouping operator:
println(2 + (3 + 4))
In Clojure, parentheses only indicate function calls, and never indicating simple grouping.

Related

Clojure can't find java constructors for native classes?

I want to make a function that I can pass a map of functions and apply those functions to another map--think of it as coercing a map of strings to arbitrary types. (I'd love to do something higher level like fmap, but one step at a time, right?)
So along the way I figure I will need to do something like
user=> (apply Long. "1")
But I get this when I try:
CompilerException java.lang.ClassNotFoundException: Long., compiling:(/private/var/folders/c9/5yl3m9pn0rjdnvqlp5v4fzhr0000gn/T/form-init8437802472507251220.clj:1:1)
I can certainly find the class this way:
user=> (Long. "1")
1
If I do
user=> (apply #(Long. %1) "1")
I see
IllegalArgumentException No matching ctor found for class java.lang.Long clojure.lang.Reflector.invokeConstructor (Reflector.java:183)
which is confusing because I just used the constructor. I think I did, anyway. It even finds the right class, just not the constructor of the class.
This also fails, though differently:
user=> (apply #(new Long. %1) "1")
CompilerException java.lang.ClassNotFoundException: Long., compiling:(/private/var/folders/c9/5yl3m9pn0rjdnvqlp5v4fzhr0000gn/T/form-init8437802472507251220.clj:1:9)
I can get it to not find java.lang.Long, which is interesting:
user=> (apply #(new java.lang.Long. %1) "1")
CompilerException java.lang.ClassNotFoundException: java.lang.Long., compiling:(/private/var/folders/c9/5yl3m9pn0rjdnvqlp5v4fzhr0000gn/T/form-init8437802472507251220.clj:1:9)
This works, though:
user=> (defn l [x] (Long. x))
#'user/l
user=> (apply l ["1"])
1
And I could write my code this way, though it seems a little... off?
Anyway, what's going on here? Why would this make sense?
Java functions, including constructors, are not legal Clojure functions and cannot be passed directly to higher-order-functions like apply unless they are wrapped inside a Clojure function.
Also, note that apply expects an collection of args, as it "unwraps" them from the array. This works for a vector with one string:
(Long. "1") -> 1
(apply #(Long. %) ["1"] ) -> 1
But what you really probably want is mapv or map:
(mapv #(Long. %) ["1" "2" "3"] ) -> [1 2 3]
I'll let you figure out whats wrong with these failing cases:
; failing cases
; (apply Long. ["1"] )
; (apply #(Long. %) ["1" "2" "3"] )
; (apply #(Long. %) "1" "2" ["3"] )

Clojure doto macro

I am going to call the .toUpperCase method within a doto macro like follows but the doto returns the small letters:
(doto (java.lang.String. "clojure")
(.toUpperCase))
returns "clojure". I do the macroexpansion and as the return value is the object created:
(clojure.core/let [G__7359 (java.lang.String. "cojure")] (.toUpperCase G__7359) G__7359)
, but why i don't get the uppercased answer?
doto is part of Clojure's Java interop features. It is designed to make it possible to write java with out soooo darn many parens. so
Foo foo = new Foo;
foo.setX().setY().makeFactory().applyPhaseOfMoon();
which has 8 parens becomes:
(doto foo .setY .makeFactory .applyPhaseOfMoon)
which has a total of two.
In this case if we dig into the expanstion of your example:
user> (doto "hi" .toUpperCase)
"hi"
expands to:
user> (macroexpand-1 '(doto "hi" .toUpperCase))
(clojure.core/let [G__110453 "hi"]
(.toUpperCase G__110453)
G__110453)
where the second line does this:
user> (.toUpperCase "hi")
"HI"
and then throws the answer away and returns the saved value form the start. I personally never see doto used in practice outside of places where people are translating java to clojure inorder to call some API.
From the documentation:
Evaluates x then calls all of the methods and functions with the value
of x supplied at the front of the given arguments. The forms are
evaluated in order. Returns x.
doto returns the original argument, not any the result of functions performed using it. I believe the doto function is generally intended for side-effects. This is why you get the original string back.
What you are looking for is the .. threading macro ( https://clojuredocs.org/clojure.core/_.. ):
Expands into a member access (.) of the first member on the first
argument, followed by the next member on the result, etc. For
instance:
(.. System (getProperties) (get "os.name"))
expands to:
(. (. System (getProperties)) (get "os.name"))
but is easier to write, read, and understand.
In your case:
(doto "clojure" .toUpperCase)
; => "clojure"
(.. "clojure" toUpperCase)
; => "CLOJURE"

Converting JRuby RubyHash to Java Map?

I want to use JRuby to run some ruby scripts, get a result and continue using Java/Scala. Unfortunately, I don't know how to convert an object from a RubyHash to a Java or Scala Map.
Is there a simple way to do this?
Any suggestions on how to do it?
class org.jruby.RubyHash implements java.util.Map, so, it already is a Java Map, albeit a non-generic "raw" type.
Unfortunately, JRuby's Hash class only inherits the generic to_java method from Kernel, unlike Array which has its own version.
This works:
[1, 2, 3].to_java(:int)
This doesn't, although it looks like it should:
{ 'one' => 1, 'two' => 2 }.to_java(:string, :int)
[It might be worthwhile filing this as a feature request.]
org.jruby.RubyHash implements java.util.Map in a way that it attempts to convert Ruby objects to Java with "normal" Map operations.
e.g. if you have a hash such as: { 'a' => 1, 'b' => 2 } which (internally) means you have RubyString keys mapped to RubyFixnum values in a hash instance, on the Java side hash.get("a") will work fine and return 1 as a java.lang.Long
I would suggest to change your approach slightly: this would involve only changing the way you initialize objects in ruby, the rest should be transparent.
Instead of using pure Ruby hash objects (o=Hash.new or o={}), please use instead java.util.HashMap like in this snippet:
require 'java'
o = java.util.HashMap.new # you could also use o = Java::JavaUtil::HashMap.new
From then on, o would be a java object used as a hash by Ruby code, and can still be accessed using java methods.
Another mode complete snippet:
>> require 'java'
=> true
>> o = Java::JavaUtil::HashMap.new
=> {}
>> o[1] = 2
=> 2
>> o["cm"] = true
=> true
>> p o.keys # ruby methods/interface
[1, "cm"]
=> nil
>> p o.keySet().to_a # java methods
[1, "cm"]
=> nil

Converting Java collections to Clojure data structures

I am creating a Clojure interface to a Java API with a method that returns a java.util.LinkedHashSet.
Firstly, is the idiomatic Clojure way of handling this to convert the LinkedHashSet to a clojure data structure?
Secondly, what is the best method for converting Java collections into Clojure data structures?
There are lots of options, since Clojure plays very nicely with Java collections. It depends on exactly what data structure you want to use in Clojure.
Here's some examples:
;; create a HashSet
(def a (java.util.HashSet.))
(dotimes [i 10] (.add a i))
;; Get all the values as a sequence
(seq a)
=> (0 1 2 3 4 5 6 7 8 9)
;; build a new HashSet containing the values from a
(into #{} a)
#{0 1 2 3 4 5 6 7 8 9}
;; Just use the HashSet directly (high performance, no copy required)
(.contains a 1)
=> true
(.contains a 100)
=> false
Regarding when to use each of these, I'd suggest the following advice:
If you are trying to wrap a Java library and present a clean Clojure API, then I'd suggest converting to the equivalent Clojure data structures. This is what Clojure users will expect, and you can hide the potentially messy Java interop details. As a bonus, this will make things immutable so that you don't run the risk of Java collections mutating while you use them.
If you just want to use the Java API quickly and efficiently, just use Java interop directly on the Java collections.
The idiomatic way to convert java collections to clojure is to use the (seq) function, which is already called by most functions operating on sequences.
(def s (java.util.LinkedHashSet.))
#'user/s
user> (seq s)
nil
user> (.add s "foo")
true
user> (seq s)
("foo")
user>
I honestly don't know if there's a universally accepted practice, but here's Chris Houser arguing against Java to Clojure adapters as you break compatibility with the original Java API.
To perform the translation you asked for, simply use into:
user=> (import java.util.LinkedHashSet)
java.util.LinkedHashSet
user=> (def x (LinkedHashSet.))
#'user/x
user=> (.add x "test")
true
user=> (def y (into #{} x))
#'user/y
user=> y
#{"test"}

Dynamically generating high performance functions in clojure

I'm trying to use Clojure to dynamically generate functions that can be applied to large volumes of data - i.e. a requirement is that the functions be compiled to bytecode in order to execute fast, but their specification is not known until run time.
e.g. suppose I specify functions with a simple DSL like:
(def my-spec [:add [:multiply 2 :param0] 3])
I would like to create a function compile-spec such that:
(compile-spec my-spec)
Would return a compiled function of one parameter x that returns 2x+3.
What is the best way to do this in Clojure?
Hamza Yerlikaya has already made the most important point, which is that Clojure code is always compiled. I'm just adding an illustration and some information on some low-hanging fruit for your optimisation efforts.
Firstly, the above point about Clojure's code always being compiled includes closures returned by higher-order functions and functions created by calling eval on fn / fn* forms and indeed anything else that can act as a Clojure function. Thus you don't need a separate DSL to describe functions, just use higher order functions (and possibly macros):
(defn make-affine-function [a b]
(fn [x] (+ (* a x) b)))
((make-affine-function 31 47) 5)
; => 202
Things would be more interesting if your specs were to include information about the types of parameters, as then you could be interested in writing a macro to generate code using those type hints. The simplest example I can think of would be a variant of the above:
(defmacro make-primitive-affine-function [t a b]
(let [cast #(list (symbol (name t)) %)
x (gensym "x")]
`(fn [~x] (+ (* ~(cast a) ~(cast x)) ~(cast b)))))
((make-primitive-affine-function :int 31 47) 5)
; => 202
Use :int, :long, :float or :double (or the non-namespace-qualified symbols of corresponding names) as the first argument to take advantage of unboxed primitive arithmetic appropriate for your argument types. Depending on what your function's doing, this may give you a very significant performance boost.
Other types of hints are normally provided with the #^Foo bar syntax (^Foo bar does the same thing in 1.2); if you want to add them to macro-generated code, investigate the with-meta function (you'll need to merge '{:tag Foo} into the metadata of the symbols representing the formal arguments to your functions or let-introduced locals that you wish to put type hints on).
Oh, and in case you'd still like to know how to implement your original idea...
You can always construct the Clojure expression to define your function -- (list 'fn ['x] (a-magic-function-to-generate-some-code some-args ...)) -- and call eval on the result. That would enable you to do something like the following (it would be simpler to require that the spec includes the parameter list, but here's a version assuming arguments are to be fished out from the spec, are all called paramFOO and are to be lexicographically sorted):
(require '[clojure.walk :as walk])
(defn compile-spec [spec]
(let [params (atom #{})]
(walk/prewalk
(fn [item]
(if (and (symbol? item) (.startsWith (name item) "param"))
(do (swap! params conj item)
item)
item))
spec)
(eval `(fn [~#(sort #params)] ~#spec))))
(def my-spec '[(+ (* 31 param0) 47)])
((compile-spec my-spec) 5)
; => 202
The vast majority of the time, there is no good reason to do things this way and it should be avoided; use higher-order functions and macros instead. However, if you're doing something like, say, evolutionary programming, then it's there, providing the ultimate flexibility -- and the result is still a compiled function.
Even if you don't AOT compile your code, as soon as you define a function it gets compiled to bytecode on the fly.

Categories