I am trying to store two integers and a double from User Input into a list in Clojure. Any and all help is greatly appreciated!
My standard input to the console: 12 1 5.30.
Here is my code:
(ns clojure.partial.map
(:gen-class))
(defn string-to-list [s]
(re-seq #"\d \d (\d )?\.(\d )?" s))
(defn convert-seq-of-int-to-strings [ss]
(let [new_partition (partition-all 2 ss)
map-one (map #(Integer/parseInt %) (take 1 new_partition))
map-two (map #(Double/parseDouble %) (take 1 (drop 1 new_partition)))
map-concat (concat (map-one map-two))]
(doseq [item map-concat]
(println item)))
(def user-input (read-line))
(def new-sequence (string-to-list new-line))
(def converting-seq-to-list (convert-seq-of-int-to-strings new-seq))
; Expected Output:
; 12
; 1
; 5.30
Error Message:
Execution error (ClassCastException) at clojure.partial.map/convert-seq-of-int-to-strings.
class clojure.lang.LazySeq cannot be cast to class clojure.lang.IFn
(clojure.lang.LazySeq and clojure.lang.IFn are in unnamed module of loader 'app')
CodePudding user response:
There is actually much more errors than one let
, but let's start from that:
- You're missing parentheses around
let
and missing brackets around bindings in thislet
. (concat (map-one map-two))
is causing this exception:class clojure.lang.LazySeq cannot be cast to class clojure.lang.IFn
.map-one
isn't function, so you should call thisconcat
like this:(concat map-one map-two)
- Regex in
string-to-list
can't parse your string"5 10 2.84"
. You could rewrite that into something like this:
(->> (re-seq #"\d (\.\d )?" "5 10 2.84")
(map first))
=> ("5" "10" "2.84")
Or even more readable clojure.string/split
:
(clojure.string/split "5 10 2.84" #" ")
=> ["5" "10" "2.84"]
- I don't understand why you need to use
partition
, so I will skip this one. - Replace
Integer/parseInt
andDouble/parseDouble
withparse-long
andparse-double
. You will actually need only one, becauseparse-double
also handles strings without a decimal dot. Or you can useclojure.edn/read-string
, if you want to get numbers of desired types. - Your function
convert-seq-of-int-to-strings
actually returnsnil
, as result ofdoseq
. And its name is misleading, you're converting a sequence of strings into a sequence of numbers.
With all these changes, your code could look like this:
(defn input-to-seq []
(let [numbers (->> (clojure.string/split (read-line) #" ")
(mapv clojure.edn/read-string))]
(doseq [item numbers]
(println item))
numbers))
CodePudding user response:
You forgot the square brackets in the let
statement. Also, use (round) parentheses outside of the let
. Example:
(let [a 1
b 2
c ( a b)]
(println "c =" c))
Just guessing on what you want. Here is one possible solution, built using my favorite template project:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test)
(:require
[clojure.edn :as edn]
[clojure.string :as str]
[schema.core :as s]))
(verify
(let [input-str "1 2 3.0"
tokens (str/split input-str #"\s ")
result (vec (for [token tokens]
(edn/read-string token)))]
(is= result [1 2 3.0])))