|
| 1 | +--- |
| 2 | +title: Trying the "aliasv2" experiment |
| 3 | +authors: [jpluscplusm,rogpeppe] |
| 4 | +toc_hide: true |
| 5 | +tags: [language] |
| 6 | +--- |
| 7 | +{{<sidenote text="Requires CUE v0.15.0 or later">}} |
| 8 | + |
| 9 | +{{{with _script_ "en" "cmd/cue prerelease"}}} |
| 10 | +export PATH=/cues/$CUELANG_CUE_PRERELEASE:$PATH |
| 11 | +{{{end}}} |
| 12 | + |
| 13 | +CUE v0.15.0-alpha.2 introduced the "aliasv2" experiment, which |
| 14 | +replaces alias syntax with a more consistent form. |
| 15 | + |
| 16 | +Enable the experiment on a per-file basis using the |
| 17 | +`@experiment(aliasv2)` |
| 18 | +attribute. |
| 19 | + |
| 20 | +{{<info>}} |
| 21 | +Because this experiment changes the meaning of currently valid CUE code, the command |
| 22 | +`cue fix --exp=aliasv2` |
| 23 | +should be used to update your CUE *before* adding `@experiment(aliasv2)`. |
| 24 | + |
| 25 | +See [`cue help fix`]({{<relref "docs/reference/command/cue-help-fix" >}}) |
| 26 | +for more information. |
| 27 | +{{</info>}} |
| 28 | + |
| 29 | +The experiment replaces CUE's current alias syntaxes |
| 30 | +with a unified syntax using the `~` operator in one of two forms, |
| 31 | +and defines the `self` indentifier: |
| 32 | + |
| 33 | +- `X~V` -- the single form creates alias `V` referring to the value of `X` |
| 34 | +- `X~(L,V)` -- the dual form creates alias `L` referring to the label of `X` |
| 35 | + and alias `V` referring to the value of `X` |
| 36 | +- `self` -- refers to the innermost CUE block that contains the identifier |
| 37 | + |
| 38 | +The new syntax can be used with fields, pattern constraints, and dynamic fields. |
| 39 | +Each of CUE's current alias syntaxes has a direct replacement, as outlined in |
| 40 | +[the experiment's proposal](https://github.com/cue-lang/proposal/blob/main/designs/language/4014-aliases-v2.md#summary-of-equivalent-forms). |
| 41 | +<!-- TODO: change link to point to spec, after https://cuelang.org/cl/1222377 lands --> |
| 42 | + |
| 43 | +Here are some examples of aliases using the current syntax, and their |
| 44 | +experimental syntax as rewritten by `cue fix`: |
| 45 | + |
| 46 | +{{<columns>}} |
| 47 | +{{{with upload "en" "1 old"}}} |
| 48 | +-- current-syntax.cue -- |
| 49 | +// Refer to a field whose name is |
| 50 | +// not a valid identifier. |
| 51 | +A="-foo": 42 |
| 52 | +b: A + 1 |
| 53 | + |
| 54 | +// Refer to a field's label. |
| 55 | +c: [L=string]: { |
| 56 | + id: L |
| 57 | +} |
| 58 | +c: foo: _ |
| 59 | + |
| 60 | +// Refer to a field's value. |
| 61 | +_d: V={ |
| 62 | + e: V.g + 1 |
| 63 | +} |
| 64 | +d: _d & { |
| 65 | + g: 44 |
| 66 | +} |
| 67 | + |
| 68 | +// Refer to a field inside a pattern constraint. |
| 69 | +h: PCF=[string]: { |
| 70 | + i: PCF.j + 1 |
| 71 | +} |
| 72 | +h: foo: j: 46 |
| 73 | + |
| 74 | +// Refer to a value inside a pattern constraint. |
| 75 | +k: [string]: PCV={ |
| 76 | + m: PCV.p + 1 |
| 77 | +} |
| 78 | +k: foo: p: 48 |
| 79 | +{{{end}}} |
| 80 | + |
| 81 | +{{{with _script_ "en" "1"}}} |
| 82 | +cp current-syntax.cue experimental-syntax.cue |
| 83 | +cue fix --exp=aliasv2 experimental-syntax.cue |
| 84 | +{{{end}}} |
| 85 | + |
| 86 | +{{<columns-separator>}} |
| 87 | + |
| 88 | +{{{with upload "en" "1 new"}}} |
| 89 | +# Required by https://cuelang.org/issue/4123, but is safe because the file is |
| 90 | +# emitted by cue-fix processing a cue-fmt'd source. |
| 91 | +#nofmt(experimental-syntax.cue) |
| 92 | +#assert |
| 93 | +-- experimental-syntax.cue -- |
| 94 | +@experiment(aliasv2) |
| 95 | + |
| 96 | +// Refer to a field whose name is |
| 97 | +// not a valid identifier. |
| 98 | +"-foo"~A: 42 |
| 99 | +b: A + 1 |
| 100 | + |
| 101 | +// Refer to a field's label. |
| 102 | +c: [string]~(L,_): { |
| 103 | + id: L |
| 104 | +} |
| 105 | +c: foo: _ |
| 106 | + |
| 107 | +// Refer to a field's value. |
| 108 | +_d: { |
| 109 | + let V = self |
| 110 | + e: V.g + 1 |
| 111 | +} |
| 112 | +d: _d & { |
| 113 | + g: 44 |
| 114 | +} |
| 115 | + |
| 116 | +// Refer to a field inside a pattern constraint. |
| 117 | +h: [string]~PCF: { |
| 118 | + i: PCF.j + 1 |
| 119 | +} |
| 120 | +h: foo: j: 46 |
| 121 | + |
| 122 | +// Refer to a value inside a pattern constraint. |
| 123 | +k: [string]: { |
| 124 | + let PCV = self |
| 125 | + m: PCV.p + 1 |
| 126 | +} |
| 127 | +k: foo: p: 48 |
| 128 | +{{{end}}} |
| 129 | + |
| 130 | +{{</columns>}} |
| 131 | + |
| 132 | +Because we used `cue fix` to rewrite `current-syntax.cue` as `experimental-syntax.cue`, |
| 133 | +we can be sure that these examples still define the same concrete data: |
| 134 | + |
| 135 | +{{<columns>}} |
| 136 | +{{{with script "en" "1 export current"}}} |
| 137 | +cue export current-syntax.cue --out yaml |
| 138 | +{{{end}}} |
| 139 | +{{<columns-separator>}} |
| 140 | +{{{with script "en" "1 export experimental"}}} |
| 141 | +cue export experimental-syntax.cue --out yaml |
| 142 | +{{{end}}} |
| 143 | +{{</columns>}} |
| 144 | + |
| 145 | +The experimental syntax makes some aliasing scenarios possible for the first |
| 146 | +time, where the current syntax does not provide a direct equivalent: |
| 147 | + |
| 148 | +{{{with code "en" "2 new"}}} |
| 149 | +#nofmt(experimental-syntax.cue) # Caused by https://github.com/cue-lang/cue/issues/4123 |
| 150 | +env PATH=/cues/$CUELANG_CUE_PRERELEASE:$PATH |
| 151 | + |
| 152 | +exec cue export experimental-syntax.cue --out yaml |
| 153 | +cmp stdout out |
| 154 | +-- experimental-syntax.cue -- |
| 155 | +@experiment(aliasv2) |
| 156 | + |
| 157 | +// Pattern constraint aliases make a field (F) and |
| 158 | +// its label (L) available within the scope of the |
| 159 | +// field's value. |
| 160 | +a: [string]~(L,F): { |
| 161 | + b: F.c + 1 |
| 162 | + id: L |
| 163 | +} |
| 164 | +a: foo: c: 42 |
| 165 | + |
| 166 | +"-foo": 44 |
| 167 | + |
| 168 | +// The self identifier grants access to top-level |
| 169 | +// fields whose names are not valid identifiers. |
| 170 | +d: self["-foo"] + 1 |
| 171 | + |
| 172 | +// Binding an identifier to the top level of the |
| 173 | +// file grants access to top-level fields that |
| 174 | +// would be shadowed, or whose names are not valid |
| 175 | +// identifiers. |
| 176 | +let Root = self |
| 177 | +e: { |
| 178 | + g: Root["-foo"] + 2 |
| 179 | + "-foo": "not-44" |
| 180 | +} |
| 181 | +-- out -- |
| 182 | +a: |
| 183 | + foo: |
| 184 | + b: 43 |
| 185 | + id: foo |
| 186 | + c: 42 |
| 187 | +-foo: 44 |
| 188 | +d: 45 |
| 189 | +e: |
| 190 | + g: 46 |
| 191 | + -foo: not-44 |
| 192 | +{{{end}}} |
| 193 | + |
| 194 | +## Conclusion |
| 195 | + |
| 196 | +Combining the `~` operator with the `self` identifier, the "aliasv2" experiment |
| 197 | +replaces all of CUE's different alias forms with a unified and consistent |
| 198 | +syntax. Each of their specific replacements are outlined in |
| 199 | +[the experiment's proposal](https://github.com/cue-lang/proposal/blob/main/designs/language/4014-aliases-v2.md#summary-of-equivalent-forms). |
| 200 | +Use `cue fix --exp=aliasv2` to apply the replacements to existing CUE automatically. |
| 201 | +<!-- TODO: change link to point to spec, after https://cuelang.org/cl/1222377 lands --> |
| 202 | + |
| 203 | +As with all CUE language experiments, one of this experiment's aims is to |
| 204 | +gather feedback from users. Please do join [the CUE community](/community/) |
| 205 | +and tell us about your experience with the experiment! |
| 206 | + |
| 207 | +## Related content |
| 208 | + |
| 209 | +- {{< linkto/related/reference "command/cue-help-experiments" >}} -- |
| 210 | + a list of the language experiments that can be enabled or disabled |
| 211 | +- {{< linkto/related/reference "command/cue-help-fix" >}} -- |
| 212 | + update CUE code automatically, applying the latest fixes and language experiments |
| 213 | +- [Equivalent current and experimental syntaxes](https://github.com/cue-lang/proposal/blob/main/designs/language/4014-aliases-v2.md#summary-of-equivalent-forms) -- |
| 214 | + each of CUE's alias forms expressed as its experimental equivalent <!-- TODO: replace with cuelang.org doc --> |
0 commit comments