2
votes

I am getting into Clojure and Grammatical Evolution at the same time and discovered GEVA, which is a GE tool written in Java. I have no background in Java. So I don't have to re-invent the wheel, how can I integrate GEVA into Clojure?

I can execute the default script from the CLI with: java -jar GEVA.jar -main_class Main.Run

The GEVA source directory has the following subdirectories with packages named after the directory: Algorithm com Exceptions FitnessEvaluation Fractal Individuals Main Mapper Operator Parameter UI Util

The Main subdirectory has the following files and tutorial subdir: AbstractRun.java Experiment.java Run.java State.java Tutorials

The following classes are in the Run.java file: public class Run extends AbstractRun public Run() public void experiment(String[] args) public void setup(String[] args) private void setSeed() public static void main(String[] args)

From what I can tell, the static method 'main' in class Main.Run is what I want to execute. However when I try to follow the Java interop instructions, I am getting errors.

clgeva.test=> (.Main.Run/main)
java.lang.Exception: No such namespace: .Main.Run (NO_SOURCE_FILE:5)
clgeva.test=> (.Main.Run/main "")
java.lang.Exception: No such namespace: .Main.Run (NO_SOURCE_FILE:6)

I'm obviously not importing the namespace correctly to run the main function.

user=> (import Main)
java.lang.ClassNotFoundException: Main (NO_SOURCE_FILE:1)
user=> (import Main.Run)
Main.Run
user=> (main)
java.lang.Exception: Unable to resolve symbol: main in this context (NO_SOURCE_FILE:3)
user=> (.Main.Run/main)
java.lang.Exception: No such namespace: .Main.Run (NO_SOURCE_FILE:4)

What the heck am I doing wrong? I am sure I'm just missing something obvious, but I've been banging my head on it for a little while and need some direction. Thanks.

3

3 Answers

2
votes

First, make sure you are loading the GEVA lib correctly - see http://clojure.org/libs I'm guessing, from the java.lang.ClassNotFoundException error, that GEVA is not on your classpath.

Then you want to look at the Clojure documentation for Java interop: http://clojure.org/java_interop

1
votes

You have the right idea, but you do have some syntax errors.

clgeva.test=> (.Main.Run/main)

Should have a space between the dot operator and the Main.Run/main reference. As it is, it's trying to find something called ".Main.Run" which obviously doesn't exist. Do it like so:

clgeva.test=> (. Main.Run/main)

Assuming you have your classpath set up correctly, it should work.

Importing the class using (import ...) and calling (main) won't work because main is a static method.

1
votes

The syntax for calling a static method with no arguments (I'll use an example that everyone has access to) is:

=> (java.lang.System/currentTimeMillis)
1284574337322

The above form is preferred, but the following is also possible, and can be useful in macros:

=> (. java.lang.System currentTimeMillis)
1284574477369

In this case, "java.lang." may be omitted, but I'm including it to match your case more closely.

=> (System/currentTimeMillis)
1284574617771

Adding a dot to the first form will not work, whether with or without a space:

user=> (.System/currentTimeMillis) 
java.lang.Exception: No such namespace: .System (NO_SOURCE_FILE:44)
user=> (. System/currentTimeMillis)
java.lang.IllegalArgumentException: Malformed member expression, expecting (. target member ...) (NO_SOURCE_FILE:45)