Skip to content

Commit 510030c

Browse files
evgasterc3d
authored andcommitted
lists: Add ListRecursionDepth setting to map, reduce, filter
The `ListRecursionDepth` controls the recusion depth for the `map`, `reduce` and `filter` operation. This defaults to `1`, meaning that we apply these functions only to the top level of the lists. The idea derives from work in PR #1649, but generalizing the approach in the PR, which only had a binary setting, disabled recursion for `filter` entirely, and did not consider the case of `reduce`. Fixes: #1648 Signed-off-by: Christophe de Dinechin <christophe@dinechin.org> Suggested-by: Ed@vanGasteren.net
1 parent ae1a813 commit 510030c

9 files changed

Lines changed: 303 additions & 49 deletions

File tree

doc/0-Overview.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,9 @@ operate on these items when it makes sense. Therefore:
636636
* As indicated [earlier](#representation-of-objects), quoted names in lists
637637
remain quoted, whereas on HP calculators, the quotes are removed.
638638

639+
* The `MAP` operation on the HP50G recurses on inner lists. On DB48x, it does
640+
not by default. This is controlled by the `ListDepthIteration` setting.
641+
A value of `0` restores HP50G-style infinite recursion.
639642

640643
### Vectors and matrices differences
641644

doc/commands/lists.md

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,34 @@ first level of the stack should take one argument and return a single value.
4646

4747
`{ A B ... }` `F``{ F(A) F(B) ... }`
4848

49-
The operation applies recursively to inner lists.
49+
50+
```rpl
51+
{ 1 2 A 42.2 [ 1 2 3 ]} « →STR » MAP
52+
@ Expecting { "1" "2" "A" "42.2" "[ 1 2 3 ]" }
53+
```
54+
55+
Unlike on HP calculators, `Map` does not apply recursively to inner lists by default.
5056

5157
```rpl
5258
{ 1 2 { 3 4 } } « →STR » MAP
59+
@ Expecting { "1" "2" "{ 3 4 }" }
60+
```
61+
62+
This can be changed by setting `ListRecursionDepth` to `0`.
63+
64+
```rpl
65+
0 ListRecursionDepth
66+
{ 1 2 { 3 4 } } « →STR » MAP
5367
@ Expecting { "1" "2" { "3" "4" } }
68+
```
5469

70+
`Map` can also be constrained to a given depth.
71+
72+
```rpl
73+
2 ListRecursionDepth
74+
{ 1 2 { 3 { 4 { 5 } } } } « →STR » MAP
75+
@ Expecting { "1" "2" { "3" "{ 4 { 5 } }" } }
76+
'ListRecursionDepth' Purge
5577
```
5678

5779
## Reduce
@@ -63,6 +85,22 @@ operation to all elements.
6385

6486
`{ A B ... }` `F``F(F(A, B), ...)`
6587

88+
For example, to sum all the elements in a list as text, one can use:
89+
90+
```rpl
91+
{ X Y Z T 12 { Hello World } } « →STR + » REDUCE
92+
@ Expecting "XYZT12{ Hello World }"
93+
```
94+
95+
Reduce obeys the `ListRecursionDepth` setting:
96+
97+
```rpl
98+
0 ListRecursionDepth
99+
{ X Y Z T 12 { Hello World } } « →STR + » REDUCE
100+
@ Expecting "XYZT12HelloWorld"
101+
'ListRecursionDepth' Purge
102+
```
103+
66104

67105
## Filter
68106

@@ -72,6 +110,22 @@ resulting list is built with all elements where the predicate is true.
72110

73111
`{ A B ... }` `P``{ A ... }` if `P(A)` is true and `P(B)` is false.
74112

113+
For example, to filter all odd numbers in an array, one can use:
114+
115+
```rpl
116+
[ 1 2 3 4 5 6 42 ] « 2 MOD 0 = » FILTER
117+
@ Expecting [ 2 4 6 42 ]
118+
```
119+
120+
`Filter` obeys the `ListRecursionDepth` setting:
121+
122+
```rpl
123+
0 ListRecursionDepth
124+
{ 1 2 3 4 { 5 6 { 42 } } } « 2 MOD 0 = » FILTER
125+
@ Expecting { 2 4 { 6 { 42 } } }
126+
'ListRecursionDepth' Purge
127+
```
128+
75129

76130
## Get
77131

doc/commands/settings.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,17 @@ from the HP implementations of RPL.
864864

865865
The opposite setting is `TruthLogicForIntegers`.
866866

867+
## ListRecursionDepth
868+
869+
This setting selects the depth of recursion for `Map`, `Reduce` or `Filter`.
870+
By default, it is set to `1`, indicating that recursion only applies to the
871+
top-level of the list. This matches the way `Map`, `Reduce` and `Filter` work in
872+
most programming languages.
873+
874+
A value larger than `1` can be used to recurse beyond the first level.
875+
On the HP50G, `Map` applies recursively to all levels. This can be achieved by
876+
setting `ListRecursionDepth` to `0`.
877+
867878

868879
# Evaluation settings
869880

help/db48x.md

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,9 @@ operate on these items when it makes sense. Therefore:
578578
* As indicated [earlier](#representation-of-objects), quoted names in lists
579579
remain quoted, whereas on HP calculators, the quotes are removed.
580580

581+
* The `MAP` operation on the HP50G recurses on inner lists. On DB48x, it does
582+
not by default. This is controlled by the `ListDepthIteration` setting.
583+
A value of `0` restores HP50G-style infinite recursion.
581584

582585
### Vectors and matrices differences
583586

@@ -12592,12 +12595,34 @@ first level of the stack should take one argument and return a single value.
1259212595

1259312596
`{ A B ... }` `F` ▶ `{ F(A) F(B) ... }`
1259412597

12595-
The operation applies recursively to inner lists.
12598+
12599+
```rpl
12600+
{ 1 2 A 42.2 [ 1 2 3 ]} « →STR » MAP
12601+
@ Expecting { "1" "2" "A" "42.2" "[ 1 2 3 ]" }
12602+
```
12603+
12604+
Unlike on HP calculators, `Map` does not apply recursively to inner lists by default.
1259612605

1259712606
```rpl
1259812607
{ 1 2 { 3 4 } } « →STR » MAP
12608+
@ Expecting { "1" "2" "{ 3 4 }" }
12609+
```
12610+
12611+
This can be changed by setting `ListRecursionDepth` to `0`.
12612+
12613+
```rpl
12614+
0 ListRecursionDepth
12615+
{ 1 2 { 3 4 } } « →STR » MAP
1259912616
@ Expecting { "1" "2" { "3" "4" } }
12617+
```
12618+
12619+
`Map` can also be constrained to a given depth.
1260012620

12621+
```rpl
12622+
2 ListRecursionDepth
12623+
{ 1 2 { 3 { 4 { 5 } } } } « →STR » MAP
12624+
@ Expecting { "1" "2" { "3" "{ 4 { 5 } }" } }
12625+
'ListRecursionDepth' Purge
1260112626
```
1260212627

1260312628
## Reduce
@@ -12609,6 +12634,22 @@ operation to all elements.
1260912634

1261012635
`{ A B ... }` `F` ▶ `F(F(A, B), ...)`
1261112636

12637+
For example, to sum all the elements in a list as text, one can use:
12638+
12639+
```rpl
12640+
{ X Y Z T 12 { Hello World } } « →STR + » REDUCE
12641+
@ Expecting "XYZT12{ Hello World }"
12642+
```
12643+
12644+
Reduce obeys the `ListRecursionDepth` setting:
12645+
12646+
```rpl
12647+
0 ListRecursionDepth
12648+
{ X Y Z T 12 { Hello World } } « →STR + » REDUCE
12649+
@ Expecting "XYZT12HelloWorld"
12650+
'ListRecursionDepth' Purge
12651+
```
12652+
1261212653

1261312654
## Filter
1261412655

@@ -12618,6 +12659,22 @@ resulting list is built with all elements where the predicate is true.
1261812659

1261912660
`{ A B ... }` `P` ▶ `{ A ... }` if `P(A)` is true and `P(B)` is false.
1262012661

12662+
For example, to filter all odd numbers in an array, one can use:
12663+
12664+
```rpl
12665+
[ 1 2 3 4 5 6 42 ] « 2 MOD 0 = » FILTER
12666+
@ Expecting [ 2 4 6 42 ]
12667+
```
12668+
12669+
`Filter` obeys the `ListRecursionDepth` setting:
12670+
12671+
```rpl
12672+
0 ListRecursionDepth
12673+
{ 1 2 3 4 { 5 6 { 42 } } } « 2 MOD 0 = » FILTER
12674+
@ Expecting { 2 4 { 6 { 42 } } }
12675+
'ListRecursionDepth' Purge
12676+
```
12677+
1262112678

1262212679
## Get
1262312680

@@ -15120,6 +15177,17 @@ from the HP implementations of RPL.
1512015177

1512115178
The opposite setting is `TruthLogicForIntegers`.
1512215179

15180+
## ListRecursionDepth
15181+
15182+
This setting selects the depth of recursion for `Map`, `Reduce` or `Filter`.
15183+
By default, it is set to `1`, indicating that recursion only applies to the
15184+
top-level of the list. This matches the way `Map`, `Reduce` and `Filter` work in
15185+
most programming languages.
15186+
15187+
A value larger than `1` can be used to recurse beyond the first level.
15188+
On the HP50G, `Map` applies recursively to all levels. This can be achieved by
15189+
setting `ListRecursionDepth` to `0`.
15190+
1512315191

1512415192
# Evaluation settings
1512515193

help/db50x.md

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,9 @@ operate on these items when it makes sense. Therefore:
587587
* As indicated [earlier](#representation-of-objects), quoted names in lists
588588
remain quoted, whereas on HP calculators, the quotes are removed.
589589

590+
* The `MAP` operation on the HP50G recurses on inner lists. On DB48x, it does
591+
not by default. This is controlled by the `ListDepthIteration` setting.
592+
A value of `0` restores HP50G-style infinite recursion.
590593

591594
### Vectors and matrices differences
592595

@@ -12600,12 +12603,34 @@ first level of the stack should take one argument and return a single value.
1260012603

1260112604
`{ A B ... }` `F` ▶ `{ F(A) F(B) ... }`
1260212605

12603-
The operation applies recursively to inner lists.
12606+
12607+
```rpl
12608+
{ 1 2 A 42.2 [ 1 2 3 ]} « →STR » MAP
12609+
@ Expecting { "1" "2" "A" "42.2" "[ 1 2 3 ]" }
12610+
```
12611+
12612+
Unlike on HP calculators, `Map` does not apply recursively to inner lists by default.
1260412613

1260512614
```rpl
1260612615
{ 1 2 { 3 4 } } « →STR » MAP
12616+
@ Expecting { "1" "2" "{ 3 4 }" }
12617+
```
12618+
12619+
This can be changed by setting `ListRecursionDepth` to `0`.
12620+
12621+
```rpl
12622+
0 ListRecursionDepth
12623+
{ 1 2 { 3 4 } } « →STR » MAP
1260712624
@ Expecting { "1" "2" { "3" "4" } }
12625+
```
12626+
12627+
`Map` can also be constrained to a given depth.
1260812628

12629+
```rpl
12630+
2 ListRecursionDepth
12631+
{ 1 2 { 3 { 4 { 5 } } } } « →STR » MAP
12632+
@ Expecting { "1" "2" { "3" "{ 4 { 5 } }" } }
12633+
'ListRecursionDepth' Purge
1260912634
```
1261012635

1261112636
## Reduce
@@ -12617,6 +12642,22 @@ operation to all elements.
1261712642

1261812643
`{ A B ... }` `F` ▶ `F(F(A, B), ...)`
1261912644

12645+
For example, to sum all the elements in a list as text, one can use:
12646+
12647+
```rpl
12648+
{ X Y Z T 12 { Hello World } } « →STR + » REDUCE
12649+
@ Expecting "XYZT12{ Hello World }"
12650+
```
12651+
12652+
Reduce obeys the `ListRecursionDepth` setting:
12653+
12654+
```rpl
12655+
0 ListRecursionDepth
12656+
{ X Y Z T 12 { Hello World } } « →STR + » REDUCE
12657+
@ Expecting "XYZT12HelloWorld"
12658+
'ListRecursionDepth' Purge
12659+
```
12660+
1262012661

1262112662
## Filter
1262212663

@@ -12626,6 +12667,22 @@ resulting list is built with all elements where the predicate is true.
1262612667

1262712668
`{ A B ... }` `P` ▶ `{ A ... }` if `P(A)` is true and `P(B)` is false.
1262812669

12670+
For example, to filter all odd numbers in an array, one can use:
12671+
12672+
```rpl
12673+
[ 1 2 3 4 5 6 42 ] « 2 MOD 0 = » FILTER
12674+
@ Expecting [ 2 4 6 42 ]
12675+
```
12676+
12677+
`Filter` obeys the `ListRecursionDepth` setting:
12678+
12679+
```rpl
12680+
0 ListRecursionDepth
12681+
{ 1 2 3 4 { 5 6 { 42 } } } « 2 MOD 0 = » FILTER
12682+
@ Expecting { 2 4 { 6 { 42 } } }
12683+
'ListRecursionDepth' Purge
12684+
```
12685+
1262912686

1263012687
## Get
1263112688

@@ -15128,6 +15185,17 @@ from the HP implementations of RPL.
1512815185

1512915186
The opposite setting is `TruthLogicForIntegers`.
1513015187

15188+
## ListRecursionDepth
15189+
15190+
This setting selects the depth of recursion for `Map`, `Reduce` or `Filter`.
15191+
By default, it is set to `1`, indicating that recursion only applies to the
15192+
top-level of the list. This matches the way `Map`, `Reduce` and `Filter` work in
15193+
most programming languages.
15194+
15195+
A value larger than `1` can be used to recurse beyond the first level.
15196+
On the HP50G, `Map` applies recursively to all levels. This can be achieved by
15197+
setting `ListRecursionDepth` to `0`.
15198+
1513115199

1513215200
# Evaluation settings
1513315201

src/array.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,24 +43,24 @@ struct array : list
4343
{
4444
array(id type, gcbytes bytes, size_t len): list(type, bytes, len) {}
4545

46-
static array_g map(algebraic_fn fn, array_r x)
46+
static array_g map(algebraic_fn fn, array_r x, size_t recurse = ~0U)
4747
{
48-
return x->map(fn);
48+
return x->map(fn, recurse);
4949
}
5050

51-
array_p map(algebraic_fn fn) const
51+
array_p map(algebraic_fn fn, size_t recurse = ~0U) const
5252
{
53-
return array_p(list::map(fn));
53+
return array_p(list::map(fn, recurse));
5454
}
5555

56-
array_p map(arithmetic_fn fn, algebraic_r y) const
56+
array_p map(arithmetic_fn fn, algebraic_r y, size_t recurse = ~0U) const
5757
{
58-
return array_p(list::map(fn, y));
58+
return array_p(list::map(fn, y, recurse));
5959
}
6060

61-
array_p map(algebraic_r x, arithmetic_fn fn) const
61+
array_p map(algebraic_r x, arithmetic_fn fn, size_t recurse = ~0U) const
6262
{
63-
return array_p(list::map(x, fn));
63+
return array_p(list::map(x, fn, recurse));
6464
}
6565

6666
// Append data

src/ids.tbl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,6 +1058,8 @@ FLAG(TVMPayAtBeginningOfPeriod, TVMPayAtEndOfPeriod)
10581058
FLAG(TruthLogicForIntegers, BitwiseLogicForIntegers)
10591059
FLAG(LaxArrayResizing, StrictArrayResizing)
10601060

1061+
SETTING_BITS(ListRecursionDepth, uint, 16, 0U, 65535U, 1U)
1062+
10611063
ALIAS(HardwareFloatingPoint, "HFP")
10621064
ALIAS(HardwareFloatingPoint, "HardFP")
10631065
ALIAS(SoftwareFloatingPoint, "SFP")

0 commit comments

Comments
 (0)