antirec¶
ソースコード¶
from titan_pylib.others.antirec import antirec
from titan_pylib.others.antirec import antirec_cache
展開済みコード¶
1# from titan_pylib.others.antirec import antirec
2from types import GeneratorType
3
4# ref: https://github.com/cheran-senthil/PyRival/blob/master/pyrival/misc/bootstrap.py
5# ref: https://twitter.com/onakasuita_py/status/1731535542305907041
6
7
8def antirec(func):
9 stack = []
10
11 def wrappedfunc(*args, **kwargs):
12 if stack:
13 return func(*args, **kwargs)
14 to = func(*args, **kwargs)
15 while True:
16 if isinstance(to, GeneratorType):
17 stack.append(to)
18 to = next(to)
19 else:
20 stack.pop()
21 if not stack:
22 break
23 to = stack[-1].send(to)
24 return to
25
26 return wrappedfunc
27
28
29def antirec_cache(func):
30 stack = []
31 memo = {}
32 args_list = []
33
34 def wrappedfunc(*args):
35 args_list.append(args)
36 if stack:
37 return func(*args)
38 to = func(*args)
39 while True:
40 if args_list[-1] in memo:
41 res = memo[args_list.pop()]
42 if not stack:
43 return res
44 to = stack[-1].send(res)
45 continue
46 if isinstance(to, GeneratorType):
47 stack.append(to)
48 to = next(to)
49 else:
50 memo[args_list.pop()] = to
51 stack.pop()
52 if not stack:
53 break
54 to = stack[-1].send(to)
55 return to
56
57 return wrappedfunc