CX · Reference guide50 Ways to Love Your CX Programs
PlaygroundDownloadsAboutv0.18.0-pre.1

50 Ways to Love Your CX Programs

Fifty short CX code examples — paths, filters, conditionals, iteration, functions, modules — that walk from the simplest attribute read to a full pipeline with module activation, HTML-safe escaping, function definition, structured logging, semantic merge, and iteration. Each example pairs a tiny data input with a directive snippet.

1. A literal value

A bare expression evaluates to itself. Here, the number 42.

      42
    

2. A literal string

Same form; strings and numbers evaluate identically.

      'Hand-tossed since 1987'
    

3. Read an attribute — @name

@name after a path step selects the attribute named name. Prints "Margherita".

      [pizza name=Margherita]
         //pizza/@name
    

4. Find anywhere — //

// matches a pizza element at any depth.

      [order [pizza name=Margherita]]
         //pizza/@name
    

5. Inside body text

A [?str] template drops a computed value into text. The rest stays as written.

      [pizza name=Margherita]
         [?let [= $p [$first //pizza]]
           [receipt [?str 'Thanks for ordering {$p@name}!']]]
    

6. Inside an attribute value

Expressions evaluate in attribute-value position via [?str …]. One mechanism, two positions.

      [user id=42 name=Joe]
         [?let [= $u [$first //user]]
           [a href=[?str '/u/{$u@id}/profile'] [?str "View {$u@name}'s profile"]]]
    

7. Several holes in one template

A template can carry any number of holes.

      [pizza name=Margherita price=12]
         [?let [= $p [$first //pizza]]
           [line [?str '{$p@name} — {$p@price}€']]]
    

8. Inside a generated element

Per iteration, build a fully-formed [a href=… …] element.

      [catalog [c cid=42 name=Joe] [c cid=43 name=Ann]]
         [?for [in $c //c] [yield [a href=[?str "/u/{$c/@cid}"] $c/@name]]]
    

9. Child step

Child steps separated by /. Prints "Margherita".

      [shop [menu [pizza name=Margherita]]]
         //shop/menu/pizza/@name
    

10. Parent axis — parent::*

Walks up one element. Prints "New Haven".

      [shop name='New Haven' [pizza name=Margherita]]
         //pizza/parent::*/@name
    

11. Ancestor axis

All ancestors of c, in document order — outermost first. Prints "top;mid;".

      [a tag=top [b tag=mid [c found]]]
         [?for [in $x //c/ancestor::*] [yield [?str "{$x/@tag};"]]]
    

12. Following-sibling axis

Walks siblings to the right of the matched node.

      [row [cell n=1] [cell n=2] [cell n=3]]
         [?for [in $x //cell[= $_@n 1]/following-sibling::*] [yield [?str "{$x/@n};"]]]
    

13. Predicate filter — [@attr=value]

Brackets inside path expressions are predicates — prefix code over the context node $_.

      [menu [pizza name=Margherita] [pizza name=Hawaiian]]
         //pizza[= $_@name 'Hawaiian']/@name
    

14. Upper-case

Wrap a value in a call form to apply a function.

      [pizza name=margherita]
         [?let [= $p [$first //pizza]] [$upper $p@name]]
    

15. Default — fall back when missing

[?else EXPR DEFAULT] yields EXPR unless it is absent (or an error) — graceful fallback, no exception.

      [pizza name=Mystery]
         [?else //pizza/@price 0]
    

16. Composed filters — nested

Inside-out: trim, then upper.

      [pizza name='  margherita  ']
         [?lib 'cx-stdlib/strings']
         [?let [= $p [$first //pizza]]
           [$upper [$strings:trim [$string $p@name]]]]
    

17. String length

Counts characters. Prints 10.

      [pizza name=Margherita]
         [?let [= $p [$first //pizza]] [$string-length $p@name]]
    

18. Today's date

[$time:now] and [$time:today] from the cx-stdlib/time module (clock capability — grant --allow-clock).

      [?lib 'cx-stdlib/time']
[$time:today]
    

19. Pipeline — left-to-right composition

Same result as composed filters, read top-down instead of inside-out.

      [pizza name='  margherita  ']
         [?lib 'cx-stdlib/strings']
         [?let [= $p [$first //pizza]]
           [?pipe [$string $p@name] [$strings:trim] [$upper]]]
    

20. Method-call style via pipe

Reads as "take name, then lower it". The value threads through each bare stage; _ is the threaded value.

      [pizza name=MARGHERITA]
         [?let [= $p [$first //pizza]]
           [?pipe $p@name [$lower]]]
    

21. String concatenation

Join strings with [$concat …].

      [user first=Ada last=Lovelace]
         [?let [= $u [$first //user]]
           [$concat $u@first ' ' $u@last]]
    

22. Range — M to N

Inclusive range. Prints "1;2;3;4;".

      [?for [in $n [$range 1 4]] [yield [?str "{$n};"]]]
    

23. If — bracket-clause form

Three clauses: condition, [then …], [else …].

      [pizza stock=0]
         [?let [= $p [$first //pizza]]
           [?if [> $p@stock 0] [then 'in stock'] [else 'out of stock']]]
    

24. If — alternate values

Same semantics, named clause children read clearly.

      [pizza stock=5]
         [?let [= $p [$first //pizza]]
           [?if [> $p@stock 0] [then 'in stock'] [else 'out of stock']]]
    

25. Skip the else branch

A false condition yields the empty sequence — [else …] is optional.

      [pizza featured=true]
         [?let [= $p [$first //pizza]]
           [?if $p@featured [then '★ featured!']]]
    

26. Existence check

A node-set is truthy when non-empty.

      [pizza [tags vegan]]
         [?if //tags [then yes] [else no]]
    

27. Multi-branch — no else-if ladder

Use multi-arm [?match] with predicate-only [when …] clauses.

      [pizza stock=2]
         [?let [= $p [$first //pizza]]
           [?match
             [when [> $p@stock 100] 'plenty']
             [when [> $p@stock 10]  'some']
             [when [> $p@stock 0]   'last few']
             [else                  'sold out']]]
    

28. For — explicit binding

The [in $v SRC] clause introduces the loop variable and source.

      [pizza [topping cheese] [topping basil] [topping oil]]
         [?for [in $t //topping] [yield [?str '{[$text $t]};']]]
    

29. For — anonymous over implicit $_

Drop the variable to bind $_ automatically for each iteration.

      [pizza [topping cheese] [topping basil] [topping oil]]
         [?for [in //topping] [yield [?str '{[$text $_]};']]]
    

30. Range loop — generate elements

Produces [slot id=1][slot id=2][slot id=3].

      [?for [in $n [$range 1 3]] [yield [slot id=$n]]]
    

31. Nested for

Loop over pizzas; inside, loop over each pizza's toppings.

      [shop [pizza name=Margherita [topping cheese] [topping basil]]]
         [?for [in $p //pizza] [yield
           [grp [?str "{$p/@name}: "] [?for [in $t $p/topping] [yield [?str '{[$text $t]},']]]]]]
    

32. For — over a single element

A single-element source binds once. Prints "Pepe / IT".

      [shop [meta owner=Pepe region=IT]]
         [?for [in $m //meta] [yield [?str "{$m/@owner} / {$m/@region}"]]]
    

33. Let — bind an element, project its attrs

[?let] binds the meta element once, then projects two attributes from it.

      [shop [meta owner=Pepe region=IT]]
         [?let [= $m //meta] [?str "{$m/@owner}/{$m/@region}"]]
    

34. Let — bind once, reuse

Compute tax once, use it where the binding is in scope.

      [pizza price=12]
         [?let [= $p   [$first //pizza]]
               [= $tax [* $p@price 0.22]]
           [?str "Total: {[+ $p@price $tax]}€"]]
    

35. Let — bind a pipeline result

Pipelines and let-bindings compose naturally.

      [pizza name='  margherita  ']
         [?lib 'cx-stdlib/strings']
         [?let [= $p [$first //pizza]]
               [= $clean [?pipe [$string $p@name] [$strings:trim] [$upper]]]
           [?str "Welcome, {$clean}!"]]
    

36. Define a template fragment

[?def name () BODY] — zero-arg function definition. Call as [$slogan].

      [?def slogan () [?str 'Hand-tossed since 1987']]
         [$slogan]
    

37. With one parameter

Parameters go in the (…) parameter list. Call with [$shout arg].

      [?def shout ($x) [?str "LOUD: {$x}!"]]
         [$shout 'pizza ready']
    

38. Multiple parameters

Space-separated params; prints "cheese / basil".

      [?def pair ($a $b) [?str "{$a} / {$b}"]]
         [$pair 'cheese' 'basil']
    

39. Function plus iteration

A reusable per-item template, mapped over a node set.

      [?def line ($item) [?str "sku={$item/@sku};"]]
         [order [v sku=A] [v sku=B] [v sku=C]]
         [?for [in $x //v] [yield [$line $x]]]
    

40. Higher-order — [?fn] and call

[?fn ($p) BODY] is an anonymous function literal; pass it as a value.

      [pizza [v n=5]]
         [?let [= $dbl [?fn ($x) [* $x 2]]]
           [?for [in $x //v] [yield [$dbl $x/@n]]]]
    

41. HTML-safe output — reserved, refused until it ships

[?cx output-target=html] is reserved and refused: the pragma key set is a closed registry (include | schema | version | lint-disable | lint-enable), and output-target refuses with a message saying exactly why — it once passed through as inert data while reading like an XSS defense, which is the silent-acceptance class CX refuses everywhere else. Until context-aware escaping ships, route untrusted values through an escaping renderer at the HTML boundary.

      [?cx output-target=html]
         [pizza name='<script>alert(1)</script>']
         //pizza/@name
    
      error: cx-err:CXER0100: parse: invalid [?cx] directive: 1:24: [?cx output-target] is reserved and NOT implemented — output is not escaped by it; remove the pragma until context-aware output escaping ships (CXP-1) at line 1:1
    

42. The closed pragma registry

Every [?cx …] pragma key comes from a closed registry — include, schema, version, lint-disable, lint-enable — and an unknown key is a loud parse refusal naming that registry, never a silent pass-through. version is reader-facing metadata and round-trips verbatim; the other four are consumed by the resolver, the validator, and the linter.

      [?cx version=1.0]
         [pizza name='Margherita']
         //pizza/@name
    

43. Load a module

[?lib] loads a bundled stdlib module; module-qualified calls use [$prefix:fn args].

      [?lib 'cx-stdlib/cx']
         [?lib 'cx-stdlib/format']
         [$format:canonical [$cx:parse '[a   x=1  ]']]
    

44. [$cx:parse] — read CX from a string

CX reads its own syntax as data. Code is data.

      [?lib 'cx-stdlib/cx']
         [$cx:parse '[pizza name=Margherita]']
    

45. [$cx:emit] — emit a value back to text

Round-trip: parse then emit. Prints [a x=1 y=2].

      [?lib 'cx-stdlib/cx']
         [$cx:emit [$cx:parse '[a x=1 y=2]']]
    

46. [$format:canonical] — normalize

Whitespace and attribute order canonicalized; idempotent.

      [?lib 'cx-stdlib/cx']
         [?lib 'cx-stdlib/format']
         [$format:canonical [$cx:parse '[a   x=1   y=2]']]
    

47. Content digest — hash the canonical form

Stable digest over the canonical bytes. Same input always yields the same hash, in every binding.

      [?lib 'cx-stdlib/cx']
         [?lib 'cx-stdlib/format']
         [?lib 'cx-stdlib/hash']
         [$hash:sha256-hex [$format:canonical [$cx:parse '[pizza name=Margherita]']]]
    

48. Override — pure-functional update as merge

Two trees combined with [?modify]. The coupon's price=10 overrides the order's; the original order is unchanged.

      [order [pizza name=Margherita price=12]]
         [coupon price=10]
         [?let [= $order [$first //order]]
               [= $coupon [$first //coupon]]
           [?modify $order //pizza/@price [set $coupon@price]]]
    

49. Structured logging

[$log:LEVEL msg fields=…] emits a structured event; fields= is a map.

      [?lib 'cx-stdlib/log']
         [$log:info 'sale' fields={pizza: 'Margherita', price: 12}]
         [$log:debug 'suppressed at the default level']
    

50. The whole kitchen

Module loading, function definition, structured logging, pure-functional override, iteration. A handful of lines; the whole arc.

      [order [pizza name=Margherita price=12]]
         [coupon price=10]
         [?lib 'cx-stdlib/log']
         [?def line ($p) [li [?str "{$p/@name} — {$p/@price}€"]]]
         [?let [= $order [$first //order]]
               [= $coupon [$first //coupon]]
               [= $final [?modify $order //pizza/@price [set $coupon@price]]]
           ([$log:info 'rendering receipt'],
            [ul [?for [in $p $final/pizza] [yield [$line $p]]]])]
    

The arc. Read a value → put it in context → walk paths → filter and combine → branch → loop → factor into functions → declare an output target → reflect / hash / merge / log. Every step adds exactly one capability; data from §14 flows through unchanged.