We use cookies (including Google cookies) to personalize ads and analyze traffic. By continuing to use our site, you accept our Privacy Policy.

Allow One Function Call

Number: 2796

Difficulty: Easy

Paid? No

Companies: Amazon, Google


Problem Description

Given a function fn, create a new function that calls fn at most once. The first time the new function is invoked, it should return the result of fn with the given arguments. Every subsequent call to the function should return undefined.


Key Insights

  • Use closure to maintain a state (flag) that indicates if the function has been called.
  • On the first call, invoke fn and store the call result.
  • For subsequent calls, simply return undefined without calling fn again.
  • The approach maintains the same parameters and “this” context integrity of fn.

Space and Time Complexity

Time Complexity: O(1) per call because each call just checks a flag and may call fn once. Space Complexity: O(1) since only a single flag (and optionally stored result) is maintained in closure.


Solution

We wrap the original function fn inside another function that uses a closure variable (a boolean flag) to track whether fn has been called. When the new function is invoked for the first time, we flip this flag and return the result of fn. On later invocations, the flag remains set and we directly return undefined without calling fn.

This technique is a common idiom in functional programming where state persistence across calls is needed. The key trick is leveraging closures to maintain state even when the function call stack is no longer active.


Code Solutions

# Define the once function that wraps the given function
def once(fn):
    # flag to track if the function has been called
    called = False
    # store the result of the first call if needed (optional, here we just return directly)
    result = None

    # Define the inner function that uses closure to access 'called' and 'result'
    def inner(*args, **kwargs):
        nonlocal called, result  # use nonlocal to modify variables defined in the enclosing scope
        if not called:
            called = True       # mark as called so that further calls return undefined
            result = fn(*args, **kwargs)  # call the original function with arguments
            return result
        return None   # undefined case equivalent in Python is None

    return inner

# Example usage:
# def add(a, b, c):
#     return a + b + c
# once_add = once(add)
# print(once_add(1, 2, 3))  # Outputs: 6
# print(once_add(2, 3, 6))  # Outputs: None
← Back to All Questions