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
letand 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-oneisn't function, so you should call thisconcatlike this:(concat map-one map-two)- Regex in
string-to-listcan'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/parseIntandDouble/parseDoublewithparse-longandparse-double. You will actually need only one, becauseparse-doublealso 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-stringsactually 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])))
