Skip to content

Commit

Permalink
Add CallListFuncWrap
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisJefferson committed Jun 12, 2016
1 parent 5032202 commit 494342e
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 0 deletions.
2 changes: 2 additions & 0 deletions doc/ref/function.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ several arguments">
several arguments</Heading>

<#Include Label="CallFuncList">
<#Include Label="CallFuncListWrap">


</Section>

Expand Down
41 changes: 41 additions & 0 deletions lib/function.g
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,8 @@ BIND_GLOBAL( "EndlineFunc", ENDLINE_FUNC );
## gap> PrintDigits( 1, 9, 7, 3, 2 );
## [ 1, 9, 7, 3, 2 ]
## ]]></Example>
## To generically handle classes of functions, only some of which return values,
## see <Ref Func="CallFuncListWrap"/>
## </Description>
## </ManSection>
## <#/GAPDoc>
Expand All @@ -383,6 +385,45 @@ BIND_GLOBAL( "EndlineFunc", ENDLINE_FUNC );
UNBIND_GLOBAL("CallFuncList"); # was declared 2b defined
DeclareOperationKernel( "CallFuncList", [IS_OBJECT, IS_LIST], CALL_FUNC_LIST );

#############################################################################
##
#F CallFuncListWrap( <func>, <args> ) . . . . . . . . . . . . . call a function
##
## <#GAPDoc Label="CallFuncListWrap">
## <ManSection>
## <Func Name="CallFuncListWrap" Arg='func, args'/>
##
## <Description>
## Like <Ref Oper="CallFuncList"/>, returns the result, when calling function
## <A>func</A> with the arguments given in the list <A>args</A>.
## The difference is that <Ref Func="CallFuncListWrap"/> returns a list.
## This list is length 0 if <A>func</A> returns nothing. If <A>func</A>
## returns a value, then this list contains the return value of <A>func</A>.
## This is useful for wrapping functions which may or may not return.
## For example, a function which prints out the arguments to a function,
## and it's return value (if it exists)
## <Example><![CDATA[
## gap> Explain := function ( func, args... )
## > local ret;
## > ret := CallFuncListWrap( func, args );
## > Print(NameFunction(func), " given ", args);
## > if ret = [] then
## > Print(" returns nothing\n");
## > else
## > Print(" returns ", ret[1], "\n");
## > fi;
## > end;
## function( func, args... ) ... end
## gap> Explain(Union, [1,2], [3,4] );
## Union given [ [ 1, 2 ], [ 3, 4 ] ] returns [ 1, 2, 3, 4 ]
## gap> Explain(Add, [ [], 2 ]);
## Add given [ [ 2 ], 2 ] returns nothing
## ]]></Example>
## </Description>
## </ManSection>
## <#/GAPDoc>

BIND_GLOBAL("CallFuncListWrap", CALL_FUNC_LIST_WRAP );

#############################################################################
##
Expand Down
37 changes: 37 additions & 0 deletions src/calls.c
Original file line number Diff line number Diff line change
Expand Up @@ -1584,6 +1584,39 @@ Obj FuncCALL_FUNC_LIST (
return CallFuncList(func, list);
}

/****************************************************************************
**
*F FuncCALL_FUNC_LIST_WRAP( <self>, <func>, <list> ) . . . . .call a function
**
** 'FuncCALL_FUNC_LIST_WRAP' implements the function 'CallFuncListWrap'.
**
** 'CallFuncListWrap( <func>, <list> )'
**
** 'CallFuncListWrap' calls the function <func> with the arguments
** list <list>, i.e., it is equivalent to '<func>( <list>[1], <list>[2]... )'.
** It differs from 'CallFuncList' as it returns it's arguments as a list,
** which is empty is the function returns no value.
*/

Obj FuncCALL_FUNC_LIST_WRAP (
Obj self,
Obj func,
Obj list )
{
Obj retval = CallFuncList(func, list);
Obj retlist;
if( retval == 0 ) {
retlist = NEW_PLIST(T_PLIST_EMPTY+IMMUTABLE, 0);
}
else {
retlist = NEW_PLIST(T_PLIST, 1);
SET_LEN_PLIST(retlist, 1);
SET_ELM_PLIST(retlist, 1, retval);
CHANGED_BAG(retlist);
}
return retlist;
}

/****************************************************************************
**
Expand Down Expand Up @@ -2070,6 +2103,10 @@ static StructGVarFunc GVarFuncs [] = {

{ "ENDLINE_FUNC", 1, "func",
FuncENDLINE_FUNC, "src/calls.c:ENDLINE_FUNC" },

{ "CALL_FUNC_LIST_WRAP", 2, "func, list",
FuncCALL_FUNC_LIST_WRAP, "src/calls.c:CALL_FUNC_LIST_WRAP" },

{ 0 }

};
Expand Down
20 changes: 20 additions & 0 deletions tst/testinstall/callfunc.tst
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
gap> START_TEST("callfunc.tst");

# Union([1]) = 1 :(
gap> ForAll([0,2..100], x -> [1..x] = CallFuncList(Union, List([1..x], y -> [y]) ) );
true
gap> CallFuncList(Group, [ (1,2) ]) = Group((1,2));
true
gap> ForAll([0,2..100], x -> [[1..x]] = CallFuncListWrap(Union, List([1..x], y -> [y]) ) );
true
gap> CallFuncListWrap(Group, [ (1,2) ]) = [ Group((1,2)) ];
true
gap> l := [];;
gap> CallFuncList(Add, [ l, 2 ] );
gap> CallFuncList(Add, [ l, 3, 4] );
gap> l = [2,,,3];
true
gap> swallow := function(x...) end;;
gap> ForAll([0..100], x -> CallFuncListWrap(swallow, List([1..x], y -> [y]) ) = [] );
true
gap> STOP_TEST( "callfunc.tst", 1);

0 comments on commit 494342e

Please sign in to comment.