(ns pleac-section-5 (:require [clojure.java.io :as io] [clojure.string :as string])) ;; The commas are whitespace and optional. Maps are printed with them ;; at the REPL for readability. (def age {"Nat" 24, "Jules" 25, "Josh" 17}) (def age (assoc age "Nat" 24)) (def age (assoc age "Jules" 25)) (def age (assoc age "Josh" 17)) ;; Commas omitted here. (def food-color {"Apple" "red" "Banana" "yellow" "Lemon" "yellow" "Carrot" "orange"}) |
;; Maps, like all core Clojure data structures, are immutable. ;; Functions for "changing" maps just return new maps. (def food-color (assoc food-color "Raspberry" "pink")) (println "Known foods:") (doseq [food (keys food-color)] (println food)) ;; Known foods: ;; Carrot ;; Banana ;; Raspberry ;; Lemon ;; Apple |
(if (contains? food-color "key") "exists" "doesn't exist") (doseq [name ["Banana" "Martini"]] (if (contains? food-color name) (println name "is a food.") (println name "is a drink."))) ;; Banana is a food. ;; Martini is a drink. (def age {}) (def age (assoc age "Toddler" 3)) (def age (assoc age "Unborn" 0)) (def age (assoc age "Phantasm" nil)) ;; Maps are functions from keys to values, and can be called exactly ;; like functions, taking a key as an argument. The function call ;; returns nil if the key doesn't exist. This works just like using ;; the function "get". (doseq [thing ["Toddler" "Unborn" "Phantasm" "Relic"]] (printf "%s: " thing) (when (contains? age thing) (print "Exists ")) ;; get returns nil when the key isn't in the map, and when the key ;; does exist and the value is nil. (when (get age thing) (print "Defined ")) ;; This works just like the above. Output differs from Perl because ;; 0 is not falsy. (when (age thing) (print "True ")) (newline)) ;; Toddler: Exists Defined True ;; Unborn: Exists Defined True ;; Phantasm: Exists ;; Relic: (defn file-sizes [files] (reduce (fn [map file] (let [file (.trim file)] (if (contains? map file) map (assoc map file (.length (java.io.File. file)))))) {} files)) (file-sizes (line-seq (io/reader *in*))) |
;; dissoc is used to "remove" (return a new map without the key) (defn print-foods [] (println "Keys:" (string/join " " (keys food-color))) (print "Values: ") (doseq [food (keys food-color)] (if (food-color food) (printf "%s " (food-color food)) (print "(undef) "))) (newline)) (println "Initially:") (print-foods) (println "\nWith Banana undef") (def food-color (assoc food-color "Banana" nil)) (print-foods) (println "\nWith Banana deleted") (def food-color (dissoc food-color "Banana")) (print-foods) ;; Initially: ;; Keys: Carrot Banana Lemon Apple ;; Values: orange yellow yellow red ;; With Banana undef ;; Keys: Carrot Banana Lemon Apple ;; Values: orange (undef) yellow red ;; With Banana deleted ;; Keys: Carrot Lemon Apple ;; Values: orange yellow red (def food-color (dissoc food-color "Banana" "Apple" "Cabbage")) |
(doseq [[key value] food-color] ;; do something ) (doseq [key (keys food-color)] (let [value (food-color key)] ;; do something )) ;; food-color per the introduction (doseq [[food color] food-color] (printf "%s is %s.\n" food color)) ;; Carrot is orange. ;; Banana is yellow. ;; Lemon is yellow. ;; Apple is red. (doseq [food (keys food-color)] (let [color (food-color food)] (printf "%s is %s.\n" food color))) ;; Carrot is orange. ;; Banana is yellow. ;; Lemon is yellow. ;; Apple is red. (doseq [food (sort (keys food-color))] (let [color (food-color food)] (printf "%s is %s.\n" food color))) ;; Apple is red. ;; Banana is yellow. ;; Carrot is orange. ;; Lemon is yellow. ;; There isn't an idiomatic way to reset an iteration through a ;; collection in Clojure. (defn countfrom [file] (let [lines (line-seq (io/reader file)) match-sender (fn [line] (second (re-matches #"^From: (.*)" line))) from (reduce (fn [map line] (let [sender (match-sender line) cur (get map sender 0)] (assoc map sender (inc cur)))) {} lines)] (doseq [[person n] (sort from)] (printf "%s: %d\n" person n)))) ;; FILE ACCESS |