# mode: run # tag: closures # ticket: 82 # preparse: id # preparse: def_to_cdef cimport cython def add_n(int n): """ >>> f = add_n(3) >>> f(2) 5 >>> f = add_n(1000000) >>> f(1000000), f(-1000000) (2000000, 0) """ def f(int x): return x+n return f def a(int x): """ >>> a(5)() 8 """ def b(): def c(): return 3+x return c() return b def local_x(int arg_x): """ >>> local_x(1)(2)(4) 4 2 1 15 """ cdef int local_x = arg_x def y(arg_y): y = arg_y def z(long arg_z): cdef long z = arg_z print z, y, local_x return 8+z+y+local_x return z return y def x(int x): """ >>> x(1)(2)(4) 15 """ def y(y): def z(long z): return 8+z+y+x return z return y def x2(int x2): """ >>> x2(1)(2)(4) 4 2 1 15 """ def y2(y2): def z2(long z2): print z2, y2, x2 return 8+z2+y2+x2 return z2 return y2 def inner_override(a,b): """ >>> inner_override(2,4)() 5 """ def f(): a = 1 return a+b return f def reassign(x): """ >>> reassign(4)(2) 3 """ def f(a): return a+x x = 1 return f def reassign_int(x): """ >>> reassign_int(4)(2) 3 """ def f(int a): return a+x x = 1 return f def reassign_int_int(int x): """ >>> reassign_int_int(4)(2) 3 """ def f(int a): return a+x x = 1 return f def cy_twofuncs(x): """ >>> def py_twofuncs(x): ... def f(a): ... return g(x) + a ... def g(b): ... return x + b ... return f >>> py_twofuncs(1)(2) == cy_twofuncs(1)(2) True >>> py_twofuncs(3)(5) == cy_twofuncs(3)(5) True """ def f(a): return g(x) + a def g(b): return x + b return f def switch_funcs(a, b, int ix): """ >>> switch_funcs([1,2,3], [4,5,6], 0)([10]) [1, 2, 3, 10] >>> switch_funcs([1,2,3], [4,5,6], 1)([10]) [4, 5, 6, 10] >>> switch_funcs([1,2,3], [4,5,6], 2) is None True """ def f(x): return a + x def g(x): return b + x if ix == 0: return f elif ix == 1: return g else: return None def ignore_func(x): def f(): return x return None def call_ignore_func(): """ >>> call_ignore_func() """ ignore_func((1,2,3)) def more_inner_funcs(x): """ >>> inner_funcs = more_inner_funcs(1)(2,4,8) >>> inner_funcs[0](16), inner_funcs[1](32), inner_funcs[2](64) (19, 37, 73) """ # called with x==1 def f(a): def g(b): # called with 16 return a+b+x return g def g(b): def f(a): # called with 32 return a+b+x return f def h(b): def f(a): # called with 64 return a+b+x return f def resolve(a_f, b_g, b_h): # called with (2,4,8) return f(a_f), g(b_g), h(b_h) return resolve @cython.test_assert_path_exists("//DefNode//DefNode//DefNode//DefNode", "//DefNode[@needs_outer_scope = False]", # deep_inner() "//DefNode//DefNode//DefNode//DefNode[@needs_closure = False]", # h() ) @cython.test_fail_if_path_exists("//DefNode//DefNode[@needs_outer_scope = False]") def deep_inner(): """ >>> deep_inner()() 2 """ cdef int x = 1 def f(): def g(): def h(): return x+1 return h return g() return f() @cython.test_assert_path_exists("//DefNode//DefNode//DefNode", "//DefNode//DefNode//DefNode[@needs_outer_scope = False]", # a() "//DefNode//DefNode//DefNode[@needs_closure = False]", # a(), g(), h() ) @cython.test_fail_if_path_exists("//DefNode//DefNode//DefNode[@needs_closure = True]") # a(), g(), h() def deep_inner_sibling(): """ >>> deep_inner_sibling()() 2 """ cdef int x = 1 def f(): def a(): return 1 def g(): return x+a() def h(): return g() return h return f()