Skip to content

Commit b861834

Browse files
committed
refining language
1 parent 1a8dca4 commit b861834

2 files changed

Lines changed: 18 additions & 38 deletions

File tree

content/guides/destructuring.adoc

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -273,9 +273,9 @@ Associative destructuring, however, also allows you to supply a default value if
273273
;= Category not found
274274
----
275275

276-
The value for `:or` is a map where the bound symbol (here `category`) is bound to the expression `"Category not found"`. When category is not found in `client`, it is instead found in the `:or` map and bound to that value instead. When used this way, the default is for the key associated with that binding name. If you haven't yet used that binding name in a binding elsewhere, it is not associated with any key and the entry is a no-op.
276+
To supply default values for keys that are not present in the input map, you can use the `:or` directive, whose value is a map of binding names or [since 1.13] keys to default values. Thus here `"Category not found"` will be used as the value for the binding category if the key `:category` is not in the input map (`client`). Note that if an unadorned symbol is used as a key in the `:or` map but not yet in any binding the entry is a no-op.
277277

278-
You may also specify values either via explicit keys in the `:or` map, which was added in Clojure 1.13.
278+
The next example uses `:category` as an explicit key rather than the binding name `category` in the `:or` map.
279279

280280
[source,clojure]
281281
----
@@ -284,7 +284,7 @@ You may also specify values either via explicit keys in the `:or` map, which was
284284
;= "Category again not found"
285285
----
286286

287-
If you wish to capture the default values stated in the `:or` map, the `:defaults` directive, added in Clojure 1.13, binds a name to a map, created during destructuring, of keys to their default values. You would use `:defaults` when you want those same default values for some purpose later in your code, and don't want to restate them.
287+
If you wish to capture the default values stated in the `:or` map, the `:defaults` directive binds a name to a map, created during destructuring, of keys to their default values. [since 1.13] You would use `:defaults` when you want those same default values for some purpose later in your code, and don't want to restate them.
288288

289289
[source,clojure]
290290
----
@@ -304,7 +304,7 @@ If you need access to the entire map, you can use the `:as` key to bind the enti
304304
;= The name from {:name Super Co., :location Philadelphia, :description The world wide leader in plastic table-ware.} is Super Co.
305305
----
306306

307-
The `:as`, `:or`, and `:defaults` keywords can be combined in a single destructuring.
307+
The `:as`, `:or`, and `:defaults` keywords can be combined in a single destructuring form:
308308

309309
[source,clojure]
310310
----
@@ -346,7 +346,7 @@ The `:keys` key is for associative values with keyword keys, but there are also
346346
;= Jane Doe
347347
----
348348

349-
Additionally, since Clojure 1.13 there are checked versions of the binding directives named `:keys!`, `:strs!`, and `:syms!` that throw an exception if the keys specified are not present in the destructured map.
349+
If you want it to be an error to supply a map that is missing certain keys (rather than get `nil` or default values), you can [since 1.13] use the checked versions of the binding directives (`:keys!`, `:strs!`, and `:syms!`) that throw an exception if the required keys are not present.
350350

351351
[source,clojure]
352352
----
@@ -355,20 +355,20 @@ Additionally, since Clojure 1.13 there are checked versions of the binding direc
355355
;= throws Missing required key: "dob"
356356
----
357357

358-
As of Clojure 1.13, all of the binding directives allow you to specify literal keys after `&` for documentation:
358+
If you have keys you want to require but don't need to bind, you can list them after `&`, which will check for the presence of the listed keys but not create bindings.
359359

