From 312b823641522a889434526c06025ccd8a603bc0 Mon Sep 17 00:00:00 2001 From: Bharat Kaurav <117659673+TheNetherWatcher@users.noreply.github.com> Date: Fri, 16 Oct 2026 20:53:13 +0530 Subject: [PATCH 1/4] Riffle: insert a non-list separator only between elements 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`. --- CHANGES.md | 4 ++++ mathics/builtin/list/rearrange.py | 8 +++++++- test/builtin/list/test_list.py | 11 +++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index cb98d170e9..36cca84bbf 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,10 @@ Improve Monomial ordering. +### Bugs Fixed + +1. [\#2003](https://github.com/Mathics3/mathics-core/issues/2003) `Riffle[{a}, x]` gives `{a}`: a non-list separator is inserted only between elements + ## 10.0.1 April 18, 2026 diff --git a/mathics/builtin/list/rearrange.py b/mathics/builtin/list/rearrange.py index 57522302a2..106be4b6f5 100644 --- a/mathics/builtin/list/rearrange.py +++ b/mathics/builtin/list/rearrange.py @@ -1176,7 +1176,13 @@ def eval(self, list, sep, evaluation: Evaluation): if sep.has_form(SymbolList, None): result = riffle_lists(list.elements, sep.elements) else: - result = riffle_lists(list.elements, [sep]) + # A non-list separator goes only between elements, never + # after the last one: Riffle[{a}, x] is {a}. + result = [] + for i, element in enumerate(list.elements): + if i > 0: + result.append(sep) + result.append(element) return list.restructure("List", result, evaluation, deps=(list, sep)) diff --git a/test/builtin/list/test_list.py b/test/builtin/list/test_list.py index 1dc3e2ce74..d13097a2dd 100644 --- a/test/builtin/list/test_list.py +++ b/test/builtin/list/test_list.py @@ -129,6 +129,17 @@ "{{{1, 1, 1}, {1, 1, 2}, {1, 2, 1}, {1, 2, 2}}, {{2, 1, 1}, {2, 1, 2}, {2, 2, 1}, {2, 2, 2}}}", None, ), + # Riffle + ( + "Riffle[{a}, x]", + None, + "{a}", + "non-list separator goes only between elements", + ), + ("Riffle[{a, b}, x]", None, "{a, x, b}", None), + ("Riffle[{}, x]", None, "{}", None), + ("Riffle[{a}, {x}]", None, "{a, x}", "equal lengths: separator list appended"), + ("Riffle[{a, b}, {x, y}]", None, "{a, x, b, y}", None), # Union and Intersection ( "Union[{1, -1, 2}, {-2, 3}, SameTest -> (Abs[#1] == Abs[#2] &)]", From cffeaa1eaadc942d75b4943f2b9e6ee98be5bb1e Mon Sep 17 00:00:00 2001 From: "R. Bernstein" Date: Fri, 16 Oct 2026 11:28:06 -0400 Subject: [PATCH 2/4] Apply suggestion from @rocky Add one more assert failure message --- test/builtin/list/test_list.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/builtin/list/test_list.py b/test/builtin/list/test_list.py index d13097a2dd..a2c188e989 100644 --- a/test/builtin/list/test_list.py +++ b/test/builtin/list/test_list.py @@ -137,7 +137,7 @@ "non-list separator goes only between elements", ), ("Riffle[{a, b}, x]", None, "{a, x, b}", None), - ("Riffle[{}, x]", None, "{}", None), + ("Riffle[{}, x]", None, "{}", "Degenerate Riffle on empty list"), ("Riffle[{a}, {x}]", None, "{a, x}", "equal lengths: separator list appended"), ("Riffle[{a, b}, {x, y}]", None, "{a, x, b, y}", None), # Union and Intersection From 54a1901a15b01f0929d9d877a18f939afffc8c9b Mon Sep 17 00:00:00 2001 From: Bharat Kaurav <117659673+TheNetherWatcher@users.noreply.github.com> Date: Fri, 16 Oct 2026 21:08:11 +0530 Subject: [PATCH 3/4] Update test/builtin/list/test_list.py Co-authored-by: R. Bernstein --- test/builtin/list/test_list.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/builtin/list/test_list.py b/test/builtin/list/test_list.py index a2c188e989..e534a6e710 100644 --- a/test/builtin/list/test_list.py +++ b/test/builtin/list/test_list.py @@ -136,7 +136,7 @@ "{a}", "non-list separator goes only between elements", ), - ("Riffle[{a, b}, x]", None, "{a, x, b}", None), + ("Riffle[{a, b}, x]", None, "{a, x, b}", "Issue #2017"), ("Riffle[{}, x]", None, "{}", "Degenerate Riffle on empty list"), ("Riffle[{a}, {x}]", None, "{a, x}", "equal lengths: separator list appended"), ("Riffle[{a, b}, {x, y}]", None, "{a, x, b, y}", None), From f3a2ca631c155a393e2442ca3e6a36b45d7af17c Mon Sep 17 00:00:00 2001 From: Bharat Kaurav <117659673+TheNetherWatcher@users.noreply.github.com> Date: Sat, 17 Oct 2026 11:50:12 +0530 Subject: [PATCH 4/4] Riffle: update CSV export doctest and fix issue number in test --- mathics/builtin/import_export/importexport.py | 14 +++++++------- test/builtin/list/test_list.py | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/mathics/builtin/import_export/importexport.py b/mathics/builtin/import_export/importexport.py index 3425fdb440..cb7e6f8825 100644 --- a/mathics/builtin/import_export/importexport.py +++ b/mathics/builtin/import_export/importexport.py @@ -778,15 +778,15 @@ class ExportString(Builtin): >> ExportString[{{1,2,3,4},{3},{2},{4}}, "CSV"] = 1,2,3,4 - . 3, - . 2, - . 4, + . 3 + . 2 + . 4 >> ExportString[{1,2,3,4}, "CSV"] - = 1, - . 2, - . 3, - . 4, + = 1 + . 2 + . 3 + . 4 >> ExportString[Integrate[f[x],{x,0,2}], "SVG"]//Head = String """ diff --git a/test/builtin/list/test_list.py b/test/builtin/list/test_list.py index e534a6e710..745f7eeb89 100644 --- a/test/builtin/list/test_list.py +++ b/test/builtin/list/test_list.py @@ -136,7 +136,7 @@ "{a}", "non-list separator goes only between elements", ), - ("Riffle[{a, b}, x]", None, "{a, x, b}", "Issue #2017"), + ("Riffle[{a, b}, x]", None, "{a, x, b}", "Issue #2003"), ("Riffle[{}, x]", None, "{}", "Degenerate Riffle on empty list"), ("Riffle[{a}, {x}]", None, "{a, x}", "equal lengths: separator list appended"), ("Riffle[{a, b}, {x, y}]", None, "{a, x, b, y}", None),