Last active
August 4, 2019 21:52
-
-
Save schmee/b6ce2ec9b49733696fd99ffecc413df1 to your computer and use it in GitHub Desktop.
Temperature converter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; 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