or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

concurrency.mdcontrol-flow.mdcore-language.mddata-structures.mddata-utilities.mddev-tools.mdformats.mdindex.mdio.mdjava-interop.mdmath.mdsequences.mdstrings.mdtesting.md

control-flow.mddocs/

0

# Control Flow and Macros

1

2

Advanced control structures, conditional execution, and macro system for metaprogramming. Clojure provides both special forms and macros for controlling program flow.

3

4

## Capabilities

5

6

### Conditional Execution

7

8

Control structures for conditional program execution.

9

10

```clojure { .api }

11

(if test then else?)

12

;; Special form: evaluates test, returns then if truthy, else if falsy

13

;; else is optional (defaults to nil)

14

;; Returns: Object

15

16

(if-not test then else?)

17

;; Macro: inverted conditional, returns then if test is falsy

18

;; Returns: Object

19

20

(when test & body)

21

;; Macro: executes body when test is truthy

22

;; Returns: result of last body expression or nil

23

24

(when-not test & body)

25

;; Macro: executes body when test is falsy

26

;; Returns: result of last body expression or nil

27

28

(when-let bindings & body)

29

;; Macro: binds and executes body if binding value is truthy

30

;; bindings: [symbol test-expr]

31

;; Returns: result of last body expression or nil

32

33

(when-first bindings & body)

34

;; Macro: binds first item of sequence and executes body

35

;; bindings: [symbol sequence-expr]

36

;; Returns: result of last body expression or nil

37

38

(cond & clauses)

39

;; Macro: multi-branch conditional

40

;; clauses: test1 expr1 test2 expr2 ... :else default-expr

41

;; Returns: result of first matching expression

42

43

(condp pred expr & clauses)

44

;; Macro: conditional with predicate applied to expr

45

;; clauses: test-val result-expr test-val result-expr ... default-expr?

46

;; Returns: result expression for first (pred test-val expr) that's truthy

47

48

(case expr & clauses)

49

;; Macro: constant-time dispatch on expr value

50

;; clauses: const1 result1 const2 result2 ... default-expr?

51

;; Returns: result for matching constant

52

```

53

54

### Loops and Iteration

55

56

Constructs for repetitive execution and iteration.

57

58

```clojure { .api }

59

(loop [bindings*] & body)

60

;; Special form: establishes recursion point with local bindings

61

;; bindings: [symbol init-expr symbol init-expr ...]

62

;; Use recur to loop back with new values

63

;; Returns: result of last body expression

64

65

(recur & exprs)

66

;; Special form: recursively calls enclosing fn or loop

67

;; Must be in tail position

68

;; exprs become new parameter/binding values

69

;; Returns: never returns (transfers control)

70

71

(while test & body)

72

;; Macro: executes body repeatedly while test is truthy

73

;; Returns: nil

74

75

(dotimes [name n] & body)

76

;; Macro: executes body n times with name bound to 0, 1, ..., n-1

77

;; Returns: nil

78

79

(doseq [seq-exprs*] & body)

80

;; Macro: executes body for each item in sequences

81

;; seq-exprs: [name coll name coll :let [binding] :when test :while test]

82

;; Returns: nil

83

84

(for [seq-exprs*] body-expr)

85

;; Macro: list comprehension returning lazy sequence

86

;; seq-exprs: same as doseq but returns sequence of body-expr results

87

;; Returns: clojure.lang.LazySeq

88

```

89

90

### Exception Handling

91

92

Constructs for handling exceptions and errors.

93

94

```clojure { .api }

95

(try expr* catch* finally?)

96

;; Special form: exception handling

97

;; catch: (catch ExceptionClass binding-symbol catch-expr)

98

;; finally: (finally finally-expr)

99

;; Returns: result of expr or catch-expr

100

101

(throw expr)

102

;; Special form: throws exception

103

;; expr should evaluate to Throwable

104

;; Returns: never returns

105

106

(assert expr)

107

(assert expr message)

108

;; Macro: throws AssertionError if expr is falsy

109

;; Returns: true if assertion passes

110

111

(with-open [bindings*] & body)

112

;; Macro: ensures resources are closed after use

113

;; bindings: [name init-expr name init-expr ...]

114

;; Resources must implement java.io.Closeable

115

;; Returns: result of last body expression

116

```

117

118

### Threading Macros

119

120

Macros for readable function composition and data transformation pipelines.

121

122

