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

data-utilities.mddocs/

0

# Data Structure Utilities

1

2

Comprehensive utilities for traversing, transforming, and navigating complex data structures through specialized namespaces: clojure.walk for tree traversal, clojure.datafy for data transformation, and clojure.zip for functional tree editing.

3

4

## Capabilities

5

6

### Tree Walking (clojure.walk)

7

8

Generic tree traversal functions for recursively processing nested data structures.

9

10

```clojure { .api }

11

(clojure.walk/walk inner outer form)

12

;; Core traversal function - applies inner to each element, then outer to result

13

;; inner: function applied to each sub-element

14

;; outer: function applied to reconstructed structure

15

;; form: data structure to traverse

16

;; Returns: transformed data structure

17

18

(clojure.walk/prewalk f form)

19

;; Pre-order traversal - calls f on each sub-form before recursing

20

;; f: transformation function

21

;; form: data structure to traverse

22

;; Returns: transformed data structure

23

24

(clojure.walk/postwalk f form)

25

;; Post-order traversal - calls f on each sub-form after recursing

26

;; f: transformation function

27

;; form: data structure to traverse

28

;; Returns: transformed data structure

29

30

(clojure.walk/prewalk-demo form)

31

;; Demonstrates prewalk behavior by printing each walked form

32

;; form: data structure to walk and print

33

;; Returns: original form (unchanged)

34

35

(clojure.walk/postwalk-demo form)

36

;; Demonstrates postwalk behavior by printing each walked form

37

;; form: data structure to walk and print

38

;; Returns: original form (unchanged)

39

```

40

41

### Tree Replacement (clojure.walk)

42

43

Higher-level transformation functions built on tree walking.

44

45

```clojure { .api }

46

(clojure.walk/prewalk-replace smap form)

47

;; Pre-order replacement using substitution map

48

;; smap: map of {old-value new-value} replacements

49

;; form: data structure to transform

50

;; Returns: transformed data structure

51

52

(clojure.walk/postwalk-replace smap form)

53

;; Post-order replacement using substitution map

54

;; smap: map of {old-value new-value} replacements

55

;; form: data structure to transform

56

;; Returns: transformed data structure

57

58

(clojure.walk/keywordize-keys m)

59

;; Recursively transforms all map keys from strings to keywords

60

;; m: nested data structure containing maps

61

;; Returns: transformed structure with keyword keys

62

63

(clojure.walk/stringify-keys m)

64

;; Recursively transforms all map keys from keywords to strings

65

;; m: nested data structure containing maps

66

;; Returns: transformed structure with string keys

67

68

(clojure.walk/macroexpand-all form)

69

;; Recursively performs all possible macroexpansions in form

70

;; form: Clojure form potentially containing macros

71

;; Returns: fully macroexpanded form

72

```

73

74

### Data Transformation (clojure.datafy)

75

76

Protocol-based data transformation for converting objects to data representations.

77

78

```clojure { .api }

79

(clojure.datafy/datafy x)

80

;; Attempts to return x as data using clojure.core.protocols/datafy

81

;; x: object to transform to data representation

82

;; Returns: data representation of x with metadata about original

83

84

(clojure.datafy/nav coll k v)

85

;; Returns possibly transformed v in context of coll and key k

86

;; coll: containing collection

87

;; k: key/index context (or nil)

88

;; v: value to potentially transform

89

;; Returns: transformed value via clojure.core.protocols/nav

90

```

91

92

### Functional Zippers (clojure.zip)

93

94

Functional tree editing with location-aware navigation and modification.

95

96

#### Zipper Creation

97

98

```clojure { .api }

99

(clojure.zip/zipper branch? children make-node root)

100

;; Creates a new zipper structure for arbitrary trees

101

;; branch?: predicate fn - true if node can have children

102

;; children: fn returning seq of node's children

103

;; make-node: fn creating new branch node from existing node and children

104

;; root: root node of tree

105

;; Returns: zipper positioned at root

106

107

(clojure.zip/seq-zip root)

108

;; Returns zipper for nested sequences

109

;; root: root sequence

110

;; Returns: sequence zipper

111

112

(clojure.zip/vector-zip root)

113

;; Returns zipper for nested vectors

114

;; root: root vector

115

;; Returns: vector zipper

116

117

(clojure.zip/xml-zip root)

118

;; Returns zipper for XML elements (as from xml/parse)

119

;; root: root XML element

120

;; Returns: XML zipper

121

```

122

123

#### Zipper Navigation

124

125

```clojure { .api }

126

(clojure.zip/node loc)

127

;; Returns the node at current location

128

;; loc: zipper location

129

;; Returns: node at location

130

131

(clojure.zip/branch? loc)

132

;; Returns true if node at location is a branch

133

;; loc: zipper location

134

;; Returns: boolean

135

136

(clojure.zip/children loc)

137

;; Returns seq of children of branch node at location

138

;; loc: zipper location (must be branch)

139

;; Returns: seq of child nodes

140

141

(clojure.zip/down loc)

142

;; Returns location of first child, nil if no children

143

;; loc: zipper location

144

;; Returns: child location or nil

145

146

(clojure.zip/up loc)

147

;; Returns location of parent, nil if at top

148

;; loc: zipper location

149

;; Returns: parent location or nil

150

151

(clojure.zip/left loc)

152

;; Returns location of left sibling, nil if none

153

;; loc: zipper location

154

;; Returns: left sibling location or nil

155

156

(clojure.zip/right loc)

157

;; Returns location of right sibling, nil if none

158

;; loc: zipper location

159

;; Returns: right sibling location or nil

160

161

(clojure.zip/leftmost loc)

162

;; Returns location of leftmost sibling

163

;; loc: zipper location

164

;; Returns: leftmost sibling location

165

166

(clojure.zip/rightmost loc)

167

;; Returns location of rightmost sibling

168

;; loc: zipper location

169

;; Returns: rightmost sibling location

170

171

(clojure.zip/next loc)

172

;; Returns next location in depth-first walk, nil if end

173

;; loc: zipper location

174

;; Returns: next location or nil

175

176

(clojure.zip/prev loc)

177

;; Returns previous location in depth-first walk, nil if beginning

178

;; loc: zipper location

179

;; Returns: previous location or nil

180

```

