Scopes and Visibility



Reference Lookup

Cue will reference a value from the nearest enclosing scope. Some quirks are:

  • fields without quotes you can reference as identifiers and with dot notation
  • fields with quotes require index notation
  • fields defined across scopes require sufficient paths to resolve

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
}

Aliases

An alias defines a local value which is not part of the struct. They can be used for accessing shadowed fields, naming intermediate calculations or expressions, and more. They will not be output.

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

As we’ve seen, there are a few ways to access nested values.

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]
}

Hidden Fields and Values

Hidden fields and values are prefixed with underscores. You can reference them in the current package and optionally show them when evaluating. Use quotes if you want a real label that begins with an underscore.

note, hidden output appears (no pun intended) to be broken in v0.3.0-alpha6

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
}

Reference Cycles

Cue can resolve many cycles, as long as they resolve to a final, concrete value.

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

Structural Cycles

Structural cycles and recursion are not allowed in Cue. We can define infinite structures as long as the data is finite.

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
	}
}

2021 Hofstadter, Inc