This guide answers some questions about a language change that happened in CUE version 0.11 – including how to tell if the change affects your CUE, and how to update any CUE that’s affected.

What’s changed, and how can I tell if my CUE is affected?

From version 0.11 onwards, the list arithmetic operators * and + don’t work in CUE evaluated by the cue command and the Go API. Your CUE is not affected if a 0.11 version of cue vet evaluates it successfully.

This CUE no longer works, and must be updated as demonstrated below:

list-arithmetic.cue
A: [1, 2, 3] * 2         // Invalid CUE!
B: [1, 2, 3] + [4, 5, 6] // Invalid CUE!

The * and + operators continue to work as expected in all other situations, such as numeric arithmetic and string composition. They are only affected by this change if they are used with a list value on their left or right side.

CUE versions 0.11 and later report the following errors when evaluating CUE that contains list arithmetic operators:

TERMINAL
$ cue vet list-arithmetic.cue
A: Multiplication of lists is superseded by list.Repeat; see https://cuelang.org/e/v0.11-list-arithmetic:
    ./list-arithmetic.cue:1:4
B: Addition of lists is superseded by list.Concat; see https://cuelang.org/e/v0.11-list-arithmetic:
    ./list-arithmetic.cue:2:4

What changes are needed in my CUE?

  • Wherever the * operator is used with a list: use list.Repeat instead.
  • Wherever the + operator is used to combine lists: use either list.Concat or a nested for loop instead.
  • Use cue fix to try and make the changes automatically.

cue fix will make these changes for you in many cases, but only if you are using cue command version
v0.11.0-alpha.1 or later. Here’s how to use cue fix:

Start with some CUE that requires changes because it uses list arithmetic operators:

changes-required.cue
// "[1, 2, 3] * 2" is no longer valid CUE.
A: [1, 2, 3] * 2

// "[1, 2, 3] + [4, 5, 6]" is no longer valid CUE.
B: [1, 2, 3] + [4, 5, 6]

// "[1, 2, 3] + [4, 5, 6]" can also be rewritten using a nested for loop:
B: [for i in [1, 2, 3] {i}, for i in [4, 5, 6] {i}]

// The operators can still be used, unchanged, to produce number, string, and bytes types.
C: 1 + 2*3.3
D: 2*"O." + 3*"X."
E: 2*'X.' + 3*'O.'

Use cue fix to update files, packages, or entire modules. The command is silent unless it fails to process its inputs:

TERMINAL
$ cue fix changes-required.cue

cue fix updates its inputs in place, rewriting files on disk:

changes-required.cue
import "list"

// "[1, 2, 3] * 2" is no longer valid CUE.
A: list.Repeat([1, 2, 3], 2)

// "[1, 2, 3] + [4, 5, 6]" is no longer valid CUE.
B: list.Concat([[1, 2, 3], [4, 5, 6]])

// "[1, 2, 3] + [4, 5, 6]" can also be rewritten using a nested for loop:
B: [for i in [1, 2, 3] {i}, for i in [4, 5, 6] {i}]

// The operators can still be used, unchanged, to produce number, string, and bytes types.
C: 1 + 2*3.3
D: 2*"O." + 3*"X."
E: 2*'X.' + 3*'O.'

Why do I still get evaluation failures after running cue fix?

cue fix can only update CUE where the list arithmetic operators are used with a literal list value (e.g. [1, 2, 3]). The command can’t detect when they are used with a list value via a reference – you must update these uses manually, for the time being.

The following CUE would not be updated by cue fix:

references.cue
// This file contains invalid CUE.
x: [1, 2, 3]
y: [4, 5, 6]

A: x * 2 // Invalid use of the "*" operator with a list reference.
B: x + y // Invalid use of the "+" operator with two list references.

This file must be manually updated with the following CUE:

references.cue
import "list"

x: [1, 2, 3]
y: [4, 5, 6]

A: list.Repeat(x, 2)
B: list.Concat([x, y])

Why are list arithmetic operators being removed?

Early versions of the CUE language allowed lists to be used with the arithmetic operators “+” and “*”. This feature was removed from the language specification some years ago, with the removal being completed in CUE version 0.11.

The commit that removed them from the CUE language specification in 2021 explained the project’s rationale:

List operators are confusing [and unnecessary].

For instance, is the result of [a, ...] + [b, ...] open or closed?
What about [a] + [b, ...]?

Why were list arithmetic operators supported until now?

The CUE project takes its compatibility responsibilities to its users seriously. A capability that’s made available in a released version of CUE (as list arithmetic operators were) shouldn’t be removed the instant that it’s deprecated, even though CUE is still pre-version-1.0 and such an immediate removal might seem generally allowable under semantic versioning guidelines.

Users might have written CUE that relied on list arithmetic operators, so the CUE tooling supported this feature up to and including version 0.10 – which was released over 3½ years after the feature stopped being mentioned.

This breaking language change isn’t based on language.version from cue.mod/module.cue because a significant length of time has now passed without the feature being mentioned in the CUE language specification or official documentation.

I have a question that isn’t answered here

Please join the CUE community on GitHub, Slack, or Discord and ask the question there – we’ll be happy to help!