Reputation: 35
I have a filename at args[0] (e.g. (first args) and I want to pass it from my main method to the slurp-std-input . I tried to do the followings but I get this error:
CompilerException java.lang.RuntimeException: Unable to resolve symbol: enc in this context, compiling:(regexdna/core.clj:19:3)
The code for both methods is:
(defn -main
[& args]
(let [content (slurp-std-input (first args))
original-len (count content)
;; I'd prefer if I could use the regexp #"(^>.*)?\n" like the
;; Perl benchmark does, but that only matches ^ at the beginning
;; of the string, not at the beginning of a line in the middle
;; of the string.
content (str/replace content #"(^>.*|\n>.*)?\n" "")
dna-seq-only-len (count content)]
(doseq [[re num-matches] (pmap #(count-regex-occurrences % content)
dna-seq-regexes)]
(spit "./scratch/output.txt" (format "%s %d\n" re num-matches):append true))
(let [content (reduce one-replacement content iub-codes)]
(spit "./scratch/output.txt" (format "\n%d\n%d\n%d\n" original-len dna-seq-only-len (count content)) :append true)))
(flush))
and the method in which I want to pass the (first args) parameter, so I can read from the String filename that is contained in (first args) is:
(defn slurp-std-input [args]
;; Reads the standard input using the encoding enc into a string and
;; returns it.
([] (slurp-std-input (.name (java.nio.charset.Charset/defaultCharset))))
([#^String enc]
(with-open [r (new java.io.BufferedReader (clojure.java.io/reader args))]
(let [sb (new StringBuilder)]
(loop [c (.read r)]
(if (neg? c)
(str sb)
(do
(.append sb (char c))
(recur (.read r)))))))))
Note that I have changed reading from in to reading from my file contained in args[o]
Upvotes: 1
Views: 424
Reputation: 3010
RedDeckWins is on the right track, but I felt I could better help to clarify the problem in a separate answer, and also point out a couple of other things while I'm at it.
This should at least fix the error that you're getting:
(defn slurp-std-input ;; (1)
"Reads the standard input using the encoding enc into a string and
returns it." ;; (2)
([fname]
(slurp-std-input fname (.name (java.nio.charset.Charset/defaultCharset))))
([fname ^String enc] ;; (3)
(with-open [r (new java.io.BufferedReader
(clojure.java.io/reader fname :encoding enc))]
(let [sb (new StringBuilder)]
(loop [c (.read r)]
(if (neg? c)
(str sb)
(do
(.append sb (char c))
(recur (.read r)))))))))
Take note of three things above:
Here is where your problem lies -- you're defining a function with multiple arities, but the first line was (defn slurp-std-input [args]
-- this means the function has the arity 1, so anything after [args]
must be a single definition of your fixed-arity function. That isn't what you want, so get rid of [args]
and you should be good to go.
The convention in Clojure is to document functions via a string following the name of the function. This enables the user to obtain the documentation of your function via (doc slurp-std-input)
.
Your type hinting syntax was slightly off. It should be ^String enc
, not #^String enc
.
EDIT: I just realized your code uses args
, which will no longer work with the corrections I've made, since the symbol args
isn't bound to anything... I think I've figured out your intention, though. I've edited my code above. Your function should have the possible arities 1 and 2, not 0 and 1. You're at least passing one argument -- the filename -- and you can optionally pass an encoding as well.
EDIT #2: Here is a revised version that relies on clojure.core/slurp
, which conveniently allows for optional parameters such as encoding
:
(defn slurp-std-input
"Returns the contents of a file as a string.
Optionally takes an encoding as a second argument."
([fname] (slurp fname))
([fname ^String enc] (slurp fname :encoding enc)))
Note that this is literally just a wrapper for clojure.core/slurp
, so the fact that you're slurping a filename that comes from standard input is actually irrelevant. If I were to write a function like this, I would call it something like slurp-plus
or slurp'
or something.
Upvotes: 0
Reputation: 2121
You have invalid syntax. If you are providing multiple implementations of a method with different arities, the proper syntax would be something like I've put below. Essentially, the args you had on the first line was incorrect.
(defn slurp-std-input
;; Reads the standard input using the encoding enc into a string and
;; returns it.
([fname]
(with-open [r (new java.io.BufferedReader (clojure.java.io/reader fname))]
(let [sb (new StringBuilder)]
(loop [c (.read r)]
(if (neg? c)
(str sb)
(do
(.append sb (char c))
(recur (.read r)))))))))
EDIT: changed code a bit. What was your intention with the #^String enc?
Upvotes: 1