类型和数值



接下来介绍 CUE 的基本数据结构。

内置类型

CUE 有以下内置的类型,它们有意和 JSON 的类型对齐。

null  bool  string  bytes  number  list  struct
                             |
                            int

builtins.cue

N:   null
B:   bool
S:   string
By:  bytes
Num: number // Decimals or integers, a superclass if you will
Int: int    // Big Int which can represent values without limits
List: [...]
Struct: {...}

Top 和 Bottom

Top 和 Bottom 是 CUE 的特殊类型,他们构成了 的两端。

_” 用来表示 top,可以匹配所有值,它也被称为 “any”。

_|_” 用来表示 bottom,代表错误。 (这个符号将来可能被一个关键词取代)

Error

错误结果是在 bottom 并会携带错误信息,当从 CUE 导出数据而有未完成的类型,或在你代码包含冲突或无效的语义时,会发生错误。

errors.cue

s: "hello"
s: "world" // conflicting values "hello" and "world"

A: foo: "bar"
a: A.goo // undefined field A.goo (cue eval -c)

b: int // incomplete value (cue eval -c)

l: [1, 2]
l: [1, 3] // conflicting values 2 and 3

m: [1, 2]
v: m[2] // index out of range

cue eval -c errors.cue

l.1: conflicting values 3 and 2:
    ./errors.cue:7:7
    ./errors.cue:8:7
s: conflicting values "world" and "hello":
    ./errors.cue:1:4
    ./errors.cue:2:4

注意,因为这个 issue 并不会展示所有的错误

空值结合运算

空值结合运算在发生错误时提供备选,这是个技术方面的错误合并,因为 null 是个有效值。

使用析取符和默认值可以设置。

coalesce.cue

elems: ["a", "b", "c"]
a: *elems[0] | "A"
// out of bounds error
d: *elems[3] | "D"

S: {
	hello: "world"
}

// missing fields
s: *S.foo | "bar"

cue eval coalesce.cue

elems: ["a", "b", "c"]
a: "a"
d: "D"
S: {
	hello: "world"
}
s: "bar"

Number

CUE 定义了两种数字类型:

  • int 是整数,通过 BigInt 实现以代表所有值,而且可以限制字节长度(像 int64)
  • number 是小数,(也不受字节长度限制, ?),整数也是 number

numbers.cue

a: int
a: 42

b: number
b: 3.14

c: int & 42.0 // conflict int and 42.0

d: 42   // will be type int
e: 3.14 // will be type number

CUE 也有一些数字的语法糖:

  • 0x, 0o, 0b 分别代表十六进制(hex), 八进制(octal)和二进制(binary)
  • K, M, G, T, P 来表示数字大小,后面的 i 可以省略
  • e/E 表示十进制指数
  • 可以用下划线让大数更具可读性

number-sugar.cue

hex:  0xdeadbeef
oct:  0o755
bin:  0b0101_0001
cpu:  0.5Mi
mem:  4Gi
mill: 1M
bill: 1G
zero: 0.0
half: 0.5
trim: 01.23
mole: 6.022_140_76e+23
tiny: 1.2345e-12
long: 23_456_789_000_000000

cue eval number-sugar.cue

hex:  3735928559
oct:  493
bin:  81
cpu:  524288
mem:  4294967296
mill: 1000000
bill: 1000000000
zero: 0
half: 0.5
trim: 1.23
mole: 6.02214076e+23
tiny: 1.2345e-12
long: 23456789000000000

String

CUE 的字符串是有效的 UTF-8 字符串,特殊字符可以转义表示。

strings.cue

str:    "hello world"
smile:  "\U0001F60A"
quoted: "you can \"quote by escaping \\ \""
multiline: """
	hello world
	a "quoted string in a string"
	down under
	   - some author
	"""

cue eval strings.cue

str:    "hello world"
smile:  "😊"
quoted: "you can \"quote by escaping \\ \""
multiline: """
	hello world
	a "quoted string in a string"
	down under
	   - some author
	"""

转义方式:

\a   U+0007 alert or bell
\b   U+0008 退格
\f   U+000C 换页
\n   U+000A 换行
\r   U+000D 回车
\t   U+0009 水平制表符
\v   U+000b 垂直制表符
\/   U+002f 斜杠(solidus)
\\   U+005c 反斜杠
\'   U+0027 单引号 (只在单引号引用的字符串中生效)
\"   U+0022 双引号 (只在双引号引用的字符串中生效)

\nnn   八进制      (只在单引号引用的字符串中生效)
\xnn   十六进制    (只在单引号引用的字符串中生效)

\uXXXX  for unicode
\UXXXXXXXX for longer unicode

