Built-in Functions
Carina provides built-in functions for string manipulation, list operations, map operations, networking, and security. All built-in functions support partial application when called with fewer arguments than expected.
String Functions
upper
Converts a string to uppercase.
upper(string: string) -> stringupper('hello') # => 'HELLO'upper('Hello World') # => 'HELLO WORLD'lower
Converts a string to lowercase.
lower(string: string) -> stringlower('HELLO') # => 'hello'lower('Hello World') # => 'hello world'trim
Removes leading and trailing whitespace from a string.
trim(string: string) -> stringtrim(' hello ') # => 'hello'trim('\n hello \t') # => 'hello'replace
Replaces all occurrences of a search string. Data-last argument order for pipe compatibility.
replace(search: string, replacement: string, string: string) -> stringreplace('-', '_', 'hello-world') # => 'hello_world''hello-world' |> replace('-', '_') # => 'hello_world' (pipe form)replace('::', '.', 'foo::bar::baz') # => 'foo.bar.baz'split
Splits a string into a list using a separator.
split(separator: string, string: string) -> listsplit('-', 'a-b-c') # => ['a', 'b', 'c']'a-b-c' |> split('-') # => ['a', 'b', 'c'] (pipe form)split('::', 'a::b::c') # => ['a', 'b', 'c']join
Joins list elements into a string using a separator.
join(separator: string, list: list) -> stringjoin('-', ['a', 'b', 'c']) # => 'a-b-c'['a', 'b', 'c'] |> join('-') # => 'a-b-c' (pipe form)join(', ', ['hello', 42]) # => 'hello, 42'List Functions
concat
Appends items to a list. Data-last argument order for pipe compatibility. The result is base_list followed by items.
concat(items: list, base_list: list) -> listconcat([3, 4], [1, 2]) # => [1, 2, 3, 4][1, 2] |> concat([3, 4]) # => [1, 2, 3, 4] (pipe form)concat(['c'], ['a', 'b']) # => ['a', 'b', 'c']flatten
Flattens nested lists by one level. Non-list elements are kept as-is.
flatten(list: list) -> listflatten([[1, 2], [3, 4]]) # => [1, 2, 3, 4]flatten([['a', 'b'], ['c']]) # => ['a', 'b', 'c']flatten([[1, 2], 3, [4]]) # => [1, 2, 3, 4]Only one level of nesting is removed:
flatten([[1, [2, 3]]]) # => [1, [2, 3]]length
Returns the number of elements in a list or map, or the number of characters in a string.
length(value: list | map | string) -> intlength([1, 2, 3]) # => 3length({a = 1, b = 2}) # => 2length('hello') # => 5length([]) # => 0map
Extracts a field from each element of a collection. The accessor must be a dot-prefixed string.
map(accessor: string, collection: list | map) -> list | mapWhen applied to a list of maps, returns a list of the extracted values:
let subnets = [ { name = 'a', subnet_id = 'id-1' }, { name = 'b', subnet_id = 'id-2' },]
map('.subnet_id', subnets) # => ['id-1', 'id-2']subnets |> map('.subnet_id') # => ['id-1', 'id-2'] (pipe form)When applied to a map of maps, returns a map with the same keys and extracted values:
let envs = { dev = { cidr = '10.0.0.0/16', name = 'development' } stg = { cidr = '10.1.0.0/16', name = 'staging' }}
envs |> map('.cidr') # => { dev = '10.0.0.0/16', stg = '10.1.0.0/16' }Map Functions
keys
Returns the keys of a map as a sorted list of strings.
keys(map: map) -> listkeys({ b = 2, a = 1, c = 3 }) # => ['a', 'b', 'c']keys({}) # => []values
Returns the values of a map as a list, ordered by sorted keys.
values(map: map) -> listvalues({ b = 2, a = 1, c = 3 }) # => [1, 2, 3]values({}) # => []lookup
Looks up a key in a map, returning a default value if the key is not found.
lookup(map: map, key: string, default: any) -> anylookup({ a = 'one', b = 'two' }, 'a', 'default') # => 'one'lookup({ a = 'one', b = 'two' }, 'c', 'default') # => 'default'Numeric Functions
min
Returns the smaller of two numbers. If both are integers, returns an integer. If either is a float, returns a float.
min(a: number, b: number) -> numbermin(3, 5) # => 3min(2.5, 1.0) # => 1.0min(1, 2.5) # => 1.0max
Returns the larger of two numbers. If both are integers, returns an integer. If either is a float, returns a float.
max(a: number, b: number) -> numbermax(3, 5) # => 5max(2.5, 1.0) # => 2.5max(1, 2.5) # => 2.5Networking Functions
cidr_subnet
Calculates a subnet CIDR block within a given IP network address prefix.
cidr_subnet(prefix: string, newbits: int, netnum: int) -> stringprefix: base CIDR string (e.g.,"10.0.0.0/16")newbits: number of additional bits for the subnet masknetnum: subnet number within the new address space
cidr_subnet('10.0.0.0/16', 8, 0) # => '10.0.0.0/24'cidr_subnet('10.0.0.0/16', 8, 1) # => '10.0.1.0/24'cidr_subnet('10.0.0.0/16', 8, 255) # => '10.0.255.0/24'cidr_subnet('10.0.0.0/8', 8, 10) # => '10.10.0.0/16'This is commonly used with for expressions to allocate subnets:
let vpcs = for (i, env) in ['dev', 'stg'] { awscc.ec2.vpc { cidr_block = cidr_subnet('10.0.0.0/8', 8, i) }}Environment Functions
env
Reads an environment variable. Returns an error if the variable is not set.
env(name: string) -> stringlet home = env('HOME')let db_host = env('DB_HOST')Security Functions
secret
Marks a value as secret. The value is sent to the provider but stored only as a SHA256 hash in state. Plan output displays (secret) instead of the actual value.
secret(value: any) -> secretawscc.rds.db_instance { master_user_password = secret(env('DB_PASSWORD'))}decrypt
Decrypts ciphertext using the configured provider’s encryption service (e.g., AWS KMS). The key argument is optional when the key identifier is embedded in the ciphertext.
decrypt(ciphertext: string, key?: string) -> string# Key embedded in ciphertext (e.g., AWS KMS encrypted blob)let password = decrypt('AQICAHh...')
# Explicit keylet password = decrypt('AQICAHh...', 'alias/my-key')
# Combined with secret() to prevent storing the decrypted value in stateawscc.rds.db_instance { master_user_password = secret(decrypt('AQICAHh...'))}Requires a configured provider with encryption support. An error is raised if no provider is configured or credentials are unavailable.