作用域与可见性



静态作用域

CUE 使用 静态作用域而非动态作用域

引用的求值(或解析)是惰性的,参考 https://cuelang.org/play/?id=5AmcbLo3DPC#cue@export@cue

“example” 的字段结合了 #example 的定义,example 也没有将 #example 的字段放到它的作用域中。

引用查找

CUE 将会从最近的封闭作用域中查找要引用的值,

有些特殊的点:

  • 没有引号的字段,可以通过"点记法"作为标识符进行引用
  • 有引号的字段,必须通过"索引引用"
  • 跨作用域中定义字段,必须通过完整的路径解析

lookup.cue

val: 42
A: {
	val: 23
	num: val // will be 23, matches locally

	// irregular names need to be quoted and require indexing to access
	"user-id": "abc"
	UserID:    A["user-id"]
}
A: {
	b: val   // 42, matches top-level
	c: A.num // 23, reference A.num

	// num itself is not in scope even though it is part of A
}

别名 (Alias)

别名定义一个不属于 struct 的值,它们可以用于访问经过处理的字段、定义中间计算或表达式等,它们也不会被输出。

alias.cue

import "strings"

label: "app"
// alias for label
let L = label
S: {
	name: "Postgres"
	// intermediate value
	let lower = strings.ToLower(name)
	version: "13"
	label:   L
	image:   "docker.io/\(lower):\(version)"
}

路径(Paths)

正如我们所看到的,有好几种方式可以访问嵌套的值。

paths.cue

A: {
	a:    "A"
	"2f": 3
	l: ["cow", "moo"]
}

a: {
	// either is valid
	f1: A.a
	f2: A["a"]
	// must index
	f3: A["2f"]
	// list index
	f4: A.l[1]
}

隐式字段和值

隐式字段和值通过在前面增加下划线定义,可以在当前 package 进行引用,在计算时可以可选的显示它们,cue eval -H hidden.cue

如果想定义一个确实包含下划线的字段需要使用引号进行引用。

hidden.cue

A: {
	_hidden: "a hidden field"
	isshown: "I can be seen"
	hidrefd: _hidden + " sort of?"
}

_#NoshowDefn: {
	hello: string
	num:   int | *42
}

B: _#NoshowDefn & {hello: "world"}

cue eval hidden.cue

A: {
	isshown: "I can be seen"
	hidrefd: "a hidden field sort of?"
}
B: {
	hello: "world"
	num:   42
}

cue eval -H hidden.cue

A: {
	_hidden: "a hidden field"
	isshown: "I can be seen"
	hidrefd: "a hidden field sort of?"
}
B: {
	hello: "world"
	num:   42
}

注意,隐式字段在不同 package 中是不可见的,所以不可以使用引用的 package 中隐式字段。

引用循环

CUE 可以处理多次引用循环,只要它们最终能被解析为具体的值。

ref-cycle.cue

// a mathematically valid releationship
// but invalid in Cue until one or the other has a value
a: b - 10
b: a + 10

// we need to set a or b and Cue will do the rest
// if not, a cycle error will be reported
a: 100

构造循环

CUE 不允许存在构造循环和递归,可以定义无限的结构只要数据是有限的。

structural.cue

#List: {
	val:  _
	next: #List | *null
}

// Cannot do this, it is structural recursion
#Contains: {
	list:  #List
	val:   _
	found: bool | *false

	if list.val == val {
		found: true
	}
	if list.val != val && list.next != null {
		// No recursion!
		found: #Contains & {"list": list.next, "val": val}
	}
}

// We can define an infinite structure
list: #List & {val: "a", next: {val: "b"}}

// results in
list: {
	val: "a"
	next: {
		val:  "b"
		next: null
	}
}
我们绝不会将你的邮箱分享给任何人。
2022 Hofstadter, Inc