am new at clojure and would like to interact with java objects using clojure. If I have well understood,
one can reach this interaction using defprotocol.
What I concretely try to do is the following:
1- I have following java class
package mytestspackage;
public class TestObject {
private String lastName;
private String firstName;
private String age;
public TestObject(String lastName, String firstname, String age) {
super();
this.lastName = lastName;
this.firstName = firstname;
this.age = age;
}
public String getName() {
return this.lastName;
}
public void setName(String name) {
this.lastName = name;
}
public String getFirstname() {
return this.firstName;
}
public void setFirstname(String vorname) {
this.firstName = vorname;
}
public String getAge() {
return this.age;
}
public void setAge(String age) {
this.age = age;
}
}
2- I create a clojure protocol that should allow me to access to instances of the above java class TestObject
(ns mytestspackage)
(defprotocol Test
(first-name [t])
(last-name [t])
(age [t]))
Now my question is: where do I concretly implement the methods defined in the protocol and how do I use this implementation to pass TestObject instances to the clojure side and access to values like first name, last name etc...
Any help would be appreciated.
Thanks in advance.
Regards, Horace
If I have well understood, one can reach this interaction using
defprotocol.
No, you've got it wrong. Protocols are intended to allow things similar to what interfaces allow in plain java (though more powerful). You can access your Java class without any protocols. Official clojure documentation on this topic: http://clojure.org/java_interop
Example:
(ns example
(:import mytestpackage.TestObject))
;; This is how we call methods on java objects
(defn first-name [obj]
(.getFirstname obj))
(defn last-name [obj]
(.getName obj))
(defn age [obj]
(.getAge obj))
(defn set-first-name [obj name]
(.setFirstname obj name))
(defn set-last-name [obj name]
(.setName obj name))
(defn set-age [obj age]
(.setAge obj age))
;; In REPL
example => (let [x (TestObject. nil nil nil) ;; This is how we create Java objects
x (new TestObject nil nil nil)] ;; These expressions are equivalent
(println (first-name x))
(set-first-name x "Name")
(println (first-name x))
(set-last-name x "Last name")
(set-age x "23")
(println (last-name x))
(println (age x)))
;; Outputs
nil
Name
Last name
23
Please note that this code is nothing more than example intended to introduce java interop. By no means you should write real programs like that, especially if they are mostly in Clojure.
If you just want to interact with java objects using Clojure and not implement new functionality on them you don't need to worry about protocols. Clojure provides direct access and syntax for java method calls.
For example strings in Clojure are java.lang.String objects:
user=> (type "Really a Java String")
;; java.lang.String
user=> (.toUpperCase "Really a java string")
;;=> "REALLY A JAVA STRING"
Provided your test object class is on the classpath you can create instances like so:
user=> (def a-test-object (mytestpackage/TestObject. "lastName" "firstName" 42))
And call methods like:
user=> (.getAge a-test-object)
See http://clojure.org/java_interop for more info.
Related
There is a standard function clojure.core/bean converting POJO to map:
class MyPojo{
public String getFirst(){ return "abc"; }
public int getSecond(){ return 15; }
}
IFn bean = Clojure.var("clojure.core", "bean")
var result = bean.invoke(new MyPojo())
// result => {:first = abc, :second = 15}
For Java 17 record classes this function would not work, because records do not follow POJO convention "get***" for properties.
Is there Clojure support for Java 17 record instances in the same manner?
Java 16 introduces Class.getRecordComponents. So given an instance of a record, you can look up the record's class, and from there its record components. Each record component has a name and a getter Method, which you can use to look up the value of that component. You can put these pieces together to build an analogue of bean.
(defn record->map [r]
(into {} (for [^java.lang.reflect.RecordComponent c (seq (.getRecordComponents (class r)))]
[(keyword (.getName c))
(.invoke (.getAccessor c) r nil)])))
I am taking an example from the clojure site.
(defmulti foo class)
(defmethod foo ::collection [c] :a-collection)
(defmethod foo String [s] :a-string)
(foo [])
:a-collection
(foo (java.util.HashMap.))
:a-collection
(foo "bar")
:a-string
This functionality is cool. I'm trying to understand the technical reasons why this is superior to an instanceof based implementation in (for example) java. It seems to me essentially equivalent in function with nicer syntax.
public <T> String foo(final T t) {
if (t instanceof Collection) {
return "a-collection";
} else if (t instanceof String) {
return "a-string";
} else {
throw new IllegalArgumentException("Undefined - no available dispatch");
}
}
What are the reasons why multimethods are considered a great alternative to visitor pattern based double dispatch while instanceof is not when they seem like they're essentially doing the same thing?
One of the benefits discussed in the comments is that the defmulti and defmethod can be done in different files, by different users. An excellent example is Clojure's own print-method multi-method.
From the docs, we see how we can define a custom print-method for a new record type we create:
(deftype XYZ [])
; without custom print-method defined:
user=> (prn (XYZ.))
#<XYZ user.XYZ#2670d85b>
; Note, this hooks into the pre-existing `(defmulti print-method ...)`
(defmethod print-method XYZ [v ^java.io.Writer w]
(.write w "<<-XYZ->>"))
; with print-method
user=> (prn (XYZ.))
<<-XYZ->>
So while it has similarity to a giant cond statement, it is more flexible & cleaner.
I am doing a library in ClojureScript that will expose a public JavaScript API. Since it has to mimic the API of an existing JavaScript library, I would like to present the same kind of fluent API :
myLib.prepareToDo()
.something()
.and('also')
.somethingElse()
.run(function(err, result) {
console.log("yay!");
});
In Javascript, one could create a fluent API like this site point):
var MyClass = function(a) {
this.a = a;
}
MyClass.prototype.foo = function(b) {
// Do some complex work
this.a += Math.cos(b);
return this;
}
I can then call it like :
var obj = new MyClass(5);
obj.foo(1).foo(2).foo(3);
Now, as far as I know, there is no notion of this in ClojureScript, although apparently it is possible to access it this-as.
I don't get how to use it though, hence my question.
How can I create a fluent interface in ClojureScript ?
(defrecord) and this answer to the rescue. Extending the "magic" protocol Object to our record or type causes the defined methods to appear as member functions in the JavaScript object. To enable the "fluent interface", some methods return an instance of MyClass.
(defrecord MyClass [a b]
Object
(something [this] this)
(and-then [this s] (assoc this :a s))
(something-else [this] (assoc this :b (str a "-" a)))
(run [this f] (f a b)))
Then we can have a JavaScript client like so:
var myClass = new my_namespace.core.MyClass();
myClass.something()
.and_then("bar")
.something_else()
.run(function(a, b) {
console.log(a + " - " + b) });
I am trying to get javafx2 working with Clojure - In implementing an abstract class such as DoubleBinding, I am unsure what the equivalent of super.bind(moo) is in Clojure. The class I am implementing can be found here: http://docs.oracle.com/javafx/2/api/index.html.
(def moo (ObservableDoubleValue. ...))
(def foo (proxy [DoubleBinding] []
(computeValue []
(Math/sqrt (.getValue moo)))))
final ObservableDoubleValue moo = ...;
DoubleBinding foo = new DoubleBinding() {
{
super.bind(moo);
}
#Override
protected double computeValue() {
return Math.sqrt(moo.getValue());
}
};
According to proxy documentation, methods in proxy has no access to super... I would recommend you to generate class using gen-class and use it. You can access to super's methods if you'll expose them with :exposes-methods directive. Something, like:
(gen-class :name MyDoubleBinding
:extends DoubleBinding
:exposes-methods {bind my-bind}
....
)
and then call -my-bind from your constructor...
Please, check documentation about class generation on Clojure's site for more details on gen-class
I recently asked why interfaces and protocols could be incompletely implemented in clojure:
user=> (defprotocol P (foo [self]))
P
user=> (extend-type Long P)
nil
user=> (extends? P Long)
true
user=> (foo 1)
IllegalArgumentException No implementation of method: :foo of protocol: #'user/P found for class: java.lang.Long clojure.core/-cache-protocol-fn (core_deftype.clj:527)
and was told that this was for interop reasons and that it wouldn't be a problem in practice. Sure.
But apparently extends? really tells me nothing about the relationship between a protocol and a class: just as (extends? P C) does not imply that I can call foo on objects of class C, (not (extends? P C)) does not imply that I cannot call foo on objects of class C:
user=> (defprotocol P (foo [self]))
P
user=> (extend-type Object P (foo [self] 1))
nil
user=> (extends? P Long)
false
user=> (foo 1)
1
Now I am very confused about what information extends? is supposed to give me... satisfies?, on the other hand, handles the second case correctly, but not the first one.
When in doubt check the code :). The implementation of extends? is this:
(defn extends?
"Returns true if atype extends protocol"
{:added "1.2"}
[protocol atype]
(boolean (or (implements? protocol atype)
(get (:impls protocol) atype))))
So it just check if the atype has been extended by the protocol and it doesn't mean it has implemented all the methods of the protocol.
The :impls is a map where key is the type that extended the protocol and the value is map which has the methods implementation of the protocol for the type.
user=> (defprotocol hello (a [self]))
hello
user=> (:impls hello)
nil
user=> (extend-type String hello)
nil
user=> (:impls hello)
{java.lang.String {}}
user=> (extend-type String hello (a [self] 10))
nil
user=> (:impls hello)
{java.lang.String {:a #<user$eval613$fn__614 user$eval613$fn__614#1d978ea>}}
On the other hand to satisfies? you need to pass the object on which you want to check for protocol and not the type as in case of extends? So if you look at satisfies? code it is a bit more complex then extends as it has to check the base classes of the object being passed for being extended by protocol. But both the functions just check whether there the type (or base types) has extended the protocol or not AND they don't check if you have actually implemented the protocol methods or not.