tur/list-typed
a phantom-typed (List A) view over the int64 cons-list carrier.
(List A) is the "either empty or a chain of Cons cells of A" view that smart constructors like refined.tur's ne-from? consume: it pins the element type at the boundary so downstream accessors recover A instead of a bare tyvar. It lowers to :int (the head cons-cell pointer, or 0 for empty) at zero runtime cost, sitting alongside the untyped carrier helpers (list-head, list-tail, ...) in list.tur, which keep working unchanged.
This module is NOT auto-loaded: List is an extremely common user type name (a plain (defdata List ...) in user code must not collide with it), so it stays opt-in via (load "stdlib/list-typed.tur"). refined.tur loads it for the NonEmpty smart constructors.
Since: end-to-end-monomorphization-plan (Phase 1.1)
List
(defopaque List [A] :int)
a typed view over the int64 cons-list carrier, carrying a phantom element type A.
Lowers to :int (the head cons-cell pointer, or 0 for empty). Construct it with list-of (variadic) or an explicit (:: ... (List A)) ascription on a tcons chain whose head type pins A.
Since: end-to-end-monomorphization-plan (Phase 1.1)
list-of
(list-of [A])
build a (List A) from N values, recovering A from the rest type.
| & xs -- zero or more elements, all of type A. |
A (List A) over the int64 cons-list carrier the variadic collector builds. With zero arguments, the empty list (carrier 0).
(list-empty? (list-of)) ; => true (list-empty? (list-of 1 2)) ; => false
Since: end-to-end-monomorphization-plan (Phase 1.1)
list-empty?
(list-empty? [A])
is a (List A) the empty list?
| xs | the (List A) to inspect |
true when xs is empty (carrier 0), false otherwise.
(list-empty? (list-of)) ; => true (list-empty? (list-of 9)) ; => false
Since: end-to-end-monomorphization-plan (Phase 1.1)
list->carrier
(list->carrier [A])
recover the raw int64 cons-list carrier from a (List A).
| xs | the (List A) to unwrap |
The underlying int64 cons-list pointer (0 for empty), suitable as input to the untyped carrier helpers (list-head, list-tail, list-length, ...).
(list-head (list->carrier (list-of 7 8))) ; => 7
Since: end-to-end-monomorphization-plan (Phase 1.1)
list-count
(list-count [A])
number of elements in a (List A), correct for aggregate A.
The element-aware length for the typed list view. list-length (the carrier helper) walks the chain at the fixed {int64 head; int64 tail} layout and segfaults when A is a by-value aggregate; list-count recovers the concrete (Cons A) layout and walks it via the typed tlength, so a (List (Option int)) (and any by-value-aggregate element) measures safely.
This relies on phantom-opaque element specialization: although (List A) lowers to the int64 carrier, the compiler mints a per-element-type clone of list-count when A is a by-value aggregate, so the inner (:: ... (Cons A)) resolves to the concrete cell layout instead of collapsing to the carrier.
| xs | the (List A) to measure |
Integer length (0 for the empty list).
(list-count (list-of 1 2 3)) ; => 3
Since: Phase G4 (carrier<->concrete ABI crossing audit)
list-nil
(list-nil [A])
the empty (List A).
The empty list (carrier 0); its element type comes from the context.
(list-empty? (:: (list-nil) (List int))) ; => true
Since: parsec-guide-plan P5
list-cons
(list-cons [A])
prepend x to xs.
| x | the new first element | |
| xs | the rest of the list |
A (List A) whose first element is x, followed by xs.
(list-count (list-cons 1 (list-of 2 3))) ; => 3
Since: parsec-guide-plan P5
list-first
(list-first [A])
the first element of a non-empty list.
| xs | a non-empty (List A); check with list-empty? first |
The first element.
(list-first (list-of 7 8)) ; => 7
Since: parsec-guide-plan P5
list-rest
(list-rest [A])
everything after the first element of a non-empty list.
| xs | a non-empty (List A) |
The (List A) after the first element (empty for a one-element list).
(list-first (list-rest (list-of 7 8))) ; => 8
Since: parsec-guide-plan P5
list-foldl
(list-foldl [A B])
fold a list from the left.
| xs | the list to fold | |
| init | the starting accumulator | |
| f | (fn [acc x] acc'), called once per element, first to last |
The final accumulator.
(list-foldl (list-of 1 2 3) 0 (fn [acc : int x : int] : int (+ acc x))) ; => 6
Since: parsec-guide-plan P5
list-reverse-onto__
(list-reverse-onto__ [A])
internal: prepend xs, reversed, onto acc.
list-reverse
(list-reverse [A])
the elements of xs in reverse order.
| xs | the list to reverse |
A new (List A), last element first.
(list-first (list-reverse (list-of 1 2 3))) ; => 3
Since: parsec-guide-plan P5
list-map-onto__
(list-map-onto__ [A B])
internal: map f over xs, consing results onto acc in reverse.
list-map
(list-map [A B])
apply f to every element.
| xs | the list to map over | |
| f | the function applied to each element |
A new (List B) of the results, in the original order.
(list-first (list-map (list-of 1 2) (fn [x : int] : int (* x 10)))) ; => 10
Since: parsec-guide-plan P5
list->string-loop__
(list->string-loop__ [xs :(List Char) b :StringBuilder] :String)
internal: append each Char of xs to the builder.
list->string
(list->string [xs :(List Char)] :String)
the characters of a (List Char) as a String.
The usual last step of a character-level parser: (many (satisfy alpha?)) produces a (List Char), and this turns it into the String it spells.
| xs | the characters, first to last |
A fresh owned String.
(string/to-cstr (list->string (list-of #\h #\i))) ; => "hi"
Since: parsec-guide-plan P5