Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Syntax extension: unpacking argument lists #2043

Open
fingolfin opened this issue Dec 20, 2017 · 4 comments
Open

Syntax extension: unpacking argument lists #2043

fingolfin opened this issue Dec 20, 2017 · 4 comments

Comments

@fingolfin
Copy link
Member

Somewhat dually to #40, I often wish there was a shorter way to call a function with a given list of arguments than CallFuncList(func, list). And quite often I also would like to do something like CallFuncList(func, Concatenation([true], list, [42])), i.e. prepend or append some arguments.

In Python, this is solved by Unpacking Argument Lists. A hypothetical GAP adaption might look like this:

# this becomes ...
CallFuncList(func, list);
# that
func(*list);

# and this ...
CallFuncList(func, Concatenation([true], list, [42]));
# ... could be rewritten like so
func(true, *list, 42);

Then I could e.g. write List(Collected(FactorsInt(n)), pn -> \^(*pn)); to get a list of the maximal primer power divisors of n. That's a somewhat artificial example, of course, but I have had need for something like this plenty of times.

Actually, what I'd also quite often use is a variant of List which uses * when it invokes the function. Say

# if we define this...
ListWithUnpacking:= {list, func} ->  List(list, x -> func(*x));

# then the above example can be rewritten as:
ListWithUnpacking(Collected(FactorsInt(n)), \^);
@fingolfin
Copy link
Member Author

BTW, this could of course also be extended to other contexts, to give some form of "list interpolation" (if that's the right term). E.g. list := [true, *list, 42] as shorthand for Concatenation([true], list, [42]).

And of course one could also use * multiple times. So [*listA, *listB] to concatenate two lists.

So, * would be valid in two places: inside of function call parameter lists; and inside list literal definitions. Nowhere else.

(The syntax with * is of course not set in stone; but it has the advantage of being close to Python, and I think so far no valid expression in GAP can start with an *, so that's one problem less when implementing this).

@ChrisJefferson
Copy link
Contributor

I like this, definately for function calls, and then it would be natural to have it in lists too.

Talking about notation (sorry!), the other option would be f(list...), which would line up with f := function(x...).

@sebasguts
Copy link
Member

I think this feature would be really useful.

@fingolfin
Copy link
Member Author

BTW, another idea would be to also allow interpolation for records. I think I can explain it best with an example (here I am using a... instead of *a as discussed on issue #40, but that is not intended to presume any kind of decision as to which syntax to use):

gap> r:=rec( a:=1, a:=2 );  # current GAP behavior: take last value for the record key
rec( a := 2 )
gap> a:=rec( x:=1, y:=2 );;
gap> b:=rec( x:=40, z:=42 );;
gap> c:=rec( a:=1, a..., b..., y:=5 );
rec( a := 1, x := 40, y := 5, z := 42 )
gap> # the above is essentially equivalent to this:
gap> c:=rec( a:=1, x:=1, y:=2, x:=40, z:=42, y:=5 );
rec( a := 1, x := 40, y := 5, z := 42 )

So one could "merge" records this way. This is useful if one wants to implement options via records, and give default values. You can write this:

foo := function(arg1, arg2, opt)
...
  defaultOpts := rec( opt1 := true, opt2 := fase );
  opt := rec( defaultOpts..., opt... );

That said, I am not sure record interpolation would be quite as useful as list interpolation. It could become more interesting if we ever want to add keyword arguments (see feature request issue #1051), because then it would be natural to also allow this for function calls:

val := myfunc(1, 2, opt...);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants