Home > Mobile >  Running script with `Lein run`and `Clojure -M` hang. Works in REPL
Running script with `Lein run`and `Clojure -M` hang. Works in REPL

Time:09-15

$ lein --version
Leiningen 2.9.10 on Java 17.0.4.1 OpenJDK 64-Bit Server VM
$ clojure -version
Clojure CLI version 1.11.1.1155
$ java -version
openjdk version "17.0.4.1" 2022-08-12
OpenJDK Runtime Environment (build 17.0.4.1 1)
OpenJDK 64-Bit Server VM (build 17.0.4.1 1, mixed mode)

I have some very basic code I'm trying to run.

(use '[clojure.java.shell :only [sh]])
(defn -main [] (sh "echo" "Hello, World!"))
(-main)

In a REPL, this predictably returns

{:exit 0, :out "Hello, World!\n", :err ""}

However, when that is the contents of a script (verbatim), clojure -M just hangs. Uncommenting the ns and trying to run this as a project with lein run produces the same behavior.

I've also tried with requires :refer and putting that in with the namespace. I've tried explicitly printing stdout with (print (:out (sh "echo" "stuff"))).

My project.clj:

(defproject findbad "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :dependencies [[org.clojure/clojure "1.11.1"]]
  :source-paths ["."]
  :repl-options {:init-ns findbad}
  :main findbad)

and .lein/profile.clj:

{:user {:plugins [
                  [lein-try "0.4.3"]
                  [flat-layout/lein-template "1.6.0"]
                  [simple-layout/lein-template "0.1.0"]]}}

I can get the following to run with clojure -M, but lein run -main now throws errors (an improvement?).

(ns findbad
  (:gen-class))

(use '[clojure.java.shell :only [sh]])

(defn -main [] (print "Hello, World"))

(-main)
{:clojure.main/message
 "Execution error (ArityException) at user/eval140 (form-init17641850740462455309.clj:1).\nWrong number of args (1) passed to: findbad/-main\n",
 :clojure.main/triage
 {:clojure.error/class clojure.lang.ArityException,
  :clojure.error/line 1,
  :clojure.error/cause
  "Wrong number of args (1) passed to: findbad/-main",
  :clojure.error/symbol user/eval140,
  :clojure.error/source "form-init17641850740462455309.clj",
  :clojure.error/phase :execution},
 :clojure.main/trace
 {:via
  [{:type clojure.lang.Compiler$CompilerException,
    :message
    "Syntax error macroexpanding at (/tmp/form-init17641850740462455309.clj:1:74).",
    :data
    {:clojure.error/phase :execution,
     :clojure.error/line 1,
     :clojure.error/column 74,
     :clojure.error/source "/tmp/form-init17641850740462455309.clj"},
    :at [clojure.lang.Compiler load "Compiler.java" 7665]}
   {:type clojure.lang.ArityException,
    :message "Wrong number of args (1) passed to: findbad/-main",
    :at [clojure.lang.AFn throwArity "AFn.java" 429]}],
  :trace
  [[clojure.lang.AFn throwArity "AFn.java" 429]
   [clojure.lang.AFn invoke "AFn.java" 32]
   [clojure.lang.Var invoke "Var.java" 384]
   [user$eval140 invokeStatic "form-init17641850740462455309.clj" 1]
   [user$eval140 invoke "form-init17641850740462455309.clj" 1]
   [clojure.lang.Compiler eval "Compiler.java" 7194]
   [clojure.lang.Compiler eval "Compiler.java" 7184]
   [clojure.lang.Compiler load "Compiler.java" 7653]
   [clojure.lang.Compiler loadFile "Compiler.java" 7591]
   [clojure.main$load_script invokeStatic "main.clj" 475]
   [clojure.main$init_opt invokeStatic "main.clj" 477]
   [clojure.main$init_opt invoke "main.clj" 477]
   [clojure.main$initialize invokeStatic "main.clj" 508]
   [clojure.main$null_opt invokeStatic "main.clj" 542]
   [clojure.main$null_opt invoke "main.clj" 539]
   [clojure.main$main invokeStatic "main.clj" 664]
   [clojure.main$main doInvoke "main.clj" 616]
   [clojure.lang.RestFn applyTo "RestFn.java" 137]
   [clojure.lang.Var applyTo "Var.java" 705]
   [clojure.main main "main.java" 40]],
  :cause "Wrong number of args (1) passed to: findbad/-main",
  :phase :execution}}

How am I getting a "wrong number of args"? I'm passing nothing to a function that takes nothing.

Even if I could get that (print "Hello, World") example to work, that's not what I'm interested in.

edit: Okay, I'm not sure what I did differently, but I can get it to work with (print (:out (sh "echo" "stuff"))). Also, the hanging was fixed with (shutdown-agents).

CodePudding user response:

Your main function accepts no arguments ([]). Clojure invokes -main from cli with list of command line arguments causing arity exception. Try adding & args to -main arguments vector:

(defn -main [& args] (print "Hello, World"))
  • Related