The First Class Function

A medium Python interview practice problem on DataDriven. Write the Python and run it against test cases, with instant feedback.

Domain
Python
Difficulty
medium
Seniority
L4
Asked in
Horizon Media

Problem

Implement first_class_demo(test_cases), where test_cases is a list of dicts. Each dict has an op of either 'apply_twice' or 'compose' and an integer x. Inside, build a registry of named one-argument functions: 'double' = x*2, 'inc' = x+1, 'square' = x*x. For an 'apply_twice' op, look up the named function in f and return f(f(x)). For a 'compose' op, look up f and g, build the composed function lambda x: f(g(x)) (apply g first, then f), and apply it to x. Return the list of results, one per test case, in the same order as the input. Your implementation should pass functions as values and return a function from compose (closure). An empty test_cases returns an empty list.

Functions travel as values - prove you can pass one around.

Example 1

Input:

test_cases = [{"f":"double","x":3,"op":"apply_twice"},{"f":"double","g":"inc","x":5,"op":"compose"}]

Output:

[12,12]

Example 2

Input:

test_cases = [{"f":"inc","x":10,"op":"apply_twice"},{"f":"square","g":"inc","x":4,"op":"compose"},{"f":"double","g":"double","x":7,"op":"compose"}]

Output:

[12,25,28]

Worked solution and explanation

Why this problem exists in real interviews

This tests understanding of first-class functions and function composition in Python. It probes whether a candidate can pass functions as arguments, return functions from functions, and chain transformations. The driver first_class_demo ties it together: it builds a registry of named functions and dispatches each test case through apply_twice or compose.


Break down the requirements

Step 1: Build the function registry

Map each name to a one-argument function: 'double' -> x*2, 'inc' -> x+1, 'square' -> x*x. These are the first-class values you will pass around.

Step 2: Implement apply_twice(f, x)

Call f(x) to get an intermediate result, then call f on that result and return it: f(f(x)).

Step 3: Implement compose(f, g)

Return a new function that, when called with x, computes f(g(x)) - apply g first, then f. This closure captures f and g.

Step 4: Dispatch each test case

Iterate the test cases in order. For 'apply_twice', look up f and return apply_twice(f, x). For 'compose', look up f and g, build compose(f, g), and apply it to x. Collect each result into a list and return it.


The solution

Higher-order function application and composition
def first_class_demo(test_cases):
    registry = {
        'double': lambda x: x * 2,
        'inc': lambda x: x + 1,
        'square': lambda x: x * x,
    }

    def apply_twice(f, x):
        first = f(x)
        result = f(first)
        return result

    def compose(f, g):
        def composed(x):
            inner = g(x)
            result = f(inner)
            return result
        return composed

    results = []
    for case in test_cases:
        op = case['op']
        x = case['x']
        if op == 'apply_twice':
            f = registry[case['f']]
            results.append(apply_twice(f, x))
        elif op == 'compose':
            f = registry[case['f']]
            g = registry[case['g']]
            composed = compose(f, g)
            results.append(composed(x))
    return results

Common follow-up questions