Skip to content

Commit 5397e70

Browse files
authored
Add FoldLeft, FoldLeftX; and ForAllX, ForAnyX, FilteredX, NumberX, PerformX to complement ListX, SetX, SumX, ProductX (#3357)
1 parent 0644142 commit 5397e70

File tree

7 files changed

+755
-450
lines changed

7 files changed

+755
-450
lines changed

doc/ref/lists.xml

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1688,12 +1688,26 @@ with possibly slightly different meaning for lists and non-list collections.
16881688

16891689
The following functions are generalizations of
16901690
<Ref Func="List" Label="for a collection"/>,
1691-
<Ref Oper="Set"/>, <Ref Func="Sum"/>, and <Ref Func="Product"/>.
1692-
1691+
<Ref Oper="Set"/>,
1692+
<Ref Func="Sum"/>,
1693+
<Ref Func="Product"/>,
1694+
<Ref Func="ForAll"/>,
1695+
<Ref Func="ForAny"/>,
1696+
<Ref Func="Filtered"/>,
1697+
<Ref Func="Number"/>,
1698+
and <Ref Func="Perform"/>.
1699+
1700+
<#Include Label="FoldLeft">
1701+
<#Include Label="FoldLeftX">
16931702
<#Include Label="ListX">
16941703
<#Include Label="SetX">
16951704
<#Include Label="SumX">
16961705
<#Include Label="ProductX">
1706+
<#Include Label="ForAllX">
1707+
<#Include Label="ForAnyX">
1708+
<#Include Label="FilteredX">
1709+
<#Include Label="NumberX">
1710+
<#Include Label="PerformX">
16971711

16981712
</Section>
16991713

@@ -1890,4 +1904,3 @@ such as before objectifying, or calling some kernel functions.
18901904
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
18911905
<!-- %% -->
18921906
<!-- %E -->
1893-

lib/coll.gd

Lines changed: 282 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2478,6 +2478,126 @@ DeclareOperation( "AsSSortedListNonstored", [IsListOrCollection] );
24782478
DeclareGlobalFunction( "Elements" );
24792479

24802480

2481+
#############################################################################
2482+
##
2483+
#O FoldLeft( <C>, <func>[, <init>] )
2484+
##
2485+
## <#GAPDoc Label="FoldLeft">
2486+
## <ManSection>
2487+
## <Oper Name="FoldLeft" Arg='C, func[, init]'/>
2488+
##
2489+
## <Description>
2490+
## <Ref Oper="FoldLeft"/> applies the binary function <A>func</A>
2491+
## left-associatively to the elements of the list or collection <A>C</A>.
2492+
## <P/>
2493+
## If no initial accumulator <A>init</A> is given, the first element of
2494+
## <A>C</A> is used as the initial accumulator and the remaining elements
2495+
## are combined with it from left to right. In that case <A>C</A> must not
2496+
## be empty.
2497+
## <P/>
2498+
## If <A>init</A> is given, the accumulator is initialized with
2499+
## <A>init</A>. Then an empty list or collection is allowed, and
2500+
## <A>init</A> is returned unchanged in that case.
2501+
## <P/>
2502+
## If <A>C</A> is a list with holes, these holes are ignored, just as when
2503+
## iterating over the list with a <C>for</C>-loop.
2504+
## <P/>
2505+
## This operation can be used to express reductions similar to
2506+
## <Ref Func="Sum"/> or <Ref Func="Product"/>, but it is more general
2507+
## because the accumulator is updated by an arbitrary binary function.
2508+
## <P/>
2509+
## <Example><![CDATA[
2510+
## gap> FoldLeft( [ 1 .. 10 ], \+ );
2511+
## 55
2512+
## gap> FoldLeft( [ 1 .. 4 ], \*, 2 );
2513+
## 48
2514+
## gap> FoldLeft( [ 1,, 3 ], { a, b } -> a + b );
2515+
## 4
2516+
## ]]></Example>
2517+
## </Description>
2518+
## </ManSection>
2519+
## <#/GAPDoc>
2520+
##
2521+
DeclareOperation( "FoldLeft", [ IsListOrCollection, IsFunction ] );
2522+
DeclareOperation( "FoldLeft", [ IsListOrCollection, IsFunction, IsObject ] );
2523+
2524+
2525+
#############################################################################
2526+
##
2527+
#O FoldLeftX( <gens>, <func>, <init>[, <abortValue>] )
2528+
##
2529+
## <#GAPDoc Label="FoldLeftX">
2530+
## <ManSection>
2531+
## <Func Name="FoldLeftX" Arg='gens, func, init[, abortValue]'/>
2532+
##
2533+
## <Description>
2534+
## <Ref Func="FoldLeftX"/> is a generalization of <Ref Oper="FoldLeft"/>
2535+
## which applies an accumulation function <A>func</A> to a bunch of
2536+
## inputs which are derived from <A>gens</A>.
2537+
## <P/>
2538+
## The argument <A>gens</A> must be a plain list whose entries describe a
2539+
## sequence of nested loops and filters. Specifically, let <C>n</C> denote
2540+
## the length of <A>gens</A>. Then each of the entries
2541+
## <A>gens</A><C>[1]</C>, <M>\ldots</M> <A>gens</A><C>[n]</C>
2542+
## must be one of the following:
2543+
## <List>
2544+
## <Mark>a list or collection</Mark>
2545+
## <Item>
2546+
## this introduces a new for-loop in the sequence of nested
2547+
## for-loops and if-statements;
2548+
## </Item>
2549+
## <Mark>a function returning a list or collection</Mark>
2550+
## <Item>
2551+
## this introduces a new for-loop in the sequence of nested
2552+
## for-loops and if-statements, where the loop-range depends on
2553+
## the values of the outer loop-variables; or
2554+
## </Item>
2555+
## <Mark>a function returning <K>true</K> or <K>false</K></Mark>
2556+
## <Item>
2557+
## this introduces a new if-statement in the sequence of nested
2558+
## for-loops and if-statements.
2559+
## </Item>
2560+
## </List>
2561+
## <P/>
2562+
## Each function occurring in <A>gens</A> is called with the values selected
2563+
## by the preceding entries of <A>gens</A>, in order.
2564+
## Thus the function in <A>gens</A><C>[k]</C> receives one argument for each
2565+
## of <A>gens</A><C>[1]</C>, <M>\ldots</M>, <A>gens</A><C>[k-1]</C> that
2566+
## introduced a loop variable.
2567+
## <P/>
2568+
## The argument <A>func</A> must be a binary function, whose first
2569+
## argument is an accumulator variable, and the second argument is
2570+
## the tuple of values of the loop-variables.
2571+
## <P/>
2572+
## The accumulator is initialized with <A>init</A>. For every tuple that is
2573+
## produced by the loops and filters described by <A>gens</A>,
2574+
## <A>func</A> is called with the current accumulator and that tuple.
2575+
## Its return value becomes the new accumulator.
2576+
## <P/>
2577+
## If the optional argument <A>abortValue</A> is given, iteration stops as
2578+
## soon as the accumulator becomes identical to <A>abortValue</A>.
2579+
## This is useful for short-circuiting computations such as
2580+
## <Ref Func="ForAllX"/> and <Ref Func="ForAnyX"/>.
2581+
## <P/>
2582+
## <Example><![CDATA[
2583+
## gap> FoldLeftX( [ [ 1 .. 3 ], i -> [ 1 .. i ],
2584+
## > { i, j } -> i <> j ],
2585+
## > { acc, x } -> acc + 1, 0 );
2586+
## 3
2587+
## gap> FoldLeftX( [ [ 1 .. 3 ], [ 1 .. 3 ], \< ],
2588+
## > function( acc, x )
2589+
## > Add( acc, ShallowCopy( x ) );
2590+
## > return acc;
2591+
## > end, [] );
2592+
## [ [ 1, 2 ], [ 1, 3 ], [ 2, 3 ] ]
2593+
## ]]></Example>
2594+
## </Description>
2595+
## </ManSection>
2596+
## <#/GAPDoc>
2597+
##
2598+
DeclareGlobalFunction( "FoldLeftX" );
2599+
2600+
24812601
#############################################################################
24822602
##
24832603
#F Sum( <list>[, <init>] ) . . . . . . . . . . sum of the elements of a list
@@ -2803,6 +2923,8 @@ DeclareOperation( "ForAnyOp", [ IsListOrCollection, IsFunction ] );
28032923
##
28042924
## <Description>
28052925
## <Ref Func="ListX"/> returns a new list constructed from the arguments.
2926+
## The general mechanism underlying this and the related <Q>X</Q>-functions
2927+
## is described in <Ref Func="FoldLeftX"/>.
28062928
## <P/>
28072929
## Each of the arguments <A>arg1</A>, <A>arg2</A>, <M>\ldots</M> <A>argn</A>
28082930
## must be one of the following:
@@ -2825,6 +2947,11 @@ DeclareOperation( "ForAnyOp", [ IsListOrCollection, IsFunction ] );
28252947
## </Item>
28262948
## </List>
28272949
## <P/>
2950+
## Each function occurring among the arguments is called with the values
2951+
## selected by the preceding arguments, in order.
2952+
## Thus the function in the <A>k</A>-th argument position receives one
2953+
## argument for each preceding argument that introduced a loop variable.
2954+
## <P/>
28282955
## The last argument <A>func</A> must be a function,
28292956
## it is applied to the values of the loop-variables
28302957
## and the results are collected.
@@ -2864,7 +2991,7 @@ DeclareOperation( "ForAnyOp", [ IsListOrCollection, IsFunction ] );
28642991
## <Example><![CDATA[
28652992
## gap> l:= [ 1, 2, 3, 4 ];;
28662993
## gap> pair:= function( x, y ) return [ x, y ]; end;;
2867-
## gap> ListX( l, l, pair );
2994+
## gap> ListX( l, l, {x,y} -> [x,y] );
28682995
## [ [ 1, 1 ], [ 1, 2 ], [ 1, 3 ], [ 1, 4 ], [ 2, 1 ], [ 2, 2 ],
28692996
## [ 2, 3 ], [ 2, 4 ], [ 3, 1 ], [ 3, 2 ], [ 3, 3 ], [ 3, 4 ],
28702997
## [ 4, 1 ], [ 4, 2 ], [ 4, 3 ], [ 4, 4 ] ]
@@ -2895,6 +3022,11 @@ DeclareGlobalFunction( "ListX" );
28953022
## <Description>
28963023
## The only difference between <Ref Func="SetX"/> and <Ref Func="ListX"/>
28973024
## is that the result list of <Ref Func="SetX"/> is strictly sorted.
3025+
## <P/>
3026+
## <Example><![CDATA[
3027+
## gap> SetX( [ 1 .. 3 ], [ 1 .. 3 ], \+ );
3028+
## [ 2, 3, 4, 5, 6 ]
3029+
## ]]></Example>
28983030
## </Description>
28993031
## </ManSection>
29003032
## <#/GAPDoc>
@@ -2913,6 +3045,11 @@ DeclareGlobalFunction( "SetX" );
29133045
## <Description>
29143046
## <Ref Func="SumX"/> returns the sum of the elements in the list obtained
29153047
## by <Ref Func="ListX"/> when this is called with the same arguments.
3048+
## <P/>
3049+
## <Example><![CDATA[
3050+
## gap> SumX( [ 1 .. 3 ], [ 1 .. 3 ], \+ );
3051+
## 36
3052+
## ]]></Example>
29163053
## </Description>
29173054
## </ManSection>
29183055
## <#/GAPDoc>
@@ -2932,13 +3069,157 @@ DeclareGlobalFunction( "SumX" );
29323069
## <Ref Func="ProductX"/> returns the product of the elements in the list
29333070
## obtained by <Ref Func="ListX"/> when this is called with the same
29343071
## arguments.
3072+
## <P/>
3073+
## <Example><![CDATA[
3074+
## gap> ProductX( [ 1 .. 3 ], [ 1 .. 3 ], \+ );
3075+
## 172800
3076+
## ]]></Example>
29353077
## </Description>
29363078
## </ManSection>
29373079
## <#/GAPDoc>
29383080
##
29393081
DeclareGlobalFunction( "ProductX" );
29403082

29413083

3084+
#############################################################################
3085+
##
3086+
#O ForAllX( <arg1>, <arg2>, ... <func> )
3087+
##
3088+
## <#GAPDoc Label="ForAllX">
3089+
## <ManSection>
3090+
## <Func Name="ForAllX" Arg='arg1, arg2, ... func'/>
3091+
##
3092+
## <Description>
3093+
## <Ref Func="ForAllX"/> returns <K>true</K> if all elements are
3094+
## <K>true</K> in the list obtained by calling <Ref Func="ListX"/> with the
3095+
## same arguments. Otherwise <K>false</K> is returned.
3096+
## As with <Ref Func="ForAll"/>, the last argument must return either
3097+
## <K>true</K> or <K>false</K>, and evaluation stops as soon as the result
3098+
## is known.
3099+
## <P/>
3100+
## <Example><![CDATA[
3101+
## gap> ForAllX( [ 1 .. 3 ], [ 1 .. 3 ], \< );
3102+
## false
3103+
## ]]></Example>
3104+
## </Description>
3105+
## </ManSection>
3106+
## <#/GAPDoc>
3107+
##
3108+
DeclareGlobalFunction( "ForAllX" );
3109+
3110+
3111+
#############################################################################
3112+
##
3113+
#O ForAnyX( <arg1>, <arg2>, ... <func> )
3114+
##
3115+
## <#GAPDoc Label="ForAnyX">
3116+
## <ManSection>
3117+
## <Func Name="ForAnyX" Arg='arg1, arg2, ... func'/>
3118+
##
3119+
## <Description>
3120+
## <Ref Func="ForAnyX"/> returns <K>true</K> if any element is
3121+
## <K>true</K> in the list obtained by calling <Ref Func="ListX"/> with the
3122+
## same arguments. Otherwise <K>false</K> is returned.
3123+
## As with <Ref Func="ForAny"/>, the last argument must return either
3124+
## <K>true</K> or <K>false</K>, and evaluation stops as soon as the result
3125+
## is known.
3126+
## <P/>
3127+
## <Example><![CDATA[
3128+
## gap> ForAnyX( [ 1 .. 3 ], [ 1 .. 3 ], \< );
3129+
## true
3130+
## ]]></Example>
3131+
## </Description>
3132+
## </ManSection>
3133+
## <#/GAPDoc>
3134+
##
3135+
DeclareGlobalFunction( "ForAnyX" );
3136+
3137+
3138+
#############################################################################
3139+
##
3140+
#O FilteredX( <arg1>, <arg2>, ... <func> )
3141+
##
3142+
## <#GAPDoc Label="FilteredX">
3143+
## <ManSection>
3144+
## <Func Name="FilteredX" Arg='arg1, arg2, ... func'/>
3145+
##
3146+
## <Description>
3147+
## <Ref Func="FilteredX"/> returns the tuples of loop-variable values for
3148+
## which the last argument returns <K>true</K>.
3149+
## In other words, it keeps precisely those tuples that would pass the
3150+
## filters when calling <Ref Func="ListX"/> with the same arguments.
3151+
## <P/>
3152+
## Even with only one generator, the result consists of singleton tuples.
3153+
## Thus <C>FilteredX( [ 1 .. 4 ], IsEvenInt )</C> returns
3154+
## <C>[ [ 2 ], [ 4 ] ]</C>, not <C>[ 2, 4 ]</C>.
3155+
## Use <Ref Func="Filtered"/> if you want to filter the elements of a single
3156+
## list or collection directly.
3157+
## <P/>
3158+
## <Example><![CDATA[
3159+
## gap> FilteredX( [ 1 .. 4 ], IsEvenInt );
3160+
## [ [ 2 ], [ 4 ] ]
3161+
## gap> FilteredX( [ 1 .. 4 ], [ 1 .. 4 ], \< );
3162+
## [ [ 1, 2 ], [ 1, 3 ], [ 1, 4 ], [ 2, 3 ], [ 2, 4 ], [ 3, 4 ] ]
3163+
## ]]></Example>
3164+
## </Description>
3165+
## </ManSection>
3166+
## <#/GAPDoc>
3167+
##
3168+
DeclareGlobalFunction( "FilteredX" );
3169+
3170+
3171+
#############################################################################
3172+
##
3173+
#O NumberX( <arg1>, <arg2>, ... <func> )
3174+
##
3175+
## <#GAPDoc Label="NumberX">
3176+
## <ManSection>
3177+
## <Func Name="NumberX" Arg='arg1, arg2, ... func'/>
3178+
##
3179+
## <Description>
3180+
## <Ref Func="NumberX"/> returns the number of tuples selected by the last
3181+
## argument, using the same arguments as <Ref Func="ListX"/>.
3182+
## Equivalently, it counts the entries of the result that
3183+
## <Ref Func="FilteredX"/> would return with the same arguments.
3184+
## <P/>
3185+
## <Example><![CDATA[
3186+
## gap> NumberX( [ 1 .. 4 ], IsEvenInt );
3187+
## 2
3188+
## gap> NumberX( [ 1 .. 4 ], [ 1 .. 4 ], \< );
3189+
## 6
3190+
## ]]></Example>
3191+
## </Description>
3192+
## </ManSection>
3193+
## <#/GAPDoc>
3194+
##
3195+
DeclareGlobalFunction( "NumberX" );
3196+
3197+
3198+
#############################################################################
3199+
##
3200+
#O PerformX( <arg1>, <arg2>, ... <func> )
3201+
##
3202+
## <#GAPDoc Label="PerformX">
3203+
## <ManSection>
3204+
## <Func Name="PerformX" Arg='arg1, arg2, ... func'/>
3205+
##
3206+
## <Description>
3207+
## <Ref Func="PerformX"/> works like <Ref Func="ListX"/> except that it
3208+
## returns nothing and ignores the return values of <A>func</A>.
3209+
## It is useful for iterating through the tuples described by the arguments
3210+
## purely for their side effects.
3211+
## <P/>
3212+
## <Example><![CDATA[
3213+
## gap> PerformX( [ 1 .. 2 ], [ 3 .. 4 ], Print ); Print( "\n" );
3214+
## 13142324
3215+
## ]]></Example>
3216+
## </Description>
3217+
## </ManSection>
3218+
## <#/GAPDoc>
3219+
##
3220+
DeclareGlobalFunction( "PerformX" );
3221+
3222+
29423223
#############################################################################
29433224
##
29443225
#O Perform( <list>, <func>)

0 commit comments

Comments
 (0)