clojure struct with java

45 views
Skip to first unread message

Diego Pacheco

unread,
Oct 13, 2011, 8:33:21 PM10/13/11
to Clojure
Hi guys,

I’m trying to call Clojure from Java(I already managed to do it
compiling Clojure using :gen-class  ).

I want call Clojure using Java without compiling Clojure… I’m having
issues with my structs they are not behaving in the way that I want, I
tested the Clojure code on REPL and it seems to be ok...

I Guess is something that I’m doing in java(possibly wrong )

[company.clj]

(ns user)

(def employees (ref []))

(defstruct employee :name :age :role :salary)

(defn hire[e]
(dosync (alter employees conj e))
)

(defn print-employee[e]
(prn (str "Name: " (:name e) " - Age: " (:age e)
" - Role: " (:role e) " - Salary:" (:salary e)
)
)
)

(defn print-employees[]
(for [i (range (count @employees))]
(print-employee (employees i))
)
)

[JavaCallsClojureInterpreted.java]

import clojure.lang.RT;
import clojure.lang.Var;

/**
*
* @author Diego Pacheco
*
*/
public class JavaCallsClojureInterpreted {

public static void main(String args[]) throws
Throwable{
try{

RT.loadResourceScript("company.clj");

Var struct = RT.var("clojure.core",
"struct","employee :diego 10 :coach 1000");

Var hire = RT.var("user", "hire");
Object r = hire.invoke(struct);
System.out.println(r);

Var printee = RT.var("user", "print-employee");
Object r2 = printee.invoke(struct);
System.out.println(r2);

Var print = RT.var("user", "print-employees");
Object result = print.invoke();
System.out.println(result);

}catch(Exception e){
e.printStackTrace();
}
}

}

This code produce the following output:

[#'clojure.core/struct]
"Name: - Age: - Role: - Salary:"
null
"Name: - Age: - Role: - Salary:"
clojure.lang.LazySeq@1f

Any Clue ?

Thanks for your help.

Cheers,
Diego Pacheco
@diego_pacheco

Alexander Taggart

unread,
Oct 14, 2011, 2:58:20 AM10/14/11
to clo...@googlegroups.com
I suspect this...

Var struct = RT.var("clojure.core", "struct","employee :diego 10 :coach 1000"); 

isn't doing what you think it will.  That will set the root binding of clojure.core/struct to the string you gave it.  you probably want to get the var for the struct function, and then invoke it with the arguments to create an employee struct instance.

Diego Pacheco

unread,
Oct 17, 2011, 12:23:37 AM10/17/11
to Clojure

You Right! BUT still does not work.

I tried:

Var type = RT.var("clojure.core","type");
Object oType = type.invoke("employee");

Var struct = RT.var("clojure.core", "struct-map");
Object oStruct = struct.invoke(oType,"Diego",26,"Coach",1000);

Var hire = RT.var("user", "hire");
Object r = hire.invoke(oStruct);
System.out.println(r);

......

I got the exception:

java.lang.ClassCastException: java.lang.Class cannot be cast to
clojure.lang.PersistentStructMap$Def
at clojure.core$struct_map.doInvoke(core.clj:3128)
at clojure.lang.RestFn.invoke(RestFn.java:486)
at clojure.lang.Var.invoke(Var.java:381)
at
com.github.diegopacheco.sandbox.java.clojure.JavaCallsClojureInterpreted.main(JavaCallsClojureInterpreted.java:
42)


.............


When I do:

Var struct = RT.var("clojure.core", "create-
struct");
Object oStruct = struct.invoke("employee","Diego",26,"Coach",
1000);

Var hire = RT.var("user", "hire");
Object r = hire.invoke(oStruct);
System.out.println(r);

Var printee = RT.var("user", "print-employee");
Object r2 = printee.invoke(oStruct);
System.out.println(r2);

Var print = RT.var("user", "print-employees");
Object result = print.invoke();
System.out.println(result);


............

I GOT:

[#<Def clojure.lang.PersistentStructMap$Def@6b6ac8>]
"Name: - Age: - Role: - Salary:"
null
"Name: - Age: - Role: - Salary:"
clojure.lang.LazySeq@1f

...........

When I DO:

Var struct = RT.var("clojure.core", "create-struct");
Object oStruct = struct.invoke("employee","Diego",26,"Coach",
1000);

Var employee = RT.var("clojure.core", "struct");
Object oEmployee = employee.invoke(oStruct);

Var hire = RT.var("user", "hire");
Object r = hire.invoke(oEmployee);
System.out.println(r);

Var printee = RT.var("user", "print-employee");
Object r2 = printee.invoke(oEmployee);
System.out.println(r2);

Var print = RT.var("user", "print-employees");
Object result = print.invoke();
System.out.println(result);

.......


I Got:

[{"employee" nil, "Diego" nil, 26 nil, "Coach" nil, 1000 nil}]
"Name: - Age: - Role: - Salary:"
null
"Name: - Age: - Role: - Salary:"
clojure.lang.LazySeq@1f


I'm loosing my hope, does anybody used this feature before ? Any idea
what I'm doing wrong ?

Cheers,
@diego_pacheco

Diego Pacheco

unread,
Oct 17, 2011, 1:49:57 AM10/17/11
to Clojure

I found the Solution. !!!! :-)

I hope it help other people with the same issues, this worked out for
me. I read clojure code on github and java code as well after some
time struggling with the objects and functions I found this solution:

package com.github.diegopacheco.sandbox.java.clojure;

import clojure.lang.RT;
import clojure.lang.Var;

/**
*
* @author Diego Pacheco
*
*/
public class JavaCallsClojureInterpreted {

private static final Var seq = RT.var("clojure.core",
"seq");
private static final Var type = RT.var("clojure.core",
"type");
private static final Var keyword = RT.var("clojure.core",
"keyword");
private static final Var hashMap = RT.var("clojure.core", "hash-
map");
private static final Var structMap = RT.var("clojure.core",
"struct-map");

public static void loadClojureScript(String script){
try {
RT.loadResourceScript(script);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public static Object buildKeyword(String k){
try {
return keyword.invoke(k);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public static Object buildSeq(Object o){
try {
return seq.invoke(o);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public static Object buildUserTypeDef(String ns,String structDefName)
{
try {
Var userType = RT.var(ns, structDefName);
return userType.get();
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public static Var buildUserFunction(String ns,String func){
try {
return RT.var(ns, func);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public static Object infoType(Object o){
try {
return type.invoke(o);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public static Object buildHashMap(Object... mapArgs){
try {
Object userSeq = buildSeq(mapArgs);
return hashMap.applyTo((clojure.lang.ISeq)userSeq);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public static void main(String args[]) throws Throwable{
try{

loadClojureScript("company.clj");

Object employeeStructDef = buildUserTypeDef("user","employee");
System.out.println(infoType(employeeStructDef));

Object oEmployee =
structMap.invoke(employeeStructDef,buildKeyword("name"),"Diego",buildKeyword("age"),
26,

buildKeyword("role"),"Coach",buildKeyword("salary"),1000);
System.out.println(oEmployee);

Var hire = buildUserFunction("user", "hire");
Object r = hire.invoke(oEmployee);
System.out.println(r);

Var printee = buildUserFunction("user", "print-employee");
Object r2 = printee.invoke(oEmployee);
System.out.println(r2);

Var print = buildUserFunction("user", "print-employees");
Object result = print.invoke();
System.out.println(result);

}catch(Exception e){
e.printStackTrace();
}
}

}

Cheers,
@diego_pacheco
Reply all
Reply to author
Forward
0 new messages