From 1fac3e30edb6be9dde3c1f594c9522018eebe872 Mon Sep 17 00:00:00 2001 From: Ed van Gasteren Date: Wed, 4 Mar 2026 22:07:34 +0100 Subject: [PATCH 1/4] src: Commands Map and Filter should not recurse With nested lists the commands Map and Filter operated not only on the top level list but recursively on the nested list(s) ... with the same provided rpl program. Removed the recursive processing of the elements of a list. Fixes: #1648 Signed-off-by: Ed@vanGasteren.net --- src/list.cc | 60 ++++++++++++++++++----------------------------------- 1 file changed, 20 insertions(+), 40 deletions(-) diff --git a/src/list.cc b/src/list.cc index 58d85497..4b58bcd2 100644 --- a/src/list.cc +++ b/src/list.cc @@ -786,7 +786,7 @@ bool list::expand() const bool list::expand_deep(uint32_t which) const // ---------------------------------------------------------------------------- -// Expand list content, expending inner expressions/programs/lists +// Expand list content, expanding inner expressions/programs/lists // ---------------------------------------------------------------------------- { for (object_p obj : *this) @@ -1536,25 +1536,16 @@ list_p list::map(object_p prgobj) const scribble scr; for (object_p obj : *this) { - id oty = obj->type(); - if (is_array_or_list(oty)) - { - list_g sub = list_p(obj)->map(prg); - obj = +sub; - } - else + if (!rt.push(obj)) + goto error; + if (program::run(prg, true) != OK) + goto error; + if (rt.depth() != depth + 1) { - if (!rt.push(obj)) - goto error; - if (program::run(prg, true) != OK) - goto error; - if (rt.depth() != depth + 1) - { - rt.misbehaving_program_error(); - goto error; - } - obj = rt.pop(); + rt.misbehaving_program_error(); + goto error; } + obj = rt.pop(); if (!obj) goto error; @@ -1621,31 +1612,20 @@ list_p list::filter(object_p prgobj) const scribble scr; for (object_g obj : *this) { - id oty = obj->type(); bool keep = false; - if (is_array_or_list(oty)) - { - object_g sub = list_p(+obj)->filter(prg); - obj = +sub; - keep = true; - } - else + if (!rt.push(obj)) + goto error; + if (program::run(prg, true) != OK) + goto error; + if (rt.depth() != depth + 1) { - if (!rt.push(obj)) - goto error; - if (program::run(prg, true) != OK) - goto error; - if (rt.depth() != depth + 1) - { - rt.misbehaving_program_error(); - goto error; - } - object_p test = rt.pop(); - keep = test->as_truth(true); - if (rt.error()) - goto error; + rt.misbehaving_program_error(); + goto error; } - + object_p test = rt.pop(); + keep = test->as_truth(true); + if (rt.error()) + goto error; if (keep && !rt.append(obj)) goto error; } From c278968594cd60b1d93e3c33a6b8b7646ad6e6a7 Mon Sep 17 00:00:00 2001 From: Ed van Gasteren Date: Tue, 10 Mar 2026 17:02:23 +0100 Subject: [PATCH 2/4] lists: map recursive or one level depending on a flag The HP 50g maps recursively. Most other programming languages map only on level. Introduce the flag MapRecursive / MapOneLevel. Both behaviours are now possible. Describes as such in the documentation. Fixes: #1648 Signed-off-by: Ed@vanGasteren.net --- doc/commands/lists.md | 17 +++++++---------- src/ids.tbl | 1 + src/list.cc | 31 ++++++++++++++++++++----------- 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/doc/commands/lists.md b/doc/commands/lists.md index 741c4123..a0d5bf7e 100755 --- a/doc/commands/lists.md +++ b/doc/commands/lists.md @@ -26,16 +26,6 @@ at the deepest level in the stack. This is the opposite of [→List](#tolist). T `{ A B ... }` ▶ `A` `B` ... `Count` -## List→ - -Expand a list on the stack and return the number of elements. After executing -the command, level 1 contains the number of elements, and a corresponding number -of stack levels contain individual elements of the list, the first element being -at the deepest level in the stack. This is the opposite of [→List](#tolist). The -[Obj→](#fromobj) command performs the same operation when applied to a list. - -`{ A B ... }` ▶ `A` `B` ... `Count` - ## Head Return the first element of a list, or an `Invalid dimension` error if the list @@ -55,8 +45,15 @@ the list is empty. Apply an operation on all elements in a list or array. The operation on the first level of the stack should take one argument and return a single value. +If the list or array contains (nested) lists or arrays then these are recursively processed, +depending on the setting of the MapOneLevel / MapRecursive flag. +On the HP 50g the command works recursively (See the "HP 50g advanced user's reference manual"). +With DB48x rpl the default is MapOneLevel, as with most programming languages. + `{ A B ... }` `F` ▶ `{ F(A) F(B) ... }` + + ## Reduce Apply a cumulative pairwise operation on all elements in a list or array. diff --git a/src/ids.tbl b/src/ids.tbl index 19928b14..2a6c6ed5 100644 --- a/src/ids.tbl +++ b/src/ids.tbl @@ -1049,6 +1049,7 @@ FLAG(NumericalIntegration, SymbolicIntegration) FLAG(TVMPayAtBeginningOfPeriod, TVMPayAtEndOfPeriod) FLAG(TruthLogicForIntegers, BitwiseLogicForIntegers) FLAG(LaxArrayResizing, StrictArrayResizing) +FLAG(MapOneLevel, MapRecursive) ALIAS(HardwareFloatingPoint, "HFP") ALIAS(HardwareFloatingPoint, "HardFP") diff --git a/src/list.cc b/src/list.cc index 4b58bcd2..ae006241 100644 --- a/src/list.cc +++ b/src/list.cc @@ -1536,16 +1536,25 @@ list_p list::map(object_p prgobj) const scribble scr; for (object_p obj : *this) { - if (!rt.push(obj)) - goto error; - if (program::run(prg, true) != OK) - goto error; - if (rt.depth() != depth + 1) + id oty = obj->type(); + if (is_array_or_list(oty) && Settings.MapRecursive()) { - rt.misbehaving_program_error(); - goto error; + list_g sub = list_p(obj)->map(prg); + obj = +sub; + } + else + { + if (!rt.push(obj)) + goto error; + if (program::run(prg, true) != OK) + goto error; + if (rt.depth() != depth + 1) + { + rt.misbehaving_program_error(); + goto error; + } + obj = rt.pop(); } - obj = rt.pop(); if (!obj) goto error; @@ -1688,7 +1697,7 @@ list_p list::map(algebraic_fn fn) const for (object_p obj : *this) { id oty = obj->type(); - if (is_array_or_list(oty)) + if (is_array_or_list(oty) && Settings.MapRecursive()) { list_g sub = list_p(obj)->map(fn); obj = +sub; @@ -1726,7 +1735,7 @@ list_p list::map(arithmetic_fn fn, algebraic_r y) const for (object_p obj : *this) { id oty = obj->type(); - if (is_array_or_list(oty)) + if (is_array_or_list(oty) && Settings.MapRecursive()) { list_g sub = list_p(obj)->map(fn, y); obj = +sub; @@ -1764,7 +1773,7 @@ list_p list::map(algebraic_r x, arithmetic_fn fn) const for (object_p obj : *this) { id oty = obj->type(); - if (is_array_or_list(oty)) + if (is_array_or_list(oty) && Settings.MapRecursive()) { list_g sub = list_p(obj)->map(x, fn); obj = +sub; From b5598fbadb30b060b3b953eaa6ccdf1eeb93ec25 Mon Sep 17 00:00:00 2001 From: Ed van Gasteren Date: Fri, 13 Mar 2026 13:43:10 +0100 Subject: [PATCH 3/4] doc: Corrected description of MapRecursive / MapOneLevel In a Previous commit I got the default flag behaviour wrong. Fixes #1648 Signed-off-by: Ed@vanGasteren.net --- doc/commands/lists.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/commands/lists.md b/doc/commands/lists.md index a0d5bf7e..2444b2e9 100755 --- a/doc/commands/lists.md +++ b/doc/commands/lists.md @@ -48,7 +48,8 @@ first level of the stack should take one argument and return a single value. If the list or array contains (nested) lists or arrays then these are recursively processed, depending on the setting of the MapOneLevel / MapRecursive flag. On the HP 50g the command works recursively (See the "HP 50g advanced user's reference manual"). -With DB48x rpl the default is MapOneLevel, as with most programming languages. +With DB48x rpl the default is MapRecursive also. +I can be set to MapOneLevel to get the behaviour of with most programming languages. `{ A B ... }` `F` ▶ `{ F(A) F(B) ... }` From d7f3777cd2fd91a9be521d07f51274184d1c67e8 Mon Sep 17 00:00:00 2001 From: Ed van Gasteren Date: Fri, 13 Mar 2026 14:02:50 +0100 Subject: [PATCH 4/4] doc: Corrected typoes Fixes c3d#1648 Signed-off-by: Ed@vanGasteren.net --- doc/commands/lists.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/commands/lists.md b/doc/commands/lists.md index 2444b2e9..83fba2ad 100755 --- a/doc/commands/lists.md +++ b/doc/commands/lists.md @@ -49,7 +49,7 @@ If the list or array contains (nested) lists or arrays then these are recursivel depending on the setting of the MapOneLevel / MapRecursive flag. On the HP 50g the command works recursively (See the "HP 50g advanced user's reference manual"). With DB48x rpl the default is MapRecursive also. -I can be set to MapOneLevel to get the behaviour of with most programming languages. +It can be set to MapOneLevel to get the behaviour of most programming languages. `{ A B ... }` `F` ▶ `{ F(A) F(B) ... }`