181

182

#### Zipper Query Functions

183

184

```clojure { .api }

185

(clojure.zip/path loc)

186

;; Returns seq of nodes leading to this location

187

;; loc: zipper location

188

;; Returns: seq of ancestor nodes

189

190

(clojure.zip/lefts loc)

191

;; Returns seq of left siblings of this location

192

;; loc: zipper location

193

;; Returns: seq of left sibling nodes

194

195

(clojure.zip/rights loc)

196

;; Returns seq of right siblings of this location

197

;; loc: zipper location

198

;; Returns: seq of right sibling nodes

199

200

(clojure.zip/root loc)

201

;; Returns root node of entire tree

202

;; loc: zipper location

203

;; Returns: root node

204

205

(clojure.zip/end? loc)

206

;; Returns true if location represents end of depth-first walk

207

;; loc: zipper location

208

;; Returns: boolean

209

```

210

211

#### Zipper Editing

212

213

```clojure { .api }

214

(clojure.zip/replace loc node)

215

;; Returns new location with node replaced

216

;; loc: zipper location

217

;; node: replacement node

218

;; Returns: new location with replaced node

219

220

(clojure.zip/edit loc f & args)

221

;; Returns location with node replaced by (apply f node args)

222

;; loc: zipper location

223

;; f: transformation function

224

;; args: additional arguments to f

225

;; Returns: new location with edited node

226

227

(clojure.zip/insert-left loc item)

228

;; Returns location with item inserted as left sibling

229

;; loc: zipper location

230

;; item: node to insert

231

;; Returns: new location

232

233

(clojure.zip/insert-right loc item)

234

;; Returns location with item inserted as right sibling

235

;; loc: zipper location

236

;; item: node to insert

237

;; Returns: new location

238

239

(clojure.zip/insert-child loc item)

240

;; Returns location with item inserted as leftmost child

241

;; loc: zipper location (must be branch)

242

;; item: node to insert

243

;; Returns: new location

244

245

(clojure.zip/append-child loc item)

246

;; Returns location with item inserted as rightmost child

247

;; loc: zipper location (must be branch)

248

;; item: node to insert

249

;; Returns: new location

250

251

(clojure.zip/remove loc)

252

;; Returns location with node removed

253

;; loc: zipper location

254

;; Returns: new location with node removed

255

```

256

257

**Usage Examples:**

258

259

```clojure

260

;; Tree walking examples

261

(require '[clojure.walk :as walk])

262

263

;; Transform all numbers in nested structure

264

(walk/postwalk

265

#(if (number? %) (* % 2) %)

266

{:a 1 :b [2 3 {:c 4}]})

267

;; => {:a 2, :b [4 6 {:c 8}]}

268

269

;; String keys to keyword keys

270

(walk/keywordize-keys {"a" 1 "b" {"c" 2}})

271

;; => {:a 1, :b {:c 2}}

272

273

;; Replace specific values

274

(walk/postwalk-replace {'old 'new :a :replaced}

275

'(old data (:a value) old))

276

;; => (new data (:replaced value) new)

277

278

;; Functional zipper examples

279

(require '[clojure.zip :as zip])

280

281

;; Navigate nested vector structure

282

(def data [[1 2] [3 [4 5]] 6])

283

(def z (zip/vector-zip data))

284

285

;; Navigate to deeply nested value

286

(-> z

287

zip/down ; into first level: [1 2]

288

zip/right ; to [3 [4 5]]

289

zip/down ; into [3 [4 5]]

290

zip/right ; to [4 5]

291

zip/down ; into [4 5]

292

zip/right ; to 5

293

zip/node) ; => 5

294

295

;; Edit nested structure

296

(-> z

297

zip/down ; to [1 2]

298

zip/right ; to [3 [4 5]]

299

zip/down ; into [3 [4 5]]

300

(zip/edit inc) ; change 3 to 4

301

zip/root) ; => [[1 2] [4 [4 5]] 6]

302

303

;; Add new elements

304

(-> z

305

zip/down ; to [1 2]

306

(zip/insert-right [7 8]) ; insert new vector

307

zip/root) ; => [[1 2] [7 8] [3 [4 5]] 6]

308

309

;; Tree traversal with zippers

310

(defn find-in-tree [pred z]

311

(loop [loc z]

312

(cond

313

(zip/end? loc) nil

314

(pred (zip/node loc)) loc

315

:else (recur (zip/next loc)))))

316

317

;; Find first even number

318

(let [z (zip/vector-zip [1 [2 3] [4 [5 6]]])]

319

(when-let [loc (find-in-tree even? z)]

320

(zip/node loc))) ; => 2

321

322

;; Data transformation with datafy

323

(require '[clojure.datafy :as d])

324

325

;; Transform exception to data

326

(try

327

(/ 1 0)

328

(catch Exception e

329

(d/datafy e)))

330

;; => returns map with exception details

331

332

;; Working with refs and atoms

333

(let [a (atom {:count 42})]

334

(d/datafy a)) ; => [{\count 42}] with metadata

335

```