Skip to content

Instantly share code, notes, and snippets.

@schmee
Last active August 4, 2019 21:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save schmee/b6ce2ec9b49733696fd99ffecc413df1 to your computer and use it in GitHub Desktop.
Save schmee/b6ce2ec9b49733696fd99ffecc413df1 to your computer and use it in GitHub Desktop.
Temperature converter
;; Comments
;; 1. Functions take data and return data! If you compare your solution, you see that
;; there is a chain of method calls: get-user-input -> parse-input -> print-temp -> convert-temp
;; Since get-user-input and print-temp are unpure, this makes it hard to break apart and to test.
;; Compare here: convert-temp, temp->str and parse-input all take data and return data, and all IO
;; happens in read-loop.
;; 2. There are many approaches to error handling, but initially a simple try/catch will do!
;; try/catch works the same way is in Java, so it is a good idea to get familiar with Java exceptions.
;; https://clojuredocs.org/clojure.core/try
;; 3. This type of input loop can be done with loop/recur. When you call recur, you go back to the
;; start of the loop block. To exit when you enter "quit", check the input before parsing, and if
;; it matches then don't call recur.
(ns temp-converter.core) ;; don't need :gen-class
(defn convert-temp [degrees unit]
(case unit
"C" (+ 32.0 (* 1.8 degrees))
"F" (/ (- degrees 32.0) 1.8)))
;; foo->bar is common naming convention for functions that convert from foo to bar
;; returns a string instead of printing directly, easier to test!
(defn temp->str [degrees unit]
(case unit
"C" (str degrees unit "=" (format "%.2f" (convert-temp degrees unit)) "F")
"F" (str degrees unit "=" (format "%.2f" (convert-temp degrees unit)) "C")
(str "unsupported unit " unit)))
;; takes data (a string) and returns data (a map). No side-effects!
(defn parse-input [input]
(try
{:degrees (Integer/parseInt (apply str (butlast input)))
:unit (str (last input))}
(catch NumberFormatException e
nil)))
;; All IO is shoved into this method
(defn read-loop []
(loop []
(println "Please input a temperature (format: 100F or 20C):")
(let [input (read-line)]
(if (= input "quit")
(println "Bye bye!")
(let [parsed (parse-input input)]
(if parsed
(println (temp->str (:degrees parsed) (:unit parsed)))
(println "Invalid input, please try again"))
(recur))))))
(defn -main []
(println "Welcome to the temperature converter!")
(read-loop))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment