Search code examples
clojurejvm

Why I am getting Error compiling in Clojure?


I have recently started to work with Clojure. When I run a program in lein, I get the below error:

Exception in thread "main" Syntax error compiling at (bioavailability.clj:79:36).
        at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3707)
        at clojure.lang.Compiler$DefExpr.eval(Compiler.java:457)
        at clojure.lang.Compiler.eval(Compiler.java:7181)
        at clojure.lang.Compiler.load(Compiler.java:7635)
        at clojure.lang.RT.loadResourceScript(RT.java:381)
        at clojure.lang.RT.loadResourceScript(RT.java:372)
        at clojure.lang.RT.load(RT.java:463)
        at clojure.lang.RT.load(RT.java:428)
        at clojure.core$load$fn__6824.invoke(core.clj:6126)
        at clojure.core$load.invokeStatic(core.clj:6125)
        at clojure.core$load.doInvoke(core.clj:6109)
        at clojure.lang.RestFn.invoke(RestFn.java:408)
        at clojure.core$load_one.invokeStatic(core.clj:5908)
        at clojure.core$load_one.invoke(core.clj:5903)
        at clojure.core$load_lib$fn__6765.invoke(core.clj:5948)
        at clojure.core$load_lib.invokeStatic(core.clj:5947)
        at clojure.core$load_lib.doInvoke(core.clj:5928)
        at clojure.lang.RestFn.applyTo(RestFn.java:142)
        at clojure.core$apply.invokeStatic(core.clj:667)
        at clojure.core$load_libs.invokeStatic(core.clj:5985)
        at clojure.core$load_libs.doInvoke(core.clj:5969)
        at clojure.lang.RestFn.applyTo(RestFn.java:137)
        at clojure.core$apply.invokeStatic(core.clj:667)
        at clojure.core$require.invokeStatic(core.clj:6007)
        at clojure.core$require.doInvoke(core.clj:6007)
        at clojure.lang.RestFn.invoke(RestFn.java:408)
        at clojush.core$_main.invokeStatic(core.clj:40)
        at clojush.core$_main.doInvoke(core.clj:26)
        at clojure.lang.RestFn.invoke(RestFn.java:408)
        at clojure.lang.Var.invoke(Var.java:384)
        at user$eval140.invokeStatic(form-init8949943542898746617.clj:1)
        at user$eval140.invoke(form-init8949943542898746617.clj:1)
        at clojure.lang.Compiler.eval(Compiler.java:7176)
        at clojure.lang.Compiler.eval(Compiler.java:7166)
        at clojure.lang.Compiler.load(Compiler.java:7635)
        at clojure.lang.Compiler.loadFile(Compiler.java:7573)
        at clojure.main$load_script.invokeStatic(main.clj:452)
        at clojure.main$init_opt.invokeStatic(main.clj:454)
        at clojure.main$init_opt.invoke(main.clj:454)
        at clojure.main$initialize.invokeStatic(main.clj:485)
        at clojure.main$null_opt.invokeStatic(main.clj:519)
        at clojure.main$null_opt.invoke(main.clj:516)
        at clojure.main$main.invokeStatic(main.clj:598)
        at clojure.main$main.doInvoke(main.clj:561)
        at clojure.lang.RestFn.applyTo(RestFn.java:137)
        at clojure.lang.Var.applyTo(Var.java:705)
        at clojure.main.main(main.java:37)
Caused by: java.lang.IllegalArgumentException: No matching method findResource found taking 1 args for class jdk.internal.loader.ClassLoaders$AppClassLoader
        at clojure.lang.Reflector.invokeMatchingMethod(Reflector.java:127)
        at clojure.lang.Reflector.invokeInstanceMethod(Reflector.java:102)
        at local_file$find_resource.invokeStatic(local_file.clj:30)
        at local_file$find_resource.invoke(local_file.clj:26)
        at local_file$project_dir.invokeStatic(local_file.clj:39)
        at local_file$project_dir.invoke(local_file.clj:34)
        at local_file$project_dir.invokeStatic(local_file.clj:47)
        at local_file$project_dir.invoke(local_file.clj:34)
        at local_file$file_STAR_.invokeStatic(local_file.clj:55)
        at local_file$file_STAR_.invoke(local_file.clj:51)
        at local_file$slurp_STAR_.invokeStatic(local_file.clj:60)
        at local_file$slurp_STAR_.doInvoke(local_file.clj:57)
        at clojure.lang.RestFn.invoke(RestFn.java:410)
        at clojush.problems.regression.bioavailability$read_data.invokeStatic(bioavailability.clj:51)
        at clojush.problems.regression.bioavailability$read_data.invoke(bioavailability.clj:49)
        at clojush.problems.regression.bioavailability$define_fitness_cases.invokeStatic(bioavailability.clj:63)
        at clojush.problems.regression.bioavailability$define_fitness_cases.invoke(bioavailability.clj:57)
        at clojure.lang.AFn.applyToHelper(AFn.java:152)
        at clojure.lang.AFn.applyTo(AFn.java:144)
        at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3702)
        ... 46 more

The code I am trying to run is:

https://github.com/lspector/Clojush/blob/master/src/clojush/problems/regression/bioavailability.clj

and the command that I use is:

lein run clojush.problems.regression.bioavailability

Thanks in advance for your kind help.

I tried to run each section of the main code seperately to understand where the problem exactly is but it was not succesful.


Solution

  • The problem is that the code in bioavailability.clj calls the function find-resource that in turn calls a method findResource that (i) is protected and (ii) expects a string but is passed a File.

    To fix this, I did two things:

    First, copied the function find-resource from the local-file library and renamed it get-resource and replaced the call to findResource by a call to getResource which is public. I inserted this code just above the read-data function in bioavailability.clj.

    Second, I changed a line in read-data that calls the slurp* (that was (slurp* "src/clojush/problems/regression/data/bioavailability.txt")) function to instead call (slurp (get-resource "../src/clojush/problems/regression/data/bioavailability.txt")) by calling slurp on the result of the get-resource function to which I pass a path that I have prepended with ../. The prepended path is relative to the default resources directory.

    The modified code is

    ;; I added this function
    (defn get-resource
      [file]
      (loop [cl (.. Thread currentThread getContextClassLoader)]
        (when cl
          (if-let [url (.getResource cl file)]
            url
            (recur (.getParent cl))))))
    
    (defn read-data []
      "Reads data from data/bioavailability.txt into a sequence of sequences."
    
      ;; This line has been updated:
      (let [f (slurp (get-resource "../src/clojush/problems/regression/data/bioavailability.txt"))
    
            lines (csv/parse-csv f :delimiter \tab)]
        (map #(map (fn [x] (float (read-string x)))
                   %)
             lines)))