1# mode: run 2# tag: closures 3# ticket: 82 4# preparse: id 5# preparse: def_to_cdef 6 7cimport cython 8 9def add_n(int n): 10 """ 11 >>> f = add_n(3) 12 >>> f(2) 13 5 14 15 >>> f = add_n(1000000) 16 >>> f(1000000), f(-1000000) 17 (2000000, 0) 18 """ 19 def f(int x): 20 return x+n 21 return f 22 23def a(int x): 24 """ 25 >>> a(5)() 26 8 27 """ 28 def b(): 29 def c(): 30 return 3+x 31 return c() 32 return b 33 34def local_x(int arg_x): 35 """ 36 >>> local_x(1)(2)(4) 37 4 2 1 38 15 39 """ 40 cdef int local_x = arg_x 41 def y(arg_y): 42 y = arg_y 43 def z(long arg_z): 44 cdef long z = arg_z 45 print z, y, local_x 46 return 8+z+y+local_x 47 return z 48 return y 49 50def x(int x): 51 """ 52 >>> x(1)(2)(4) 53 15 54 """ 55 def y(y): 56 def z(long z): 57 return 8+z+y+x 58 return z 59 return y 60 61def x2(int x2): 62 """ 63 >>> x2(1)(2)(4) 64 4 2 1 65 15 66 """ 67 def y2(y2): 68 def z2(long z2): 69 print z2, y2, x2 70 return 8+z2+y2+x2 71 return z2 72 return y2 73 74 75def inner_override(a,b): 76 """ 77 >>> inner_override(2,4)() 78 5 79 """ 80 def f(): 81 a = 1 82 return a+b 83 return f 84 85 86def reassign(x): 87 """ 88 >>> reassign(4)(2) 89 3 90 """ 91 def f(a): 92 return a+x 93 x = 1 94 return f 95 96def reassign_int(x): 97 """ 98 >>> reassign_int(4)(2) 99 3 100 """ 101 def f(int a): 102 return a+x 103 x = 1 104 return f 105 106def reassign_int_int(int x): 107 """ 108 >>> reassign_int_int(4)(2) 109 3 110 """ 111 def f(int a): 112 return a+x 113 x = 1 114 return f 115 116 117def cy_twofuncs(x): 118 """ 119 >>> def py_twofuncs(x): 120 ... def f(a): 121 ... return g(x) + a 122 ... def g(b): 123 ... return x + b 124 ... return f 125 126 >>> py_twofuncs(1)(2) == cy_twofuncs(1)(2) 127 True 128 >>> py_twofuncs(3)(5) == cy_twofuncs(3)(5) 129 True 130 """ 131 def f(a): 132 return g(x) + a 133 def g(b): 134 return x + b 135 return f 136 137def switch_funcs(a, b, int ix): 138 """ 139 >>> switch_funcs([1,2,3], [4,5,6], 0)([10]) 140 [1, 2, 3, 10] 141 >>> switch_funcs([1,2,3], [4,5,6], 1)([10]) 142 [4, 5, 6, 10] 143 >>> switch_funcs([1,2,3], [4,5,6], 2) is None 144 True 145 """ 146 def f(x): 147 return a + x 148 def g(x): 149 return b + x 150 if ix == 0: 151 return f 152 elif ix == 1: 153 return g 154 else: 155 return None 156 157def ignore_func(x): 158 def f(): 159 return x 160 return None 161 162def call_ignore_func(): 163 """ 164 >>> call_ignore_func() 165 """ 166 ignore_func((1,2,3)) 167 168def more_inner_funcs(x): 169 """ 170 >>> inner_funcs = more_inner_funcs(1)(2,4,8) 171 >>> inner_funcs[0](16), inner_funcs[1](32), inner_funcs[2](64) 172 (19, 37, 73) 173 """ 174 # called with x==1 175 def f(a): 176 def g(b): 177 # called with 16 178 return a+b+x 179 return g 180 def g(b): 181 def f(a): 182 # called with 32 183 return a+b+x 184 return f 185 def h(b): 186 def f(a): 187 # called with 64 188 return a+b+x 189 return f 190 def resolve(a_f, b_g, b_h): 191 # called with (2,4,8) 192 return f(a_f), g(b_g), h(b_h) 193 return resolve 194 195 196@cython.test_assert_path_exists("//DefNode//DefNode//DefNode//DefNode", 197 "//DefNode[@needs_outer_scope = False]", # deep_inner() 198 "//DefNode//DefNode//DefNode//DefNode[@needs_closure = False]", # h() 199 ) 200@cython.test_fail_if_path_exists("//DefNode//DefNode[@needs_outer_scope = False]") 201def deep_inner(): 202 """ 203 >>> deep_inner()() 204 2 205 """ 206 cdef int x = 1 207 def f(): 208 def g(): 209 def h(): 210 return x+1 211 return h 212 return g() 213 return f() 214 215 216@cython.test_assert_path_exists("//DefNode//DefNode//DefNode", 217 "//DefNode//DefNode//DefNode[@needs_outer_scope = False]", # a() 218 "//DefNode//DefNode//DefNode[@needs_closure = False]", # a(), g(), h() 219 ) 220@cython.test_fail_if_path_exists("//DefNode//DefNode//DefNode[@needs_closure = True]") # a(), g(), h() 221def deep_inner_sibling(): 222 """ 223 >>> deep_inner_sibling()() 224 2 225 """ 226 cdef int x = 1 227 def f(): 228 def a(): 229 return 1 230 def g(): 231 return x+a() 232 def h(): 233 return g() 234 return h 235 return f() 236