Problem with gen-class, cannot get basic stuff to work


In my top level project folder, “Searchbar” I have a deps.edn file:

{:paths ["src" "test" "classes"]
 :deps {org.openjfx/javafx-controls {:mvn/version "15-ea+2"}
        org.openjfx/javafx-base {:mvn/version "15-ea+2"}
        org.openjfx/javafx-graphics {:mvn/version "15-ea+2"}
        org.openjfx/javafx-fxml {:mvn/version "15-ea+2"}}}

In my src/searchbar/core.clj file:

(ns searchbar.core)

(import (javafx.application.Application)

(gen-class :name "searchbar.JfxGUI" :extends [javafx.application.Application])

(defn -start [stage]
  (println "Inside the start function"))
(defn -main [& args]
  (println "Inside main")

When I try to run this with:

clojure -m searchbar.core

Syntax error macroexpanding clojure.core/import at (searchbar/core.clj:3:1).
javafx.application.Application - failed: #{(quote quote)} at: [:class :quoted-spec :quote] spec: :clojure.core.specs.alp
() - failed: Insufficient input at: [:package-list :spec :classes] spec: :clojure.core.specs.alpha/package-list
javafx.application.Application - failed: #{(quote quote)} at: [:package-list :quoted-spec :quote] spec: :clojure.core.sp
(javafx.application.Application) - failed: simple-symbol? at: [:class :spec] spec: :clojure.core.specs.alpha/quotable-im

Could anyone shed some light over what I’m doing wrong? It feels like I’m missing syntax but I’m not sure.

One problem is that you need to separate the classes from their packages when using import: (import (java.util Date)), not (import (java.util.Date)).

See for more examples.

In general, while you can call import, require and gen-class as functions, it is usually a good idea to include them in the namespace declaration: (ns (:import (java.util Date)) (:gen-class)). Note that they are keywords in this case.

Ah, I seem to have missed that. Reading the doc there is indeed a space between package and class.

But in the first example below the description:

(import java.util.Date)

Soo… confused.

Thank you.

Edit: The reason I’m doing it explicitly is because I’m just learning the basics. It feel intuitive easier to call import, require, gen-class. Like you mention, It seems the standard way is to use keywords from what I’ve seen at other sources, but I have not quite yet grasped the fundamentals yet (obviously)(like, I thought you only used keywords with maps {}, but here it is in list forms. Anyway. Much to learn.

Ya, this is one of the quirks of Clojure, the require and import clauses have a bit of an inconsistent non-intuitive syntax.

import can take one or more “import symbol” or “import list” where an import symbol is a fully qualified package.class like java.util.Date. Or where an import list is a list like (package class1 class2 class3).

1 Like

Thank you for clearing that up.

The stand-alone import takes a literal list (you must quote it), while the ns form takes an embedded :import clause without a quote. The error message in the original post was telling you that the import expected a literal list.

You can write either

(ns searchbar.core
  (:import (javafx.application Application)
     ;; etc        


(ns searchbar.core)
(import '(javafx.application Application)
     ;; etc        

Ah, yes, thank you. It starts to get clearer now.

One thing I did not realize, is that you have to compile the code first. I’m using emacs/cider, so when I just evaluate my buffer, I will get a ClassNotFound on searchbar.core. Now, If go the repl, call the compile function, change into the my namespace, voila, It works. To be fair, that is in the docs somewhere, just a lot of examples on the interweb where it is simply not mentioned. You kinda get spoiled in the beginning learning clojure, just living in the repl, even if you have a file/buffer, you just send it to the repl. As soon as you go into interop, things change.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.