```clojure { .api }

123

(-> x & forms)

124

;; Macro: thread-first - inserts x as first argument to each form

125

;; (-> x (f a) (g b)) expands to (g (f x a) b)

126

;; Returns: result of final form

127

128

(->> x & forms)

129

;; Macro: thread-last - inserts x as last argument to each form

130

;; (->> x (f a) (g b)) expands to (g b (f a x))

131

;; Returns: result of final form

132

133

(as-> expr name & forms)

134

;; Macro: thread with explicit binding - binds result to name in each form

135

;; (as-> x $ (f $ y) (g z $)) where $ is explicitly positioned

136

;; Returns: result of final form

137

138

(some-> expr & forms)

139

;; Macro: thread-first with nil safety - stops if any form returns nil

140

;; Returns: result of final form or nil

141

142

(some->> expr & forms)

143

;; Macro: thread-last with nil safety - stops if any form returns nil

144

;; Returns: result of final form or nil

145

146

(cond-> expr & clauses)

147

;; Macro: conditional threading - only applies forms when test is truthy

148

;; clauses: test1 form1 test2 form2 ...

149

;; Returns: final transformed expr

150

151

(cond->> expr & clauses)

152

;; Macro: conditional thread-last

153

;; Returns: final transformed expr

154

```

155

156

### Macro Definition and Usage

157

158

Tools for creating and working with macros.

159

160

```clojure { .api }

161

(defmacro name doc-string? attr-map? [params*] body)

162

;; Special form: defines a macro

163

;; Macro receives unevaluated arguments and returns code to execute

164

;; Returns: clojure.lang.Var

165

166

(macroexpand form)

167

;; Function: recursively expands all macros in form

168

;; Returns: expanded form

169

170

(macroexpand-1 form)

171

;; Function: expands outermost macro in form once

172

;; Returns: expanded form or original if no macro

173

174

(quote form)

175

;; Special form: returns form without evaluation (same as 'form)

176

;; Returns: unevaluated form

177

178

(unquote form)

179

;; Special form: evaluates form within syntax-quote (same as ~form)

180

;; Only valid within syntax-quote

181

;; Returns: evaluated form

182

183

(unquote-splicing form)

184

;; Special form: splices sequence into containing form (same as ~@form)

185

;; Only valid within syntax-quote

186

;; Returns: spliced sequence

187

188

;; Syntax-quote (backtick `) and unquote

189

`(form ~expr ~@seq-expr) ; Template with unquoting

190

'(form expr seq-expr) ; Simple quote - no unquoting

191

```

192

193

### Evaluation and Compilation

194

195

Functions for runtime evaluation and code generation.

196

197

```clojure { .api }

198

(eval form)

199

;; Function: evaluates form in current namespace context

200

;; Returns: result of evaluation

201

202

(load-string s)

203

;; Function: loads and evaluates Clojure code from string

204

;; Returns: result of last expression

205

206

(read-string s)

207

;; Function: reads one object from string (doesn't evaluate)

208

;; Returns: parsed object

209

210

(compile namespace-symbol)

211

;; Function: compiles namespace to class files

212

;; Returns: namespace symbol

213

```

214

215

**Usage Examples:**

216

217

```clojure

218

;; Conditional execution

219

(if (> 5 3) "yes" "no") ; => "yes"

220

(when (even? 4) "four is even") ; => "four is even"

221

(cond

222

(< 5 3) "less"

223

(> 5 3) "greater"

224

:else "equal") ; => "greater"

225

226

;; Loops

227

(loop [i 0 acc []]

228

(if (< i 3)

229

(recur (inc i) (conj acc i))

230

acc)) ; => [0 1 2]

231

232

(dotimes [i 3] (println i)) ; Prints 0, 1, 2

233

234

(doseq [x [1 2 3]] (println (* x x))) ; Prints 1, 4, 9

235

236

(for [x [1 2 3] y [10 20]]

237

(+ x y)) ; => (11 21 12 22 13 23)

238

239

;; Threading macros

240

(-> 5

241

(+ 3)

242

(* 2)) ; => 16, equivalent to (* (+ 5 3) 2)

243

244

(->> [1 2 3 4]

245

(map inc)

246

(filter even?)) ; => (2 4), equivalent to (filter even? (map inc [1 2 3 4]))

247

248

;; Exception handling

249

(try

250

(/ 1 0)

251

(catch ArithmeticException e

252

"Cannot divide by zero")) ; => "Cannot divide by zero"

253

254

;; Macro definition

255

(defmacro unless [test & body]

256

`(when (not ~test)

257

~@body))

258

259

(unless false (println "This prints")) ; Prints "This prints"

260

261

;; Macro expansion

262

(macroexpand '(when true (println "hi")))

263

; => (if true (do (println "hi")))

264

265

;; Evaluation

266

(eval '(+ 1 2 3)) ; => 6

267

(read-string "(+ 1 2)") ; => (+ 1 2) [not evaluated]

268

(load-string "(+ 1 2)") ; => 3 [evaluated]

269

```