Skip to content

Fix MapAt for parts that are lists, other heads and several positions - #2008

Open
tombouctou wants to merge 1 commit into
Mathics3:masterfrom
tombouctou:fix-mapat-positions
Open

tombouctou wants to merge 1 commit into
Mathics3:masterfrom
tombouctou:fix-mapat-positions

Conversation

@tombouctou

Copy link
Copy Markdown

MapAt gave wrong results whenever the part at the position was itself a list, which is common with matrices:

MapAt[f, {{1, 0}, {0, 1}}, {2}]            (* gave {0, f[1]};  WMA: {{1, 0}, f[{0, 1}]} *)
MapAt[0 # &, {{1, 0}, {0, 1}}, {{2}}]      (* gave {0, 0};     WMA: {{1, 0}, {0, 0}} *)
MapAt[f, {{1, 0}, {0, 1}}, {{1}, {2}}]     (* gave {f[1], f[0]}; WMA: {f[{1, 0}], f[{0, 1}]} *)

With a one-index position, the code applied f inside the part at that position and returned that part's elements as the whole result. Also:

MapAt[g, h[a, b], 2]                       (* gave {a, g[b]};  WMA: h[a, g[b]] *)
MapAt[g, {a, k[b, c]}, {2, 1}]             (* gave MapAt::partw; WMA: {a, k[g[b], c]} *)
MapAt[g, {{a, b}, {c, d}}, {{1, 2}, {2}}]  (* gave {c, g[d]};  WMA: {{a, g[b]}, g[{c, d}]} *)

This replaces the position handling in eval_MapAt with one recursive function that walks the position and rebuilds each level with its own head. Error messages (MapAt::partw, MapAt::psl), negative positions, associations, and the existing handling of rules are unchanged. The doc examples still pass.

Tests: new cases in test/builtin/functional/test_apply_fns_to_lists.py. pytest and the doctests pass.

Found while running Strickland's LambdaAlgebra.m, which builds a projection matrix with MapAt[0 # &, IdentityMatrix[n], {{i}, ...}].

🤖 Generated with Claude Code

MapAt[f, {{1, 0}, {0, 1}}, {2}] gave {0, f[1]} instead of
{{1, 0}, f[{0, 1}]}: when the part at the position was itself a List,
it applied f inside that part and returned the part's elements as the
result. Also:
- the head of the expression was lost: MapAt[g, h[a, b], 2] gave
  {a, g[b]} instead of h[a, g[b]];
- positions could not go into a part whose head is not List;
- a list of positions of different depths gave a wrong result.

Walk the position recursively, rebuilding each level with its own head.

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

This branch has not been deployed

No deployments
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.

1 participant