Control Structure
Clojure, a modern functional language on the Java platform, has a distinct approach to control structures, primarily influenced by its Lisp roots. It encourages a functional programming style, leaning heavily on recursion, immutability, and higher-order functions for managing program flow. Despite this, it also provides a suite of control structures familiar to those from imperative or procedural languages. Fundamental control structures in Clojure include if, when, cond, case, and loop coupled with recur for more efficient looping. Macros like if-let and when-let provide conditional bindings and help reduce verbosity in handling potential nil values.
Code
(ns control-structure.core)
(defn demo-if [x]
(if (> x 0)
(str "x is positive")
(str "x is non-positive")))
(demo-if -1)
;; => "x is non-positive"
(demo-if 0)
;; => "x is non-positive"
(demo-if 1)
;; => "x is positive"
(defn demo-if-let [m]
(if-let [val (m :key)]
(str "Value found:" val)
(str "No value found")))
(demo-if-let {:key "A value"})
;; => "Value found:A value"
(demo-if-let {})
;; => "No value found"
(defn demo-when [x]
(when (= x 0)
(str "x is zero")))
(demo-when 0)
;; => "x is zero"
(demo-when 1)
;; => nil
(defn demo-when-let [m]
(when-let [val (m :key)]
(str "Value found:" val)))
(demo-when-let {:key "Another value"})
;; => "Value found:Another value"
(demo-when-let {})
;; => nil
(defn demo-cond [x]
(cond
(< x 0) (str "x is negative")
(= x 0) (str "x is zero")
:else (str "x is positive")))
(demo-cond -1)
;; => "x is negative"
(demo-cond 0)
;; => "x is zero"
(demo-cond 1)
;; => "x is positive"
(defn demo-case [x]
(case x
0 (str "x is zero")
1 (str "x is one")
(str "x is neither zero nor one")))
(demo-case 0)
;; => "x is zero"
(demo-case 1)
;; => "x is one"
(demo-case 2)
;; => "x is neither zero nor one"
(defn demo-for [x]
(for [i (range x)]
(str "i:" i)))
(demo-for 3)
;; => ("i:0" "i:1" "i:2")
(defn demo-loop [x]
(loop [i 0]
(when (< i x)
(println "i:" i)
(recur (inc i)))))
(demo-loop 3)
;; => nilLet’s break this down into separate parts:
(ns control-structure.core)- This sets the namespace for the current file, sort of like usingpackagein Java. Thensmacro is used to declare a namespace, which in this case iscontrol-structure.core.(defn demo-if [x]...)- This is a function definition nameddemo-ifthat takes a single argumentx. Theiffunction then checks whetherxis greater than zero. If it is, the function returns the string “x is positive”, otherwise it returns “x is non-positive”.(defn demo-if-let [m]...)- This is a function definition nameddemo-if-letthat takes a mapmas its argument. Theif-letform is used to bindvalto the value of:keyinmif it exists, otherwise it proceeds to the else part. Ifvalis notnil, it will return “Value found:val”, otherwise it will return “No value found”.(defn demo-when [x]...)- This function, nameddemo-when, takes a single argumentx. It uses thewhenmacro, which is similar toifbut only has one branch. If the condition is true (in this case, ifxequals 0), it executes the body and returns the result; otherwise, it returnsnil.(defn demo-when-let [m]...)- Similar todemo-if-let, but it useswhen-let. If the value at:keyin the mapmis non-nil, it binds the value tovaland returns “Value found:val”. If it’snil, it does nothing and returnsnil.(defn demo-cond [x]...)- This is a function nameddemo-condwhich uses thecondmacro for multi-way conditionals. Ifxis less than zero it returns “x is negative”, ifxequals zero it returns “x is zero”, otherwise it returns “x is positive”.(defn demo-case [x]...)- The functiondemo-caseuses thecasemacro, which is similar toswitchin other languages. Depending on the value ofx, it returns “x is zero”, “x is one”, or “x is neither zero nor one”.(defn demo-for [x]...)- This function, nameddemo-for, uses theformacro to create a sequence of strings for every number in the range from 0 tox(exclusive). The range function generates a sequence of numbers.(defn demo-loop [x]...)- This function nameddemo-loopdemonstrates theloopandrecurmacros for looping in Clojure. Theloopmacro sets up some bindings, hereiis bound to0. Ifiis less thanx, it prints “i:i” and recurs with an incrementedi. Therecurfunction jumps back to the nearest enclosingloopor function call. Thedemo-loopfunction doesn’t return a value, hence it returnsnil.
Last updated on