Skip to content

Commit 96fe4d0

Browse files
committed
learn: further refine cf2
1 parent 8269331 commit 96fe4d0

File tree

2 files changed

+45
-31
lines changed

2 files changed

+45
-31
lines changed

content/learn/intermediate/control-flow-2.md

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@ condition holds.
1515
### Range
1616

1717
The `range` action performs an action for each entry in a slice or map; we say that range _iterates_ over the slice or
18-
map. If you have worked with other programming languages, `range` is roughly equivalent to a for-each loop.
18+
map. If you have experience with other programming languages, `range` is roughly equivalent to a for-each loop.
1919

2020
#### Ranging over slices
2121

22-
Consider the following program, which iterates over a slice of snacks and generates a line of output for each one.
22+
We will explain how `range` works with a slice using an illustrative example. The program below iterates over a slice of
23+
snacks and generates a line of output for each one.
2324

2425
```yag
2526
{{ $snacks := cslice
@@ -32,8 +33,11 @@ Consider the following program, which iterates over a slice of snacks and genera
3233
{{ end }}
3334
```
3435

35-
Within the range block, the dot `.` is set to successive elements of the slice. In the first iteration, for instance,
36-
`.` holds the first element of the slice: `(sdict "Name" "chips" "Calories" 540)`. Hence
36+
The loop body—that is, the code between the opening `range $snacks` and the closing `end`—is executed
37+
multiple times, with the dot `.` set to each element of the slice in succession.
38+
39+
For instance, in the first iteration, the `.` holds the first element of the slice:
40+
`(sdict "Name" "chips" "Calories" 540)`. So
3741

3842
```yag
3943
{{ .Name }} contain {{ .Calories }} calories.
@@ -45,7 +49,8 @@ evaluates to
4549
chips contain 540 calories.
4650
```
4751

48-
and likewise for the second and third elements. The complete output is
52+
Likewise, the second iteration produces `peanuts contain 580 calories`, and the third produces `crackers contain 500 calories.`
53+
The complete output of the program is
4954

5055
```txt
5156
chips contain 540 calories.
@@ -55,9 +60,9 @@ chips contain 540 calories.
5560
crackers contain 500 calories.
5661
```
5762

58-
This output contains some unwanted whitespace: ideally, we want each snack to appear on a separate line with no leading
59-
indentation. However, the extra whitespace is to be expected with our current program: the range block is indented, and
60-
YAGPDB is simply reproducing that indentation.
63+
Notice that this output contains some unwanted whitespace: ideally, we want each snack to appear on a separate line with
64+
no leading indentation. However, the extra whitespace is to be expected with our current program; the range block is
65+
indented, and YAGPDB is simply reproducing that indentation:
6166

6267
```yag
6368
{{ range $snacks }}
@@ -66,37 +71,46 @@ YAGPDB is simply reproducing that indentation.
6671
{{ end }}
6772
```
6873

69-
One solution, then, is to remove the whitespace in our source code, save the final newline:
74+
To fix the excess whitespace in the output, then, one solution is to remove the corresponding whitespace in our source
75+
code:
7076

7177
```yag
72-
{{ range $snacks }}{{ .Name }} contains {{ .Calories }} calories
78+
{{ range $snacks }}{{ .Name }} contains {{ .Calories }} calories.
7379
{{ end }}
7480
```
7581

76-
Although this version works, we have sacrificed readability in the process. To retain the indentation in our source code
77-
while simultaneously avoiding unwanted whitespace in our output, we can use _trim markers_.
82+
However, though this version works, we have sacrificed readability in the process. Can we find a way to keep our source
83+
code indented while simultaneously hiding this indentation from the final output? It turns out that we can, by carefully
84+
adding _trim markers_.
7885

7986
```yag
8087
{{ range $snacks }}
8188
{{- .Name }} contain {{ .Calories }} calories.
89+
^^^
8290
{{ end }}
8391
```
8492

8593
`{{-` is a _left trim marker_ that instructs YAGPDB to ignore all leading whitespace, so this new version is
86-
functionally equivalent to the previous solution. A right trim marker, `-}}`, also exists and trims all trailing
87-
whitespace.
94+
functionally equivalent to the previous solution. A corresponding _right trim marker_, `-}}`, also exists and trims all
95+
trailing whitespace.
8896

