Scope and ownership
СсылкаThis page covers collection construction.
See Blocks and control flow for general loops and control transfer, Expressions and operators for indexing, and the Standard library for receiver methods. Records, enums and newtypes covers record updates. Functions and generics covers spread arguments in calls.
Construction syntax
СсылкаArrayLiteral = "[" (ArrayElement ("," ArrayElement)* ","?)? "]" ;ArrayElement = Expression | "..." Expression ;SetLiteral = "set" "{" (Expression ("," Expression)* ","?)? "}" ;MapLiteral = "map" "{" (MapEntry ("," MapEntry)* ","?)? "}" ;MapEntry = Expression ":" Expression ;ArrayComprehension = "[" Clauses "=>" Expression "]" ;SetComprehension = "set" "{" Clauses "=>" Expression "}" ;MapComprehension = "map" "{" Clauses "=>" Expression ":" Expression "}" ;Clauses = ForClause (ForClause | IfClause)* ;ForClause = "for" Pattern "in" ControlOperand ;IfClause = "if" ControlOperand ;
The grammar is transcribed from the linked parser evidence. Expression, Pattern, and ControlOperand are supplied by their respective language definitions.
Collection literal entries
An array literal accepts expressions and . entries. A set literal contains expressions, and a map literal contains key: value entries.
Причина
Each literal exposes whether it stores a sequence, unique values, or key and value associations. Map entries keep each key beside its value.
Comprehension clauses and body
A comprehension starts with for pattern in (source). Additional clauses use for pattern in (source) or if (condition). The => token introduces the body. A map body has the form key: value.
Причина
Comprehensions reuse the existing for and if control forms. The final arrow separates selection of bindings from the value produced for them.
Literal types and array spread
СсылкаArray literal type
An array literal forms Array<T> from its element types.
Причина
A shared element type gives indexing and iteration one type contract. Inferring it from the entries avoids repeating type information for every value.
Set literal type
A set literal forms Set<T> from its element types.
Причина
A shared element type lets membership and duplicate checks use one value contract. The supplied entries provide the information needed to infer that type.
Map literal type
A map literal forms Map<K, V> from its key and value types.
Причина
Separate key and value types let lookup check a key without requiring the payload to have the same type. Each side is inferred from its own entries.
Context for empty collections
Причина
Collection syntax does not introduce a separate typing model.
Bare empty collections require context
Причина
The reason a collection needs context is independent of its surface form.
Array spread element type
Spreading a concrete Array<T> contributes elements of type T to the containing array literal.
Причина
Spread inserts the contents of an array into the surrounding sequence. Its element type must therefore contribute to the result instead of introducing another array layer.
Reject a non-array spread operand
An array spread whose concrete, non-union operand type is not Array<T> produces TPZ5001.
Причина
Array spread copies stored array elements. Requiring an array avoids adding an implicit conversion from other iterable values during construction.
Array construction order
Array construction appends ordinary values and inserts each spread operand’s elements at the spread position.
Причина
Arrays preserve positions, so each entry must contribute where it appears. Expanding a spread in place preserves the relative order of its elements.
Collection key checks
Key-capability checking applies to set elements and map keys in literals and comprehensions, independently of map values.
Причина
Set elements and map keys determine membership and lookup identity. Map values are payloads, so they do not need the key comparison capability.
Rejected collection key types
A function, Map, Set, Range, or ByteBuffer used as a set element or map key produces TPZ5007. A compound key containing one of these types also produces TPZ5007.
Причина
Keys require a supported equality comparison throughout their structure. Rejecting incompatible components prevents membership and lookup from reaching an unsupported comparison.
Admitted keys and stored values
Map keys and Set elements follow value semantics at insertion. Scalars include integer and floating values, strings, booleans, unit/null, Bytes, Path, URL, Date, BigInt, and Decimal. Option/Result payloads, arrays, records, enum payloads, and newtype contents must recursively be keyable. Map, Set, Range, ByteBuffer, functions, templates, File, JSONValue, Regex, Match, TOMLValue, and RoundingMode are rejected as keys. Imported namespaces and host-provided opaque values are also not keys. Structural guards bound recursive key checks. A generic type parameter passing the static gate is not evidence that every substitution is keyable; the concrete runtime value must still pass this domain check.
Причина
Stable stored values keep membership and lookup consistent. Insertion follows value semantics, including compound keys.
Where collection expectations come from
Binding annotations, expected call parameters, declared returns, block tails, parentheses, and expected function result types can supply a collection expectation. Empty literals follow empty collection context. A collection expectation does not select one arm from a union. Contextual literal typing does not change collection variance or general assignability.
Причина
A surrounding type remains useful through grouping and block tails. Sharing that context across bindings, calls, and returns avoids making empty collection typing depend on presentation.
Context through collection components
A matching Array<E>, Set<E>, or Map<K, V> expectation supplies the component types for each emitted element, key, and value. Nonempty literals and comprehension bodies receive those component expectations, including through declared or expected callable results. After successful component checking, a comprehension retains the expected type arguments in its result without further widening. Comprehension iterator sources keep their own inferred types, and filters require bool. A rigid type parameter remains rigid. An incompatible concrete component must still be rejected. Callable result inference retains the actual body constraints for its enclosing comparison. Array spread checks its contributed element type. Collection variance, assignability, and key eligibility are unchanged.
A matching collection expectation may contain a type parameter fixed by the surrounding generic declaration; that parameter remains a constraint. Fresh call inference still follows the ordinary per-call rules. Context completes missing information and checks concrete expressions using the existing assignability rules. It does not choose a collection arm from a union expectation. An array spread contributes its actual element type, so the spread operand retains its own array type. Set elements and map keys still pass the key-capability checks.
Причина
A collection expectation already identifies the types of the values being assembled. Passing those component types into every literal and comprehension body gives the same information to nested expressions across collection forms. Comprehension sources can have different element types from their outputs, so their types come from the source expressions. Preserving concrete component constraints keeps contextual inference sound.
An empty sibling cannot erase a known type mismatch
Completing an empty collection from context must preserve the constraints of its concrete siblings. A nested string array cannot satisfy an int-array expectation merely because another map value is empty. SELF currently has a whole-type refinement path that can erase this mismatch; retain the intended rejection while that implementation limitation is reviewed.
Причина
Filling an unknown element type must not erase a known incompatible value. Otherwise an annotation could admit values that violate the collection type.
Comprehension clauses and results
СсылкаCallback methods and comprehensions
Callback methods such as values. and values. apply existing function values and chain their transformations. A comprehension states source bindings, filters, and emitted values together. It constructs an array, set, or map and can combine several sources.
Array map and filter evaluate their receiver and callback expression once in ordinary call order. Each method then makes a complete eager pass in element order. It calls its function once per element. A filter retains successful elements in that order. Each method finishes before the next method in a chain begins. Thus values. finishes every call to p before its first call to f.
A comprehension eagerly builds its result. Its first source evaluates once. Each later source evaluates again for each earlier binding combination that reaches it. Clauses run in written order. Each filter decides whether later clauses and the body run for the current bindings. The body runs before traversal advances to the next reached combination.
For the same array and fixed pure functions that complete, values. and [for value in (values) => f(value)] produce the same ordered values. A pure function has the same result for the same arguments and has no observable effects. values. and [for value in (values) if (p(value)) => f(value)] also produce the same ordered values. The second comprehension calls f immediately after a successful p for each element. Effects and failures retain these evaluation boundaries.
A lambda callback owns its postfix ? return destination under lambda and callback propagation. A map of Result-returning callbacks produces an array of Results. Filter still requires a bool callback result. Comprehensions retain their existing evaluation and failure boundaries.
Причина
A callback chain communicates reuse of function values through successive transformations. A comprehension communicates how source bindings and filters construct a new collection. These intentions and their evaluation boundaries differ even when pure functions produce equal values. Both forms preserve that distinction.
Nested comprehension clauses
Each later comprehension clause executes inside the preceding clauses.
Причина
Later clauses can use earlier bindings because they execute inside those scopes. This gives the clause sequence the same meaning as explicit nested loops.
Comprehension filter scope
A comprehension if filter runs the remaining clauses and body when its condition is true and skips them when it is false.
Причина
A filter decides whether the remaining work runs for the current bindings. Skipping that work on false avoids computing values that will not enter the result.
Accumulate reached body results
Each successful comprehension body evaluation contributes one element or one map key/value pair.
Причина
Each reached body supplies one result entry. This keeps the number and order of produced entries tied to successful body evaluations.
Comprehension source and pattern types
For a concrete Array<T>, Set<T>, or Range<T> source, a comprehension checks its pattern against the source element type T.
Причина
The iteration pattern receives an element, not the collection itself. Using the source element type makes pattern checking agree with each value encountered at runtime.
Reject a non-iterable source
A concrete non-iterable source in a comprehension produces TPZ5001.
Причина
Iteration requires a defined sequence of elements. Rejecting other values avoids inventing an implicit conversion or a type-dependent notion of iteration.
Comprehension filters require bool
A comprehension if condition must have type bool. A non-boolean condition produces TPZ5001.
Причина
A filter uses the same boolean condition rule as if. Requiring bool avoids an additional truthiness convention for numbers, strings, or collections.
Array comprehension type
Without a matching array expectation, an array comprehension independently infers and widens its body type T, producing Array<T>. With a matching expectation, component checking and the result type follow collection context propagation.
Причина
Independent inference supplies a useful collection type without context. A matching expectation supplies component types that remain intact after successful checking.
Set comprehension type
Without a matching set expectation, a set comprehension independently infers and widens its body type T, producing Set<T>. With a matching expectation, component checking and the result type follow collection context propagation.
Причина
Independent inference supplies a useful collection type without context. A matching expectation supplies component types that remain intact after successful checking.
Map comprehension type
Without a matching map expectation, a map comprehension independently infers and widens its key type K and value type V, producing Map<K, V>. With a matching expectation, component checking and the result type follow collection context propagation.
Причина
Independent inference supplies a useful collection type without context. A matching expectation supplies component types that remain intact after successful checking.
Collection and comprehension evaluation order
Literal elements and spread sources evaluate in source order. Each map key evaluates before its value. A comprehension reevaluates each later iterator source for every earlier binding combination that reaches it; an if filter controls only the following clauses and body. Map literals and comprehensions evaluate all pairs before the constructor checks for duplicate keys. A duplicate does not erase effects already performed by later pairs.
Причина
A fixed operand order makes collection effects reproducible. Map construction receives evaluated pairs, so expression evaluation and duplicate validation have separate failure points.
Failure while producing a collection
If an element, iterator source, filter, key, or value faults or propagates an early result, later expressions are not evaluated and no collection result is produced on that path. Effects already performed remain observable. This production failure is distinct from duplicate-map validation, which starts only after all pairs have been accumulated; ordinary faults follow the fault cleanup rule.
Причина
A failed expression cannot supply a value for construction. Stopping at that point prevents later effects while preserving effects that already happened.
Comprehension scopes and arrow boundaries
Each for source is resolved before that clause introduces its fresh immutable pattern bindings. Later clauses and the body see earlier bindings, and a later for clause may shadow an earlier name. Each source and filter uses the required outer parentheses and ordinary expression grammar inside them. The comprehension body arrow follows the complete parenthesized operand.
Причина
A source is evaluated before its new pattern binds names, so it cannot accidentally refer to its own new binding. Required operand parentheses separate ordinary lambda syntax from the comprehension body arrow.
A refutable pattern does not silently filter
A comprehension may use a refutable pattern. Each reached element must match. The first mismatch raises runtime TPZ5001 and stops construction. Use an explicit filter or match expression to skip elements.
Причина
A binding pattern requires an element to have the stated shape. Filtering belongs to if, so a pattern mismatch must not silently discard data.
Names inside one pattern must be distinct
One pattern introduces one scope and must not bind the same name twice. This differs from valid shadowing across separate for clauses. SELF currently misses the same-scope duplicate guard on plain list patterns; the intended TPZ5008 rejection is retained as an implementation limitation.
Причина
One pattern must give each bound name one value. Repeated names would silently choose between different positions in the same element.
Duplicate elements and keys
СсылкаSet order and duplicate elements
Set literals and comprehensions preserve the order of first occurrence and collapse duplicate elements.
Reinsertion, removal, traversal, and display follow Map and Set insertion order.
Причина
Set membership ignores repeated equal elements. Preserving first encounter order also keeps iteration reproducible without rearranging the surviving values.
Map and Set insertion order
Map keys, values, and entries are observed in insertion order. Traversing those views with for preserves that order. Map display uses the same order. Inserting a new key appends it. Inserting an existing key replaces its value without moving the key. Removing a key preserves the relative order of surviving entries.
Set traversal and display follow insertion order. Adding an existing element keeps its position. Removing an element preserves the relative order of surviving elements. Set construction follows first occurrence order. Map and Set equality remains independent of this observation order.
Insertion and transfer follow collection value semantics. Collection equality is independent of insertion order.
Причина
Map and Set use the same order rule. Preserving insertion order makes traversal and display reproducible. Replacing a value does not rearrange unrelated entries.
Repeated map literal keys
Repeating a string or integer literal key in a map literal produces TPZ5602.
Причина
Two entries for the same key cannot both survive as separate associations. Rejecting an evident collision before execution catches accidental overwrites early.
Computed map key collisions
When computed keys collide during map literal or comprehension construction, execution fails with TPZ4601 without replacing the earlier value.
Причина
Computed keys can collide after evaluation. Rejecting the collision prevents source order from silently choosing which value survives.
Computed map collision location
A computed duplicate key faults at the span of the complete map literal, whose start is the map keyword. The fault location is not the second key expression. The source-backed expectation for this fixture is example.tpz:2:14; the public CLI emission is tracked as an implementation limitation.
Причина
A duplicate key is a conflict within the constructed map. Pointing to that construction identifies the operation that could not produce a value.
Canonical key equality
Key insertion follows value semantics. Canonical key equality compares the stored value family and then its contents recursively. Arrays compare elementwise; records compare field names and values; nominal records, enums, and newtypes retain declaration identity. Floating signed zeros compare equal, while NaN does not equal any key, including itself. Integer and floating keys have distinct tags. Equivalent constant spellings do not define different language values merely because static duplicate detection recognizes only some forms.
Причина
Key comparison uses stored value contents while preserving scalar tags and nominal identity. A nominal Eq method does not replace that key identity. Different constant spellings must not create a separate key identity.
Duplicate constant boolean keys
A repeated constant boolean key is a duplicate just as a repeated constant string or integer key is. SELF currently parses booleans as expression/boolean but its constant-key checker tests expression/bool. The intended TPZ5602 rejection is retained as a product test, and the mismatched syntax kind is an implementation limitation.
Причина
A boolean key has the same identity whether it is written directly or computed. Detecting a known collision early preserves the runtime duplicate-key rule.
Examples and expected results
СсылкаArray, set, and map literals
Ссылкаlet values: Array<int> = [1, 2, 3]let names: Set<string> = set { "Ada", "Lin" }let counts: Map<string, int> = map { "Ada": 1, "Lin": 2 }
example.tpz: types-ok (1 module)
example.tpz: resolve-ok (1 module)
Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
example.tpz: types-ok (1 module)example.tpz: resolve-ok (1 module)
Наблюдаемые утверждения · Пройдено · 5.21.3
Код завершения 0.
example.tpz: types-ok (1 module)example.tpz: resolve-ok (1 module)
Нет вывода ошибок.
- Пройдено · expected 0; observed 0
- Пройдено · stdout matches the authored expectation
- Пройдено · stderr matches the authored expectation
Give empty collections a contextual type
Ссылкаlet values: Array<int> = []let names: Set<string> = set {}let counts: Map<string, int> = map {}
example.tpz: types-ok (1 module)
example.tpz: resolve-ok (1 module)
Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
example.tpz: types-ok (1 module)example.tpz: resolve-ok (1 module)
Наблюдаемые утверждения · Пройдено · 5.21.3
Код завершения 0.
example.tpz: types-ok (1 module)example.tpz: resolve-ok (1 module)
Нет вывода ошибок.
- Пройдено · expected 0; observed 0
- Пройдено · stdout matches the authored expectation
- Пройдено · stderr matches the authored expectation
Append an array at the spread position
Ссылкаimport std.io { writeLine }let values = [0, ...[1, 2], 3]for value in (values) {writeLine("{value}")}
0
1
2
3
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
0123
Наблюдаемые утверждения · Пройдено · 5.21.3
Код завершения 0.
0123
Нет вывода ошибок.
- Пройдено · expected 0; observed 0
- Пройдено · stdout matches the authored expectation
- Пройдено · stderr matches the authored expectation
Nest clauses and filter the remaining body
Ссылкаimport std.io { writeLine }let values = [for x in ([1, 2]) for y in ([10, 20]) if (x == 2) => x + y]for value in (values) {writeLine("{value}")}
12
22
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
1222
Наблюдаемые утверждения · Пройдено · 5.21.3
Код завершения 0.
1222
Нет вывода ошибок.
- Пройдено · expected 0; observed 0
- Пройдено · stdout matches the authored expectation
- Пройдено · stderr matches the authored expectation
Construct a set from repeated body values
Ссылкаimport std.io { writeLine }let values = set { for n in ([1, 2, 3, 4]) => n % 2 }for value in (values) {writeLine("{value}")}
1
0
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
10
Наблюдаемые утверждения · Пройдено · 5.21.3
Код завершения 0.
10
Нет вывода ошибок.
- Пройдено · expected 0; observed 0
- Пройдено · stdout matches the authored expectation
- Пройдено · stderr matches the authored expectation
Produce key/value pairs in a map comprehension
Ссылкаlet squares: Map<int, int> = map { for n in ([1, 2, 3]) if (n > 1) => n: n * n }
example.tpz: types-ok (1 module)
example.tpz: resolve-ok (1 module)
Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
example.tpz: types-ok (1 module)example.tpz: resolve-ok (1 module)
Наблюдаемые утверждения · Пройдено · 5.21.3
Код завершения 0.
example.tpz: types-ok (1 module)example.tpz: resolve-ok (1 module)
Нет вывода ошибок.
- Пройдено · expected 0; observed 0
- Пройдено · stdout matches the authored expectation
- Пройдено · stderr matches the authored expectation
Reject a bare empty array without context
Ссылкаlet values = []
Нет стандартного вывода.error[TPZ5020]: `[]` needs a contextual type (§22.1): annotate the binding or the expected element type
--> example.tpz:1:14
|
1 | let values = []
| ^^
example.tpz: 1 type diagnostic
Ожидаемый результат
Ожидаемый результат
Этап отклонения check. Ненулевой код завершения.
bare-empty-array-without-context at
example.tpz:1:14
Наблюдаемые утверждения · Пройдено · 5.21.3
Код завершения 1.
Нет стандартного вывода.
error[TPZ5020]: `[]` needs a contextual type (§22.1): annotate the binding or the expected element type--> example.tpz:1:14|1 | let values = []| ^^example.tpz: 1 type diagnostic
- Пройдено · expected nonzero; observed 1
- Пройдено · stdout matches the authored expectation
- Пройдено · checking TPZ5020; cause bare-empty-array-without-context; primary location asserted; additional diagnostics allow
Reject a concrete non-array spread operand
Ссылкаlet values = [...1]
Нет стандартного вывода.error[TPZ5001]: array spread needs an `Array`, found `1`
--> example.tpz:1:18
|
1 | let values = [...1]
| ^
example.tpz: 1 type diagnostic
Ожидаемый результат
Ожидаемый результат
Этап отклонения check. Ненулевой код завершения.
concrete-non-array-spread at
example.tpz:1:18
Наблюдаемые утверждения · Пройдено · 5.21.3
Код завершения 1.
Нет стандартного вывода.
error[TPZ5001]: array spread needs an `Array`, found `1`--> example.tpz:1:18|1 | let values = [...1]| ^example.tpz: 1 type diagnostic
- Пройдено · expected nonzero; observed 1
- Пройдено · stdout matches the authored expectation
- Пройдено · checking TPZ5001; cause concrete-non-array-spread; primary location asserted; additional diagnostics allow
Reject an integer comprehension filter
Ссылкаlet values = [for n in ([1, 2]) if (1) => n]
Нет стандартного вывода.error[TPZ5001]: expected `bool`, found `int`
--> example.tpz:1:34
|
1 | let values = [for n in [1, 2] if 1 => n]
| ^
example.tpz: 1 type diagnostic
Ожидаемый результат
Ожидаемый результат
Этап отклонения check. Ненулевой код завершения.
non-boolean-comprehension-filter at
example.tpz:1:37
Наблюдаемые утверждения · Пройдено · 5.21.3
Код завершения 1.
Нет стандартного вывода.
error[TPZ5001]: expected `bool`, found `int`--> example.tpz:1:34|1 | let values = [for n in [1, 2] if 1 => n]| ^example.tpz: 1 type diagnostic
- Пройдено · expected nonzero; observed 1
- Пройдено · stdout matches the authored expectation
- Пройдено · checking TPZ5001; cause non-boolean-comprehension-filter; primary location asserted; additional diagnostics allow
Reject a repeated identical string key
Ссылкаlet values = map { "same": 1, "same": 2 }
Нет стандартного вывода.error[TPZ5602]: duplicate key in `map { … }` literal
--> example.tpz:1:31
|
1 | let values = map { "same": 1, "same": 2 }
| ^^^^^^
example.tpz: 1 type diagnostic
Ожидаемый результат
Ожидаемый результат
Этап отклонения check. Ненулевой код завершения.
repeated-identical-string-key-in-map-literal at
example.tpz:1:31
Наблюдаемые утверждения · Пройдено · 5.21.3
Код завершения 1.
Нет стандартного вывода.
error[TPZ5602]: duplicate key in `map { … }` literal--> example.tpz:1:31|1 | let values = map { "same": 1, "same": 2 }| ^^^^^^example.tpz: 1 type diagnostic
- Пройдено · expected nonzero; observed 1
- Пройдено · stdout matches the authored expectation
- Пройдено · checking TPZ5602; cause repeated-identical-string-key-in-map-literal; primary location asserted; additional diagnostics allow
Reject colliding computed map keys at runtime
Ссылкаfunction key(value: int) -> int { value % 2 }let values = map { key(1): 10, key(3): 30 }
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Этап отклонения run. Ненулевой код завершения.
computed-map-key-collision
Контракт обязательного основного местоположения не определён.
Repair the computed-key collision
Ссылкаfunction key(value: int) -> int { value % 2 }let values: Map<int, int> = map { key(1): 10, key(2): 20 }
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
Наблюдаемые утверждения · Пройдено · 5.21.3
Код завершения 0.
Нет стандартного вывода.
Нет вывода ошибок.
- Пройдено · expected 0; observed 0
- Пройдено · stdout matches the authored expectation
- Пройдено · stderr matches the authored expectation
Reject a computed collision at the map literal start
Ссылкаfunction key(value: int) -> int { value % 2 }let values = map { key(1): 10, key(3): 30 }
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Этап отклонения run. Ненулевой код завершения.
computed-map-key-collision at
example.tpz:2:14
Run the corresponding map with distinct computed keys
Ссылкаfunction key(value: int) -> int { value % 2 }let values = map { key(1): 10, key(2): 30 }
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
Store and deduplicate array key values before later mutation
Ссылкаimport std.iolet mut source = [1]let keys = set { source, [1], [2] }source.push(9)for key in (keys) {io.writeLine("{key.length}")}
1
1
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
11
Set elements follow value semantics. Changing source leaves the stored array values and their membership unchanged.
Reject a Map used as a Set element
Ссылкаlet keys = set { map { "a": 1 } }
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Этап отклонения check. Ненулевой код завершения.
structures-map-is-not-keyable at
example.tpz:1:12
Use recursively keyable arrays as Set elements
Ссылкаlet keys = set { [1], [2] }
example.tpz: types-ok (1 module)
example.tpz: resolve-ok (1 module)
Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
example.tpz: types-ok (1 module)example.tpz: resolve-ok (1 module)
Keep numeric key families distinct and collapse signed floating zero
Ссылкаimport std.iolet zeros = set { 0.0, -0.0 }let tagged = set { 1, 1.0 }let mut zeroCount = 0for value in (zeros) { zeroCount += 1 }let mut taggedCount = 0for value in (tagged) { taggedCount += 1 }io.writeLine("{zeroCount}:{taggedCount}")
1:2
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
1:2
Reject repeated true keys in a map literal
Ссылкаlet values = map { true: 1, true: 2 }
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Этап отклонения check. Ненулевой код завершения.
structures-duplicate-boolean-map-key at
example.tpz:1:29
Check distinct true and false keys
Ссылкаlet values = map { true: 1, false: 2 }
example.tpz: types-ok (1 module)
example.tpz: resolve-ok (1 module)
Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
example.tpz: types-ok (1 module)example.tpz: resolve-ok (1 module)
Observe literal and nested comprehension evaluation order
Ссылкаimport std.iofunction mark(label: string, value: int) -> int {io.writeLine(label)value}function source(n: int) -> Array<int> {io.writeLine("source:{n}")[n, n + 10]}function outerAllowed(n: int) -> bool {io.writeLine("outer:{n}")n > 0}function keep(n: int) -> bool {io.writeLine("filter:{n}")n < 10}let values = [mark("array1", 1), ...[mark("spread", 2)], mark("array3", 3)]let pairs = map { mark("key1", 1): mark("value1", 10), mark("key2", 2): mark("value2", 20) }let nested = [for outer in ([0, 1, 2]) if (outerAllowed(outer)) for inner in (source(outer)) if (keep(inner)) => mark("body:{inner}", inner)]io.writeLine("done")
array1
spread
array3
key1
value1
key2
value2
outer:0
outer:1
source:1
filter:1
body:1
filter:11
outer:2
source:2
filter:2
body:2
filter:12
done
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
array1spreadarray3key1value1key2value2outer:0outer:1source:1filter:1body:1filter:11outer:2source:2filter:2body:2filter:12done
Stop producing elements after Result propagation
Ссылкаimport std.iofunction item(label: string, fail: bool) -> Result<int, string> {io.writeLine(label)if (fail) { Err("stop") } else { Ok(1) }}function build() -> Result<Array<int>, string> {let values = [item("first", false)?, item("second", true)?, item("third", false)?]Ok(values)}let outcome = build()match (outcome) {case Err(message) => io.writeLine(message)case Ok(_) => io.writeLine("unexpected success")}
first
second
stop
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
firstsecondstop
Reject a duplicate after evaluating all map pairs
Ссылкаimport std.iofunction mark(label: string, value: int) -> int {io.writeLine(label)value}let values = map { mark("key1", 1): mark("value1", 10), mark("key2", 1): mark("value2", 20), mark("key3", 3): mark("value3", 30) }io.writeLine("after")
key1
value1
key2
value2
key3
value3
Ожидаемый результат
Ожидаемый результат
Этап отклонения run. Ненулевой код завершения.
computed-map-key-collision at
example.tpz:6:14
key1value1key2value2key3value3
Check annotations, calls, returns, callbacks, and nested empties
Ссылкаfunction empty<T>() -> Array<T> { [] }function count(values: Array<int>) -> int { values.length }function invoke(callback: () -> Array<int>) -> Array<int> { callback() }let nested: Array<Array<int>> = [[], [1]]let items: Array<int | string> = [1, "text"]let n = count([])let callback: () -> Array<int> = () => []let result = invoke(() => [])let parenthesized: Array<int> = ([])let block: Array<int> = { [] }let keys: Set<int> = set {}let table: Map<string, int> = map {}
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
Reject a bare empty Set without context
Ссылкаlet missing = set {}
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Этап отклонения check. Ненулевой код завершения.
structures-empty-collection-context at
example.tpz:1:15
Give the empty Set an element type
Ссылкаlet present: Set<int> = set {}
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
Reject a concrete mismatch in a nested array
Ссылкаlet nested: Array<Array<int>> = [["text"]]
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Этап отклонения check. Ненулевой код завершения.
structures-nested-array-element-type at
example.tpz:1:35
Match the nested array element expectation
Ссылкаlet nested: Array<Array<int>> = [[1]]
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
Preserve a known mismatch beside a nested empty value
Ссылкаlet values: Array<Map<string, Array<int>>> = [map { "bad": ["text"], "empty": [] }]
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Этап отклонения check. Ненулевой код завершения.
structures-nested-array-element-type at
example.tpz:2:17
Complete the empty value without a conflicting sibling
Ссылкаlet values: Array<Map<string, Array<int>>> = [map { "bad": [1], "empty": [] }]
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
Shadow across clauses and delimit source or filter lambdas
Ссылкаimport std.iolet values = [for x in ([1, 2]) for x in ([x, x + 10]) => x]for value in (values) { io.writeLine("{value}") }let selected = [for x in ((() => [1, 2])()) if (((n: int) => n > 1)(x)) => x]for value in (selected) { io.writeLine("selected:{value}") }
1
11
2
12
selected:2
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
111212selected:2
Collect when every element matches the refutable pattern
Ссылкаimport std.iolet values = [for Some(x) in ([Some(1), Some(2)]) => x]for value in (values) { io.writeLine("{value}") }
1
2
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
12
Reject a repeated name within one list pattern
Ссылкаlet values = [for [x, x] in ([[1, 2]]) => x]
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Этап отклонения check. Ненулевой код завершения.
structures-duplicate-pattern-binding at
example.tpz:1:23
Use distinct names within the list pattern
Ссылкаlet values = [for [x, y] in ([[1, 2]]) => x + y]
example.tpz: types-ok (1 module)
example.tpz: resolve-ok (1 module)
Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
example.tpz: types-ok (1 module)example.tpz: resolve-ok (1 module)
Stop at a nonmatching element
Ссылкаimport std.iolet values = [for Some(x) in ([Some(1), None(), Some(3)]) => x]io.writeLine("after")
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Этап отклонения run. Ненулевой код завершения.
structures-for-pattern-nonmatch at
example.tpz:2:14
Check every literal component from its collection context
Ссылкаnewtype Wrapped<T> = Tlet array: Array<Wrapped<int>> = [Wrapped(1)]let keys: Set<Wrapped<int>> = set { Wrapped(2) }let table: Map<Wrapped<int>, Wrapped<string>> = map { Wrapped(3): Wrapped("three") }
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
Check emitted comprehension components from their result context
Ссылкаnewtype Wrapped<T> = Tlet array: Array<Wrapped<int>> = [for item in ([1, 2]) => Wrapped(item)]let keys: Set<Wrapped<int>> = set { for item in ([1, 2]) => Wrapped(item) }let table: Map<Wrapped<int>, Wrapped<string>> = map { for item in ([1, 2]) => Wrapped(item): Wrapped("{item}") }
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
Carry collection context through declared and expected callable results
Ссылкаnewtype Wrapped<T> = Tfunction wrap<T>(value: T) -> Array<Wrapped<T>> { [Wrapped(value)] }let callback: () -> Set<Wrapped<int>> = () => set { Wrapped(1) }let result: Array<Wrapped<int>> = wrap(2)let keys = callback()
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
Reject a concrete mismatch inside a contextual set
Ссылкаlet values: Set<Array<int>> = set { ["text"] }
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Этап отклонения check. Ненулевой код завершения.
structures-nested-array-element-type at
example.tpz:1:38
Supply a compatible element in the same contextual set
Ссылкаlet values: Set<Array<int>> = set { [1] }
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
Keep map values outside the set key domain under an annotation
Ссылкаlet keys: Set<Map<string, int>> = set { map { "a": 1 } }
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Этап отклонения check. Ненулевой код завершения.
structures-map-is-not-keyable at
example.tpz:1:11
Use a keyable collection element under an annotation
Ссылкаlet keys: Set<Array<int>> = set { [1] }
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
Inferred comprehension types
Ссылкаlet inferredArray = [for item in ([0]) => 1]let array: Array<int> = inferredArraylet inferredSet = set { for item in ([0]) => 1 }let keys: Set<int> = inferredSetlet inferredMap = map { for item in ([0]) => 1: "one" }let table: Map<int, string> = inferredMap
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
Array comprehension with an expected literal type
Ссылкаlet array: Array<1> = [for item in ([0]) => 1]
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
Set comprehension with an expected literal type
Ссылкаlet keys: Set<1> = set { for item in ([0]) => 1 }
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
Map comprehension with an expected literal type
Ссылкаlet table: Map<1, "one"> = map { for item in ([0]) => 1: "one" }
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
Reuse functions through callback methods
Ссылкаimport std.iofunction addPadding(width: int) -> int { width + 2 }function double(width: int) -> int { width * 2 }let widths = [10, 20]let chained = widths.map(addPadding).map(double)let constructed = [for width in (widths) => double(addPadding(width))]for width in (chained) {io.writeLine("callback {width}")}for width in (constructed) {io.writeLine("comprehension {width}")}
callback 24
callback 44
comprehension 24
comprehension 44
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
callback 24callback 44comprehension 24comprehension 44
Construct a collection from filtered sources
Ссылкаimport std.iolet widths = [10, 20]let paddings = [1, 2]let outerWidths = [for width in (widths) if (width > 10) for padding in (paddings) => width + padding * 2]for width in (outerWidths) {io.writeLine("{width}")}
22
24
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
2224
Observe complete callback passes and per-element comprehension work
Ссылкаimport std.iofunction source() -> Array<int> {io.writeLine("source")[1, 2, 3]}function selected(value: int) -> bool {io.writeLine("select {value}")value > 1}function convert(value: int) -> int {io.writeLine("convert {value}")value * 10}function predicate() -> (int) -> bool {io.writeLine("predicate")selected}function transformation() -> (int) -> int {io.writeLine("transformation")convert}io.writeLine("callback chain")let chained = source().filter(predicate()).map(transformation())io.writeLine("comprehension")let constructed = [for value in (source()) if (selected(value)) => convert(value)]io.writeLine("results")for value in (chained) {io.writeLine("callback {value}")}for value in (constructed) {io.writeLine("comprehension {value}")}
callback chain
source
predicate
select 1
select 2
select 3
transformation
convert 2
convert 3
comprehension
source
select 1
select 2
convert 2
select 3
convert 3
results
callback 20
callback 30
comprehension 20
comprehension 30
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
callback chainsourcepredicateselect 1select 2select 3transformationconvert 2convert 3comprehensionsourceselect 1select 2convert 2select 3convert 3resultscallback 20callback 30comprehension 20comprehension 30
Keep a Map key in place when replacing its value
Ссылкаimport std.io { writeLine }let mut values = map { "first": 1, "middle": 2, "last": 3 }values.insert("middle", 20)for key in (values.keys) { writeLine(key) }for value in (values.values) { writeLine("{value}") }for entry in (values.entries) { writeLine("{entry.key}={entry.value}") }writeLine("{values}")
first
middle
last
1
20
3
first=1
middle=20
last=3
Map{first: 1, middle: 20, last: 3}
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
firstmiddlelast1203first=1middle=20last=3Map{first: 1, middle: 20, last: 3}
Keep surviving Map entries in order after removal
Ссылкаimport std.io { writeLine }let mut values = map { "first": 1, "removed": 2, "third": 3, "last": 4 }values.remove("removed")for entry in (values.entries) { writeLine("{entry.key}={entry.value}") }writeLine("{values}")
first=1
third=3
last=4
Map{first: 1, third: 3, last: 4}
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
first=1third=3last=4Map{first: 1, third: 3, last: 4}
Keep surviving Set elements in order after removal
Ссылкаimport std.io { writeLine }let mut values = set { 3, 1, 4, 2 }values.add(1)values.remove(1)for value in (values) { writeLine("{value}") }writeLine("{values}")
3
4
2
Set{3, 4, 2}
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
342Set{3, 4, 2}
Pending contracts
СсылкаRelated diagnostics and references
СсылкаValue is not comparable or keyable →