360360
[source,clojure]
361361
----
362-
(let [{:keys [fred ethel lucy & :ricky]} m] ...
362+
(let [{:keys! [fred ethel lucy & :ricky]} m] ...
363363
364-
(let [{:strs [fred ethel lucy & "ricky"]} m] ...
364+
(let [{:strs! [fred ethel lucy & "ricky"]} m] ...
365365
366-
(let [{:syms [fred ethel lucy & 'ricky]} m] ...
366+
(let [{:syms! [fred ethel lucy & 'ricky]} m] ...
367367
----
368368

369-
The use of `&` in the unchecked versions allow you to specify accepted keys, but its use in the checked variants is more strict as the keys specified are still required and will throw if not present.
369+
You can also document additional optional keys that you are not binding in the (:keys, :strs, and :syms) directives using `&`. [since 1.13]
370370

371-
Also added in Clojure 1.13 is a new directive `:select` that binds a name to a map, created during destructuring, containing only those keys from the input map, or the defaults if not present in the input, that are used anywhere in the destructuring form (other than in `:or`), including in nested destructuring. Thus it is a (deep) subset of the input augmented by defaults.
371+
To bind a name to a deep subset of the input map, augmented by defaults, use the `:select` directive. [since 1.13] It includes every key used anywhere in the destructuring form, including nested forms, but not keys used only in `:or`.
372372

373373
[source,clojure]
374374
----
@@ -399,21 +399,6 @@ Associative destructuring can be nested and combined with sequential destructuri
399399
;= Joe is a Ranger wielding a Longbow
400400
----
401401

402-
With nested destructuring, the use of `:or`, `:defaults`, and `:select` only apply at the level at which they are applied:
403-
404-
[source,clojure]
405-
----
406-
(let [{{:keys [class weapon name], :or {:name "Sir Joe"}, :defaults jdf, :select joe} :joe
407-
npc :npc
408-
:or {npc {:class "Farmer", :weapon "Shovel"}}} multiplayer-game-state]
409-
(println "Joe's :select data is" joe)
410-
(println name "had his name set as a default from the :or map" jdf)
411-
(println "The default unnamed NPC is" npc))
412-
;= Joe's :select data is {:weapon "Longbow", :name "Sir Joe", :class "Ranger"}
413-
;= Sir Joe had his name set as a default from the :or map {:name "Sir Joe"}
414-
;= The default unnamed NPC is {:class "Farmer", :weapon "Shovel"}
415-
----
416-
417402
=== Keyword arguments
418403

419404
One special case is using associative destructuring for keyword-arg parsing. Consider a function that takes options `:debug` and `:verbose`. These could be specified in an options map:

content/reference/special_forms.adoc

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ Map __binding-form__s create bindings by looking up values in collections like m
296296
->[5 3 6 {:c 6, :a 5}]
297297
----
298298

299-
Since Clojure 1.13, the `:or` directive also allows the use of explicit keys:
299+
The `:or` maps also accept the input key directly in place of the binding name. [since 1.13]
300300

301301
[source,clojure]
302302
----
@@ -306,7 +306,7 @@ Since Clojure 1.13, the `:or` directive also allows the use of explicit keys:
306306
->[5 3 42 {:a 5}]
307307
----
308308

309-
Also since Clojure 1.13, Clojure allows you to bind a name to a map of keys mapped to their default values, based on what you've said in `:or` per above:
309+
To capture the `:or` defaults as a map bound to a name, use the `:defaults` directive. [since 1.13]
310310

311311
[source,clojure]
312312
----
@@ -352,14 +352,7 @@ In the case of using prefixed keys, the bound symbol name is the same as the rig
352352
-> 42
353353
----
354354

355-
As of Clojure 1.13, associative destructuring directives allow you to specify literal keys after `&` that serve as documentation:
356-
357-
[source,clojure]
358-
----
359-
(let [{:keys [fred ethel lucy & :ricky]} m] ...
360-
----
361-
362-
There are similar `:strs` and `:syms` directives for matching string and symbol keys, the latter also allowing prefixed symbol keys since Clojure 1.6. The literal keys after `&` for these directives match the form of the keys handled, e.g. `:strs [a & "b"]` and `:syms [a & 'b]`. For `:syms` the use of quote is required to distinguish between a binding name and a literal symbol.
355+
There are similar `:strs` and `:syms` directives for matching string and symbol keys, the latter also allowing prefixed symbol keys.
363356

364357
Clojure 1.9 adds support for directly destructuring many keys (or symbols) that share the same namespace using the following destructuring key forms:
365358

@@ -379,14 +372,16 @@ Clojure 1.9 adds support for directly destructuring many keys (or symbols) that
379372
-> [1 2]
380373
----
381374

382-
As of Clojure 1.13, you can now ensure that required keys are bound during map destructuring by using the new checked variants of the `:keys`/`:syms`/`:strs` binding directives - `:keys!`/`:syms!`/`:strs!`, which will throw an exception if the keys specified are not present in the destructured map. These checked directives also support the use of `&` and will check the presence of the specified keys in the destructured map.
375+
You can ensure that required keys are present during map destructuring by using the checked variants of the `:keys`/`:syms`/`:strs` binding directives named `:keys!`/`:syms!`/`:strs!`, which throw an exception if any of the specified keys are missing from the destructured map. [since 1.13] These checked directives also accept `&`, after which you may list additional keys that are still required and checked, but not bound to a local name.
383376

384377
[source,clojure]
385378
----
386379
(let [{:keys! [fred ethel lucy & :ricky]} m] ... ;; m must have keys :fred, :ethel, :lucy, and :ricky
387380
----
388381

389-
As of Clojure 1.13, supports a directive `:select` that binds a name to a map, created during destructuring, containing only those keys from the input map, or the defaults if not present in the input, that are used anywhere in the destructuring form (other than in `:or`), including in nested destructuring. Thus it is a (deep) subset of the input augmented by defaults.
382+
The literal keys after `&` for these directives should match the form of the keys handled, e.g. `:strs [a & "b"]` and `:syms [a & 'b]`. For `:syms` the use of quote is required to distinguish between a binding name and a literal symbol. In the unchecked directives `:keys`, `:strs`, and `:syms`, `&` serves only as documentation: the listed keys are neither bound nor checked for presence. [since 1.13]
383+
384+
To bind a name to a deep subset of the input map, augmented by defaults, use the `:select` directive. [since 1.13] It includes every key used anywhere in the destructuring form, including nested forms, but not keys used only in `:or`.
390385

391386
[source,clojure]
392387
----

0 commit comments

Comments
 (0)