Skip to content

Conversation

@ahaldane
Copy link
Member

Fixes #10620

@ahaldane
Copy link
Member Author

Hmm, my original code here to do del recurse (possibly with gc.collect()) doesn't work.

I have to admit, I don't understand PyPy vs CPython garrbage collection well enough to see how to cause the closure to get collected immediately.

So I'm just going to go for the code reorg here to avoid the closure. All I did is move the closure out to its own function, with a new arg to store the closure variables.

@charris charris removed the 09 - Backport-Candidate PRs tagged should be backported label Feb 18, 2018
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A full up documentation string would be helpful here. I didn't worry about that for the backport, but it would be good to have it going forward.

@eric-wieser
Copy link
Member

eric-wieser commented Feb 18, 2018 via email

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also to avoid UPDATE_IF_COPY interactions, but no need to mention that here

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be block_recursion = None?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whoops!

@ahaldane ahaldane force-pushed the fix_arrayprint_recursive_closure branch from e667c0e to 50fde71 Compare February 19, 2018 04:22
@ahaldane
Copy link
Member Author

Fixed up.

Copy link
Member

@eric-wieser eric-wieser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM pending tests

@eric-wieser
Copy link
Member

Out of curiousity - does using a Y-combinator solve the reference cycle?

@ahaldane
Copy link
Member Author

Ah, that's a bit over my head, though I would be pleased to understand that on the tips of my fingers. I thought monads were the way of storing hidden state (closure variables).

@eric-wieser eric-wieser merged commit 71555c4 into numpy:master Feb 19, 2018
@eric-wieser
Copy link
Member

eric-wieser commented Feb 19, 2018

I guess the key thing here is to get the self-reference via an argument rather than a closure. Without invoking a full y-combinator:

def recurser(recurser, outer_args):
    ...
    # do the recursive call
    recurser(recurser, inner_args)

recurser(recurser, initial_args)

Or with one:

def fix(f):
    return lambda *args, **kwargs: f(fix(f), *args, **kwargs)

@fix
def recurser(recurser, outer_args):
    ...
    # do the recursive call
    recurser(inner_args)

recurser(initial_args)

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants