def pair(x, y):
    def set_x(v):
        nonlocal x
        x = v
    def set_y(v):
        nonlocal y
        y = v
    return lambda m: (x
                      if m == "head"
                      else y
                      if m == "tail"
                      else set_x
                      if m == "set_head"
                      else set_y
                      if m == "set_tail"
                      else error("undefined operation -- pair", m))

def head(z):
    return z("head")

def tail(z):
    return z("tail")

def set_head(z, new_value):
    z("set_head")(new_value)
    return z

def set_tail(z, new_value):
    z("set_tail")(new_value)
    return z
x = pair(1, 2)
z = pair(x, x)
set_head(tail(z), 17)
print(head(x))

# expected: 17
