antirec

ソースコード

from titan_pylib.others.antirec import antirec
from titan_pylib.others.antirec import antirec_cache

view on github

展開済みコード

 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

仕様

antirec(func)[source]
antirec_cache(func)[source]