Skip to content

Improve Strict Equality To Account For Named Closures #852

Closed
@rmorshea

Description

@rmorshea

Current Situation

Right now, strictly_equal does not understand how to check if named closures are the same. Here's an example of such a closure:

def add(first):
    def inner(second):
        return first + second
    return inner

incr = add(1)
assert incr(2) == 3

Here, while add(1) is not add(1) both produce the same behavior, IDOM won't recognize that they're the same.

Proposed Actions

It turns out that we can fairly reliable look at a function's __qualname__, __closure__, and __defaults__ to determine whether it's the same function. The logic to check this would look like:

def function_is_strictly_equal(f1, f2):
    return (
        f1.__qualname__ == f2.__qualname__
        and "<lamba>" not in f1.__qualname__
        and all(strictly_equal(c1, c2) for c1, c2 in zip(f1.__closure__, f2.__closure__))
        and all(strictly_equal(c1, c2) for c1, c2 in zip(f1.__defaults__, f2.__defaults__))
    )

The catch here is that technically, a user could do the following:

def make_closures(x):
    def do_something(y): ...
    do_something_else = do_something

    def do_something(z): ...

    return do_something, do_something_else

f1, f2 = make_closures()
assert not function_is_strictly_equal(f1, f2)  # will fail

This will fail because both functions, while they may implement different logic, have the same qualname. This is basically the same reason that we cannot compare lambdas. Since they all have the same name.

There may be ways to work around this. For example, f1 and f1 were defined on different lines. You could check this using __code__.co_firstlineno.

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority-2-moderateShould be resolved on a reasonable timeline.type-revisionAbout a change in functionality or behavior

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions