Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to open a closure in python?

I came accross the following interview question and have no idea how to solve it:

def cons(a, b):
    def pair(f):
        return f(a, b)
    return pair

Given a pair, e.g cons(6,8) I am requested to return a and b separetely, e.g in this case 6, 8 respectively.

Meaning, for example,

def first(pair):
    pass
    #would return pair's `a` somehow

def second(pair):
    pass
    #would return pair's `b` somehow

How can this be done?

like image 899
Gulzar Avatar asked Aug 12 '19 05:08

Gulzar


4 Answers

you can try:

pair = cons(6, 8)

def first(pair):
    return  pair(lambda x, y: x)

def second(pair):
    return  pair(lambda x, y: y)

print(first(pair))
print(second(pair))

# ouput:
# 6
# 8
like image 113
kederrac Avatar answered Sep 22 '22 02:09

kederrac


The function cons takes two arguments, a and b, and returns a function that takes one argument, f. The returned function is a closure, since it contains references to a and b which would otherwise be out of scope when cons returns.

The returned function takes a function argument, calls it with a and b, and returns the result.

For example, if you do:

func = cons(6, 8)

Then you can do:

def g(a, b):
    return a

func(g)

This will return 6. Similarly, if you define g to return b, then func would return 8.

like image 38
Tom Karzes Avatar answered Sep 22 '22 02:09

Tom Karzes


How about:

c = cons(6, 8)
a = c.__closure__[0].cell_contents
b = c.__closure__[1].cell_contents

print(a, b)
like image 34
Sraw Avatar answered Sep 24 '22 02:09

Sraw


Create a lambda uses iter(args) to make the args passed into cons iterable. Then, the caller can use next(it) to access individual elements:

def cons(a, b):
    def pair(f):
        return f(a, b)
    return pair

it = cons(6, 8)(lambda *args: iter(args))
print(next(it)) # => 6
print(next(it)) # => 8
like image 40
ggorlen Avatar answered Sep 23 '22 02:09

ggorlen