https://cuelang.org/docs/references/spec/#string-and-byte-sequence-literals

在下面章节中还有一种字符串插值的转义。

“Raw” String

CUE 允许修改字符串分隔符,所以可以避免使用转义,通过在普通字符串两端添加任意数量的 # 就可以。

rawstrings.cue

str1: #"avoid using \ to "escape""#
str2: ##"""
	#"""
	a nested multiline
	string goes here
	"""#
	"""##

cue eval rawstrings.cue --out json

{
    "str1": "avoid using \\ to \"escape\"",
    "str2": "#\"\"\"\na nested multiline\nstring goes here\n\"\"\"#"
}

Byte

字节是单引号引用并且输出时会被 base64 编码:

bytes.cue

b: '\x03abc\U0001F604'

cue eval bytes.cue

b: '\x03abc😄'

cue export bytes.cue --out json

{
    "b": "A2FiY/CfmIQ="
}

List

CUE 的列表可以包含任意类型的元素,列表可以保持开放(Open)也可以预设一些元素,错误匹配的元素将会导致错误。

lists.cue

empty: []
any: [...]
ints: [...int]
nested: [...[...string]]

opened: ints & [1, 2, ...]
closed: ints & [1, 2, 3]

// list of for constrained ints
ip: 4 * [uint8]
// sets the first element
tendot: ip & [10, ...uint8]
// uses constraint as second element
one72: ip & [172, >=16 & <=32, ...]

mixed: any & [...] & ["a", 1, {foo: "bar"}]
join:  [1, 2] + [3, 4]
Join:  opened & join

cue eval lists.cue

empty: []
any: []
ints: []
nested: []
opened: [1, 2]
closed: [1, 2, 3]
ip: [uint8, uint8, uint8, uint8]
tendot: [10, uint8, uint8, uint8]
one72: [172, uint & >=16 & <=32, uint8, uint8]
mixed: ["a", 1, {
	foo: "bar"
}]
join: [1, 2, 3, 4]
Join: [1, 2, 3, 4]

Struct

struct 很像 JSON 对象,它们是 CUE 主要的复合类型。

struct 包含一组字段 (label: value)。

默认情况下,struct 是开放(Open)的,可以被添加更多字段。

structs.cue

// an open struct
a: {
	foo: "bar"
}

// shorthand nested field
a: hello: "world"

// a closed struct
b: close({
	left: "right"
})

// error, field up not allowed
b: up: "down"

Definition

Definition 很像 struct,主要用于定义结构。

它们默认情况下是封闭(Close)的,而且 CUE 导出时 不会 被输出。

defns.cue

#schema: {
	word:      string
	num:       int | *42
	optional?: string
}

value: #schema & {
	word: "what's the good?"
}

cue eval defns.cue

#schema: {
	word: string
	num:  42
}
value: {
	word: "what's the good?"
	num:  42
}

cue export defns.cue

{
	"value": {
		"word": "what's the good?"
		"num":  42
	}
}

嵌套

可以在任意一个 struct 或 definition 中嵌套另一个 struct 或 definition 来构建数据。

通过开放的 struct / definition 和连接符实现同样的效果,但是通常不能修改嵌套的内容。

embed.cue

#A: {
	num: number
}

#B: {
	ans: string
}

// this won't work
#bad: #A & #B
bad:  #bad & {
	num: 42
	ans: "life"
}

// but this will
#val: {#A, #B}
val: #val & {
	num: 42
	ans: "life"
}

cue export embed.cue

{
	"val": {
		"num": 42
		"ans": "life"
	}
}

模式匹配约束

模式匹配现在允许对通过匹配的标签进行特定的约束。

目前来说还不成熟,但是当 query 提案 接受并实现之后,会变得更强大。

目前,你可以对字符串类型的标签约束,然后将其设为你想要设置的字段的值。

patterns.cue

#schema: {
	name: string
	ans:  string
	num:  int | *42
}

// match elem fields and alias labels to Name,
// unify with schema, set name to Name by label
elems: [Name=_]: #schema & {name: Name}

elems: {
	one: {
		ans: "solo"
		num: 1
	}
	two: {
		ans: "life"
	}
}

elems: other: {ans: "id", num: 23}

cue export patterns.cue

{
	"elems": {
		"one": {
			"name": "one"
			"ans":  "solo"
			"num":  1
		}
		"other": {
			"name": "other"
			"ans":  "id"
			"num":  23
		}
		"two": {
			"name": "two"
			"ans":  "life"
			"num":  42
		}
	}
}
我们绝不会将你的邮箱分享给任何人。
2022 Hofstadter, Inc