cython
1# mode: run
2# tag: closures
3# ticket: t82
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)
135
14
15>>> f = add_n(1000000)
16>>> f(1000000), f(-1000000)
17(2000000, 0)
18"""
19def f(int x):
20return x+n
21return f
22
23def a(int x):
24"""
25>>> a(5)()
268
27"""
28def b():
29def c():
30return 3+x
31return c()
32return b
33
34def local_x(int arg_x):
35"""
36>>> local_x(1)(2)(4)
374 2 1
3815
39"""
40cdef int local_x = arg_x
41def y(arg_y):
42y = arg_y
43def z(long arg_z):
44cdef long z = arg_z
45print z, y, local_x
46return 8+z+y+local_x
47return z
48return y
49
50def x(int x):
51"""
52>>> x(1)(2)(4)
5315
54"""
55def y(y):
56def z(long z):
57return 8+z+y+x
58return z
59return y
60
61def x2(int x2):
62"""
63>>> x2(1)(2)(4)
644 2 1
6515
66"""
67def y2(y2):
68def z2(long z2):
69print z2, y2, x2
70return 8+z2+y2+x2
71return z2
72return y2
73
74
75def inner_override(a,b):
76"""
77>>> inner_override(2,4)()
785
79"""
80def f():
81a = 1
82return a+b
83return f
84
85
86def reassign(x):
87"""
88>>> reassign(4)(2)
893
90"""
91def f(a):
92return a+x
93x = 1
94return f
95
96def reassign_int(x):
97"""
98>>> reassign_int(4)(2)
993
100"""
101def f(int a):
102return a+x
103x = 1
104return f
105
106def reassign_int_int(int x):
107"""
108>>> reassign_int_int(4)(2)
1093
110"""
111def f(int a):
112return a+x
113x = 1
114return 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)
127True
128>>> py_twofuncs(3)(5) == cy_twofuncs(3)(5)
129True
130"""
131def f(a):
132return g(x) + a
133def g(b):
134return x + b
135return 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
144True
145"""
146def f(x):
147return a + x
148def g(x):
149return b + x
150if ix == 0:
151return f
152elif ix == 1:
153return g
154else:
155return None
156
157def ignore_func(x):
158def f():
159return x
160return None
161
162def call_ignore_func():
163"""
164>>> call_ignore_func()
165"""
166ignore_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
175def f(a):
176def g(b):
177# called with 16
178return a+b+x
179return g
180def g(b):
181def f(a):
182# called with 32
183return a+b+x
184return f
185def h(b):
186def f(a):
187# called with 64
188return a+b+x
189return f
190def resolve(a_f, b_g, b_h):
191# called with (2,4,8)
192return f(a_f), g(b_g), h(b_h)
193return 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()()
2042
205"""
206cdef int x = 1
207def f():
208def g():
209def h():
210return x+1
211return h
212return g()
213return 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()()
2242
225"""
226cdef int x = 1
227def f():
228def a():
229return 1
230def g():
231return x+a()
232def h():
233return g()
234return h
235return f()
236