Skip to content

Table: do not mark the result as fully evaluated; a literal element is fully evaluated - #2020

Merged
rocky merged 4 commits into
Mathics3:masterfrom
tombouctou:fix-table-fully-evaluated
Oct 17, 2026
Merged

rocky merged 4 commits into
Mathics3:masterfrom
tombouctou:fix-table-fully-evaluated

Conversation

@tombouctou

@tombouctou tombouctou commented Oct 16, 2026 •

Copy link
Copy Markdown
Collaborator

Table gave its result ElementsProperties(elements_fully_evaluated=True). A ListExpression with that flag never evaluates its elements again. So a table whose elements depend on a definition made later keeps its old value:

l = Table[x, {1}]; x = 1; l             (* Mathics3: {x};    WMA: {1} *)
l = Table[f[y], {1}]; f[y_] := 7; l     (* Mathics3: {f[y]}; WMA: {7} *)
t = Table[i + x, {i, 2}]; x = 1; t      (* Mathics3: {1 + x, 2 + x}; WMA: {2, 3} *)

Range with symbolic bounds and Array already behave like WMA. Only Table set the flag unconditionally.

With this PR, Table.get_result just builds a ListExpression from the elements and lets it work out its properties, as any other list does. A table of literals (numbers, strings) is still marked as fully evaluated, because that comes from the elements themselves.

Second commit: a literal element is fully evaluated. Building the list this way exposed a crash that is already on master. Map over an empty list gives {} with pessimistic properties (elements_fully_evaluated=False), although {} is literal. A list that holds such an element is itself literal, and _build_elements_properties then fails its assertion:

{f /@ {}}            (* master: AssertionError; WMA: {{}} *)
Table[f /@ {}, {2}]  (* with the first commit alone: AssertionError *)

_build_elements_properties and convert_expression_elements now treat a literal element as fully evaluated, whatever its own properties say.

Checks: test_table_is_evaluated_again in test/builtin/list/test_constructing.py (now including both cases above) fails on master and passes here. Full pytest and doctests pass.

🤖 Generated with Claude Code

tombouctou and others added 2 commits October 16, 2026 21:53
Table.get_result() gave its list ElementsProperties(elements_fully_evaluated=True).
ListExpression then never evaluated the elements again, even when they depend
on definitions made later:

    l = Table[x, {1}]; x = 1; l               (* gave {x}; WMA: {1} *)
    l = Table[f[y], {1}]; f[y_] := 7; l       (* gave {f[y]}; WMA: {7} *)

The list now works out its properties from its elements, as any other list does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Map over an empty list gives {} with pessimistic elements properties
(elements_fully_evaluated=False), although {} is literal. A list holding such
an element is itself literal, and _build_elements_properties() then failed on
`assert self.elements_properties.elements_fully_evaluated`:

    {f /@ {}}                 (* AssertionError; WMA: {{}} *)

The previous commit makes Table build its list this way too, so that
Table[f /@ {}, {2}] and Strickland's TodaChecks.m crashed as well.
_build_elements_properties() and convert_expression_elements() now take a
literal element as fully evaluated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tombouctou tombouctou changed the title Table: do not mark the result as fully evaluated, so it sees later definitions Table: do not mark the result as fully evaluated; a literal element is fully evaluated Oct 16, 2026
@mmatera

mmatera commented Oct 16, 2026

Copy link
Copy Markdown
Contributor

The property is_fully_evaluated should be set to True when Table produces a List of literal elements (like a list of numbers). This should be checked at creation time.

As suggested in review: when all the elements Table produces are literal,
like a list of numbers, the list is marked as fully evaluated when Table
builds it. Other tables still get their properties from ListExpression.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tombouctou

Copy link
Copy Markdown
Collaborator Author

@mmatera thanks, done in the latest commit. When every element Table produces is literal (Table[i, {i, 3}], Table[{i, 2 i}, {i, 3}]), get_result now builds the properties right away, so the list is marked fully evaluated at creation. For any other table (Table[i x, {i, 3}], or l = Table[x, {1}] before x = 1), the properties are left to ListExpression, so the list is evaluated again later. A new test calls Table.get_result directly and checks both cases.

@rocky

rocky commented Oct 17, 2026

Copy link
Copy Markdown
Member

LGTM thanks @tombouctou and @mmatera

@rocky
rocky merged commit 15fb42d into Mathics3:master Oct 17, 2026
15 checks passed
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.

3 participants