8997
{{< callout context="tip" title="Tip: Trim Markers" icon="outline/rocket" >}}
9098

91-
Use trim markers `{{-` and `-}}` to remove unwanted whitespace in output while keeping your source code readable.
99+
Use trim markers `{{-` and `-}}` to control the whitespace output by your program.
100+
101+
A mnemonic to help remember what `{{-` and `-}}` do is to view them as arrows that gobble up whitespace in the direction
102+
they point; for instance, `{{-` points left, and eats all whitespace to the left.
92103

93104
{{< /callout >}}
94105

95106
#### Ranging over maps
96107

97108
It is also possible to range over the (key, value) pairs of a map. To do so, assign two variables to the result of the
98-
range action, corresponding to the key and value respectively. For example, the following program outputs the prices of
99-
various types of fruit, formatted nicely to 2 decimal places with the `printf` function.
109+
range action, corresponding to the key and value respectively. (Note that the dot `.` is still overwritten when ranging
110+
with variables.)
111+
112+
For example, the following program displays the prices of various types of fruit, formatted nicely to 2 decimal places
113+
with the `printf` function.
100114

101115
```yag
102116
{{ $fruitPrices := sdict "pineapple" 3.50 "apple" 1.50 "banana" 2.60 }}
@@ -106,19 +120,19 @@ various types of fruit, formatted nicely to 2 decimal places with the `printf` f
106120
{{ end }}
107121
```
108122

109-
Note that the names of the variables assigned to the key and value are arbitrary; instead of
110-
`range $fruit, $price := $fruitPrices`, we could also have written `range $k, $v := $fruitPrices`. However,
111-
if we use the names `$k`, `$v`, we must consistently refer to those in the loop body. That is, the following program
112-
is erroneous:
123+
The names of the variables assigned to the key and value are arbitrary; instead of
124+
`range $fruit, $price := $fruitPrices`, we could also have written `range $k, $v := $fruitPrices`.
125+
However, if we use the names `$k`, `$v`, we must consistently refer to those in the loop body. That is, the following
126+
program is erroneous:
113127

114128
```yag
115129
{{ range $k, $v := $fruitPrices }}
116-
{{- /* ERROR: undefined variables $fruit, $price */}}
130+
{{- /* ERROR: $fruit and $price are undefined; must use $k and $v instead */}}
117131
{{- $fruit }} costs ${{ printf "%.02f" $price }}.
118132
{{ end }}
119133
```
120134

121-
{{< callout context="tip" title="Tip" icon="outline/rocket" >}}
135+
{{< callout context="note" title="Note" icon="outline/info-circle" >}}
122136

123137
The two-variable form of range can also be used with a slice, in which case the first variable tracks the position of
124138
the element starting from `0`.
@@ -162,11 +176,11 @@ There are a few other, less common ways to invoke the range action.
162176
executed if the slice or map is empty.
163177

164178
```yag
165-
{{ $empty := cslice }}
166-
{{ range $empty }}
167-
{{/* ... */}}
179+
{{ $users := cslice }} {{/* imagine this data is dynamically generated */}}
180+
{{ range $user := $users }}
181+
{{/* do something with $user */}}
168182
{{ else }}
169-
slice was empty
183+
no users
170184
{{ end }}
171185
```
172186

content/learn/intermediate/data-types-2.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ to the `cslice` function:
1616
{{ $fruits := cslice "banana" "orange" "apple" }}
1717
```
1818

19-
All the elements in the `$fruits` have the same type (_string_), but this is not a requirement: it is valid, though
20-
rare, for a slice to contain values of different types.
19+
All the elements in the `$fruits` slice happen to have the same type (_string_), but this is not a requirement: it is
20+
valid, though rare, for a slice to contain elements of different types.
2121

22-
Besides primitives, slices may also contain more complex data types. In the previous chapter, for instance, we
23-
represented the fields of an embed as a slice of dictionaries.
22+
Besides primitives, slices may also contain more complex data types. In previous chapters, for instance, we represented
23+
the fields of an embed as a slice of dictionaries.
2424

2525
For available operations on slices, please refer to [our template documentation][docs-slices].
2626

0 commit comments

Comments
 (0)