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

Add a convenient way to display bindings inside of closures #3569

Open
fingolfin opened this issue Jul 14, 2019 · 3 comments
Open

Add a convenient way to display bindings inside of closures #3569

fingolfin opened this issue Jul 14, 2019 · 3 comments
Labels
kind: enhancement Label for issues suggesting enhancements; and for pull requests implementing enhancements

Comments

@fingolfin
Copy link
Member

fingolfin commented Jul 14, 2019

Consider this:

gap> f := ApplicableMethod( OrbitsDomain, [ SymmetricGroup(5), [1..5] ] );;
gap> Display(f);
function ( G, D )
    if D = MovedPoints( G ) then
        return op( G );
    else
        TryNextMethod();
    fi;
    return;
end

Quick, what is "op" standing for here?...

Well, of course again for OrbitsDomain.

Code that generates code by using closures can be super helpful and nice, but a nighmare to debug, largely because it can be so tricky to figure out the bindings inside a closure. A more direct example would be this:

gap> makeFun:=n -> x -> x + n;;
gap> f:=makeFun(42);;
gap> Display(f);
function ( x )
    return x + n;
end

If you hadn't seen the definition of f here, you'd have no way to know what n is. This should be different.


Note by @wilfwilson: Since creating this PR, @fingolfin has added the function BindingsOfClosure, which allows one to see and to access these variables in PR #3606. Thus we now get:

gap> BindingsOfClosure(f);
rec( n := 42 )

Note that this function is undocumented, so it might be nice to have some kind of documentation for it if someone feels like it while addressing this issue. End of note by @wilfwilson.


I suggest that we use BindingsOfClosure to add a way to view the local bindings of a function; at least the ones that are actually used in it. We could then show it when "Displaying" the function.

gap> Display(f);
# function closure with bindings:
#   n = 42
function ( x )
    return x + n;
end

Of course the "bindings" are strictly speaking all locals (including arguments) of the parent function of the given function (and this can potentially go back recursively). Coming back to the initial OrbitsDomain example, the parent function is OrbitsishOperation and it starts like this:

BindGlobal( "OrbitsishOperation", function( name, reqs, usetype, NewAorP )
    local op;

    # Create the attribute or property.
    op:= NewAorP( name, IsExternalSet );
...

So the "bindings" in my initial example actually also include name, reqs, usetype and NewAorP. But I think that's usually actually quite helpful.

@fingolfin fingolfin added the kind: enhancement Label for issues suggesting enhancements; and for pull requests implementing enhancements label Jul 14, 2019
@wilfwilson wilfwilson changed the title Add a convenient way to display (or even access!) bindings inside of closures Add a convenient way to display bindings inside of closures Aug 30, 2019
@wilfwilson
Copy link
Member

I updated the issue in light of #3606 being created and merged.

@fingolfin
Copy link
Member Author

Here is an idea for perhaps making this more convenient: in my initial example, wouldn't it be nice if I could just write f.op to get the value of op?

It shouldn't be hard to implement that with a variation of the code in PR #3606

@wilfwilson
Copy link
Member

That sounds like a nice idea.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: enhancement Label for issues suggesting enhancements; and for pull requests implementing enhancements
Projects
None yet
Development

No branches or pull requests

2 participants