表达式
数学运算符
CUE 包含数字的标准的数学表达式,也可以在 string 或 list 中使用乘法。
math-ops.cue
// stdlib functions
import "math"
// mathematical!
n1: 3 + 2
n2: 3 - 2
n3: 3 * 2
n4: 3 / 2
// Truncated division
q: quo ( - 5 , 2 )
r: rem ( - 5 , 2 )
// Euclidean division
d: div ( - 5 , 2 )
m: mod ( - 5 , 2 )
// imported functions
f: math . Floor ( 3.14 )
l: math . Log ( 100.2 )
t: math . Tan ( 1.0 )
cue eval math-ops.cue
n1: 5
n2: 1
n3: 6
n4: 1.5
q: - 2
r: - 1
d: - 3
m: 1
f: 3
l: 4.60716818865076442405424
t: 1.557407724654902
在 CUE 的
math package
中还有其他的运算操作。
比较运算符
CUE 拥有比较运算符和语义,值合并时会处理相等性检查。
compare-ops.cue
// number constraints
positive: > 0 // numbers
doubledig: >= 10 & < 100 & int
// lexical comparison
lowercase: >= "a" & <= "z"
notone: < 1 | > 1
notone: 1 // error, empty disjuntion
cue eval compare-ops.cue
positive: > 0
doubledig: uint & >= 10 & < 100
lowercase: >= "a" & <= "z"
notone: < 1 | > 1
预设范围
CUE 针对数字拥有以下预设的范围:
int8 >=-128 & <=127
int16 >=-32_768 & <=32_767
int32 >=-2_147_483_648 & <=2_147_483_647
int64 >=-9_223_372_036_854_775_808 & <=9_223_372_036_854_775_807
int128 >=-170_141_183_460_469_231_731_687_303_715_884_105_728 &
<=170_141_183_460_469_231_731_687_303_715_884_105_727
uint >=0
uint8 >=0 & <=255
uint16 >=0 & <=65536
uint32 >=0 & <=4_294_967_296
uint64 >=0 & <=18_446_744_073_709_551_615
uint128 >=0 & <=340_282_366_920_938_463_463_374_607_431_768_211_455
rune >=0 & <=0x10FFFF
正则表达式
CUE 支持正则表达式,通过 =~
和 !~
进行限制。
regexp.cue
a: "hello world" & =~ "^hello [a-z]+$"
b: "hello" & !~ "^[A-Z]+"
lowercase: =~ "^[a-z]+$"
c: "hello" & lowercase
d: "Hello" & lowercase // error
cue eval regexp.cue
a: "hello world"
b: "hello"
lowercase: =~ "^[a-z]+$"
c: "hello"
它们基于 Go 的正则表达式 , CUE 也有一些额外的
regexp helpers
嵌入
CUE 使用 \(<expr>)
就可以 string 或 byte 中插入值。
interpolate.cue
container: {
repo: "docker.io/cuelang"
image: "cue"
version: "v0.3.0"
full: "\( repo )/\( image ):\( version )"
}
name: "Tony"
msg: "Hello \( name )"
// conver string to bytes
b: '\( msg )'
// convert bytes to string
s: "\( b )"
cue eval interpolate.cue
container: {
repo: "docker.io/cuelang"
image: "cue"
version: "v0.3.0"
full: "docker.io/cuelang/cue:v0.3.0"
}
name: "Tony"
msg: "Hello Tony"
b: 'Hello Tony'
s: "Hello Tony"
更多复杂的场景,你可以使用
text/template
包。
你也可以插入字段名称(下面章节会讲)。
List 推导
CUE 可以通过 list 推导动态生成 list,可以遍历 list 或 struct 的字段。
形式是 [ for key, val in <iterable> [condition] { production } ]
* key 是 lists 的索引, 在 struct 中是字段的名称
list-comp.cue
nums: [ 1 , 2 , 3 , 4 , 5 , 6 ]
sqrd: [ for _ , n in nums {n * n}]
even: [ for _ , n in nums if mod (n, 2 ) == 0 {n}]
listOfStructs: [ for p, n in nums {
pos: p
val: n
}]
extractVals: [ for p, S in listOfStructs {S.val}]
cue eval list-comp.cue
nums: [ 1 , 2 , 3 , 4 , 5 , 6 ]
sqrd: [ 1 , 4 , 9 , 16 , 25 , 36 ]
even: [ 2 , 4 , 6 ]
listOfStructs: [{
pos: 0
val: 1
}, {
pos: 1
val: 2
}, {
pos: 2
val: 3
}, {
pos: 3
val: 4
}, {
pos: 4
val: 5
}, {
pos: 5
val: 6
}]
extractVals: [ 1 , 2 , 3 , 4 , 5 , 6 ]
每次条件判断只能引入一个元素
(https://github.com/cue-lang/cue/discussions/713 )
可以使用 list.FlattenN
解决这个问题
Field 推导
CUE 也可以通过推导生成字段
field-comp.cue
apps: [ "nginx" , "express" , "postgres" ]
#labels: [ string ]: string
stack: {
for i, app in apps {
"\( app )" : {
name: app
labels: #labels & {
app: "foo"
tier: "\( i )"
}
}
}
}
cue eval field-comp.cue
apps: [ "nginx" , "express" , "postgres" ]
#labels: {}
stack: {
nginx: {
name: "nginx"
labels: {
app: "foo"
tier: "0"
}
}
express: {
name: "express"
labels: {
app: "foo"
tier: "1"
}
}
postgres: {
name: "postgres"
labels: {
app: "foo"
tier: "2"
}
}
}
条件字段
条件字段,或受保护的字段(技术上意味着保护),是另一种形式的字段推导
相对于通常意义的 if,有一些注意事项:
没有 else 条件,必须有两个相反的判断条件
不会忽略任何判断条件,所有的条件都会被计算
guards.cue
app: {
name: string
tech: string
mem: int
if tech == "react" {
tier: "frontend"
}
if tech != "react" {
tier: "backend"
}
if mem < 1Gi {
footprint: "small"
}
if mem >= 1Gi && mem < 4Gi {
footprint: "medium"
}
if mem >= 4Gi {
footprint: "large"
}
}
// This will result in an error because CUE evaluates all conditions
// without short-circuiting, meaning it will still try to access app.field
// if app.field != _|_ && app.field == true {
// foo: true
// }
// Use nested guards to check multiple conditions
if app.field != _|_ {
if app.field == true {
foo: true
}
}