# Funkcje jako obiekty: argumenty i "wyniki" funkcji

# Trzy funkcje użyte później:
def square(x):
    return x ** 2


def translate(x):
    return x + 1


def double(x):
    return 2 * x


# Funkcja, która dla dwóch jednoparametrowych funkcji zwraca nową funkcję - ich złożenie
def compose(f, g):
    def h(x):
        return f(g(x))  # definicja złożenia
    return h  # h jest zwracaną funkcją

# dodawanie funkcji
def add(f, g):
    def h(x):
        return f(x) + g(x)
    return h


h = compose(square, translate)
print(h(10))  # (10+1)**2 == 121
z = compose(square, translate)(10)
print(z)

h = add(square, double)
print(h(5)) # 5**2 + 2*5
