简体   繁体   中英

Parse Clojure Command Line Args

I am trying to separate my cli options into a stand-alone namespace for starting up an HTTP server, and I am getting this error-

 clojure.lang.ArraySeq cannot be cast to java.lang.CharSequence

In main.clj , this code works fine-

(ns served.main
  (:require [org.httpkit.server :refer [run-server]]
    [served.app.core :refer [handler]]
    [served.server.cli-options :refer [set-options]]
    [clojure.tools.cli :refer [parse-opts]])
    (:gen-class))

(def cli-options
 [
  ["-p" "--port PORT" "Port number"
  :default 5000 
  :parse-fn #(Integer/parseInt %)
  :validate [#(< 0 % 0x10000) "Must be a number between 0 and 65536"]]
  ])  

(defn -main [& args]
  (println "Server starting")
  (let [options (get (parse-opts args cli-options) :options)]
  ;;(let [options (set-options args)]
  (println (str options))
  (run-server handler options))) 

It will work with the default options in (def cli-options) and it compiles correctly if I pass in arguments, such as -p 7000 .

When I call the main function with the external namespace served.server.cli-options instead of clojure.tools.cli directly (ie switch the comment in main ), I get the error only when passing in args.

That is, starting the server without arguments, eg lein run compiles fine and will print out the defaults. The error comes with lein run -p 7000 .

After deleting (def cli-options) in main to avoid any global conflict, here is served.server.cli-options

(ns served.server.cli-options
  (:require [clojure.tools.cli :refer [parse-opts]]))

(def cli-options
  [
    ["-p" "--port PORT" "Port number"
    :default 5000 
    :parse-fn #(Integer/parseInt %)
    :validate [#(< 0 % 0x10000) "Must be a number between 0 and 65536"]]
  ])  

(defn set-options [& args]
  (let [options (get (parse-opts args cli-options) :options)]
  (println (str options))  
  options))

So far as I can tell, I copied the contents to the new namespace correctly. Here are the docs for parse-opts , here is the example that I am drawing from, and a similar but different SO issue here .

My question - how are the CLI args being transformed to throw casting error, and how do I fix it?

Any help would be greatly appreciated.

Delete the & in:

(defn set-options [& args]

& wraps up any additional arguments in a seq. Since you've already wrapped the program arguments once in main , you mustn't do it again in the call to set-options .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM