Skip to content

Riffle: insert a non-list separator only between elements - #2017

Merged
rocky merged 8 commits into
Mathics3:masterfrom
TheNetherWatcher:fix/riffle-single-element
Oct 17, 2026
Merged

rocky merged 8 commits into
Mathics3:masterfrom
TheNetherWatcher:fix/riffle-single-element

Conversation

@TheNetherWatcher

Copy link
Copy Markdown
Contributor

Fixes #2003.

Riffle[{a}, x] returned {a, x}; WMA returns {a}.

Riffle.eval wrapped a non-list separator as [sep] and passed it to riffle_lists, which appends a trailing separator when the item and separator lists have the same length. For a one-element list that rule fired, so x was appended.

A non-list separator is now placed only between elements. List separators still go through riffle_lists unchanged, so Riffle[{a}, {x}] is {a, x} and Riffle[{a, b}, {x, y}] is {a, x, b, y}, as in WMA.

Tests: added Riffle cases to test/builtin/list/test_list.py ({a}, {a, b}, {} with x; {a} with {x}; {a, b} with {x, y}). The list tests and the existing Riffle doctests pass. Added a CHANGES.md entry.

Fixes #2003.

`Riffle[{a}, x]` gave `{a, x}`; WMA gives `{a}`. `Riffle.eval` wrapped
a non-list separator as `[sep]` and passed it to `riffle_lists`, which
appends a trailing separator when the item and separator lists have the
same length. With one element that rule fired and `x` was appended.

A non-list separator is now placed only between elements. The
list-separator forms still go through `riffle_lists`, so
`Riffle[{a}, {x}]` is `{a, x}` and `Riffle[{a, b}, {x, y}]` is
`{a, x, b, y}`, as in WMA.

Tests: new `Riffle` cases in `test/builtin/list/test_list.py`.
Comment thread test/builtin/list/test_list.py Outdated
Add one more assert failure message
Comment thread test/builtin/list/test_list.py Outdated

@tombouctou tombouctou left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Riffle change looks right to me. I checked these against WMA 15, and the branch gives the same result for all of them: Riffle[{a}, x], Riffle[{a, b}, x], Riffle[{}, x], Riffle[{a}, {x}], Riffle[{a, b}, {x, y}], Riffle[{{1}, {2}}, x], Riffle[{a, b, c}, {x}], Riffle[{a}, {x, y}], Riffle[{a, b}, {}].

But it breaks one doctest, and that is why the build jobs are red: ExportString in mathics/builtin/import_export/importexport.py. The CSV exporter (SystemFiles/Formats/CSV/Export.wl) builds each row with Riffle[#, sep]. A one-field row like {3} used to come out as 3,, and the doctest recorded that trailing comma. With this fix, the output is the same as WMA's, so only the expected output needs updating:

    >> ExportString[{{1,2,3,4},{3},{2},{4}}, "CSV"]
     = 1,2,3,4
     . 3
     . 2
     . 4

    >> ExportString[{1,2,3,4}, "CSV"]
     = 1
     . 2
     . 3
     . 4

(WMA also ends the string with a newline, but that is a separate, existing difference.)

A small nit: in test_list.py, the failure message "Issue #2017" should be #2003. 2017 is this PR.

With the doctest updated, LGTM.

@rocky

rocky commented Oct 17, 2026

Copy link
Copy Markdown
Member

Thanks @TheNetherWatcher and @tombouctou.

LGTM

@rocky
rocky merged commit 6b24366 into Mathics3:master Oct 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Riffle[{a}, x] gives {a, x}; WMA gives {a}

4 participants