Home > Software engineering >  Clojure. Storing two Integers and a Double from User Input into a List
Clojure. Storing two Integers and a Double from User Input into a List

Time:09-30

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 this let.
  • (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 this concat 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 and Double/parseDouble with parse-long and parse-double. You will actually need only one, because parse-double also handles strings without a decimal dot. Or you can use clojure.edn/read-string, if you want to get numbers of desired types.
  • Your function convert-seq-of-int-to-strings actually returns nil, as result of doseq. 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])))
  • Related