Built-in list type has no literal-construction syntax — discussion #461

Closed
opened 2026-05-08 16:25:09 +00:00 by navicore · 1 comment
Owner

Summary

Seq's built-in list type has no literal-construction syntax.
Today the only way to put values into a list (that I'm aware of)
is to go through string.split:

"a b c" " " string.split        # List of three strings

For non-string element types or for ad-hoc test data, that's not
an option. This issue isn't a proposal — it's a problem statement
and a sketch of options, in case the topic is on the roadmap or
worth a side conversation.

Where the gap shows up

  • exercises/15-lists/01-basics.seq in seqlings. The exercise
    introduces the list type but has to construct every test list
    with string.split, which couples list-of-strings teaching to
    string parsing.
  • exercises/38-cons-list/ in seqlings (this one I just wrote
    to teach ADTs from variant primitives). Every test reads
    empty 3 swap prepend 2 swap prepend 1 swap prepend to build a
    three-element list. That's instructive once, but obscures the
    test that follows.
  • patch-seq/examples/data/cons-list.seq — your own canonical
    example does the same nil 3 swap cons 2 swap cons 1 swap cons
    dance for the demo list. It's idiomatic and clear once you read
    it, but it's also the same six tokens for every literal.

Sketch of options (not a proposal)

I don't have a strong opinion on which is right; flagging the
constraints I'm aware of so the conversation has a starting point.

  1. { 1 2 3 } — Factor-style.

    • Pros: Visually distinct from quotations; reads as a literal.
    • Cons: Allocates a new sigil; whether it lowers to a
      fixed-element or growable list is a separate decision.
  2. [ 1 2 3 ] >list — quotation-to-list conversion.

    • Pros: No new syntax — uses the existing quotation form plus
      a runtime word that walks the quotation and pushes its
      results into a list.
    • Cons: Slightly indirect; only works if the quotation has a
      known stack effect ( -- T T T … ).
  3. 3 [ 1 2 3 ] make-list — explicit length + quotation.

    • Pros: Type-checks cleanly; works the same as Factor's make
      pattern.
    • Cons: Counts are easy to get wrong; redundant with what the
      compiler can already see in the quotation.
  4. Stack-tagged form: 1 2 3 3 >list.

    • Pros: No new syntax at all; just one new word.
    • Cons: The trailing count is even less ergonomic than the
      swap prepend ladder for anything past three or four
      elements.
  5. #( 1 2 3 ) or another paren-prefixed form.

    • Pros: Parens already feel listy.
    • Cons: ( ... ) is reserved for stack effect comments, so a
      prefix sigil is needed.

Why I didn't just file a PR

The shape of "what's a list literal in a stack language?" is more
about taste than mechanics, and conflating list literals with
quotations (option 2) versus introducing a new sigil (options 1
and 5) versus going purely word-level (options 3 and 4) is a
direction call I'd want you to make.

If you'd rather close this and discuss in another forum, that's
fine — happy to follow wherever the conversation lives.

Where I hit it

Building the 38-cons-list chapter for seqlings, where the
test-data ladder dominated several otherwise-clean exercises.

## Summary Seq's built-in `list` type has no literal-construction syntax. Today the only way to put values into a `list` (that I'm aware of) is to go through `string.split`: ```seq "a b c" " " string.split # List of three strings ``` For non-string element types or for ad-hoc test data, that's not an option. This issue isn't a proposal — it's a problem statement and a sketch of options, in case the topic is on the roadmap or worth a side conversation. ## Where the gap shows up - **`exercises/15-lists/01-basics.seq` in seqlings.** The exercise introduces the `list` type but has to construct every test list with `string.split`, which couples list-of-strings teaching to string parsing. - **`exercises/38-cons-list/` in seqlings** (this one I just wrote to teach ADTs from variant primitives). Every test reads `empty 3 swap prepend 2 swap prepend 1 swap prepend` to build a three-element list. That's instructive *once*, but obscures the test that follows. - **`patch-seq/examples/data/cons-list.seq`** — your own canonical example does the same `nil 3 swap cons 2 swap cons 1 swap cons` dance for the demo list. It's idiomatic and clear once you read it, but it's also the same six tokens for every literal. ## Sketch of options (not a proposal) I don't have a strong opinion on which is right; flagging the constraints I'm aware of so the conversation has a starting point. 1. **`{ 1 2 3 }` — Factor-style.** - Pros: Visually distinct from quotations; reads as a literal. - Cons: Allocates a new sigil; whether it lowers to a fixed-element or growable list is a separate decision. 2. **`[ 1 2 3 ] >list` — quotation-to-list conversion.** - Pros: No new syntax — uses the existing quotation form plus a runtime word that walks the quotation and pushes its results into a list. - Cons: Slightly indirect; only works if the quotation has a known stack effect `( -- T T T … )`. 3. **`3 [ 1 2 3 ] make-list` — explicit length + quotation.** - Pros: Type-checks cleanly; works the same as Factor's `make` pattern. - Cons: Counts are easy to get wrong; redundant with what the compiler can already see in the quotation. 4. **Stack-tagged form: `1 2 3 3 >list`.** - Pros: No new syntax at all; just one new word. - Cons: The trailing count is even less ergonomic than the `swap prepend` ladder for anything past three or four elements. 5. **`#( 1 2 3 )` or another paren-prefixed form.** - Pros: Parens already feel listy. - Cons: `( ... )` is reserved for stack effect comments, so a prefix sigil is needed. ## Why I didn't just file a PR The shape of "what's a list literal in a stack language?" is more about taste than mechanics, and conflating list literals with quotations (option 2) versus introducing a new sigil (options 1 and 5) versus going purely word-level (options 3 and 4) is a direction call I'd want you to make. If you'd rather close this and discuss in another forum, that's fine — happy to follow wherever the conversation lives. ## Where I hit it Building the `38-cons-list` chapter for seqlings, where the test-data ladder dominated several otherwise-clean exercises.
Author
Owner
https://git.navicore.tech/navicore/patch-seq/pulls/465
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
navicore/patch-seq#461
No description provided.