рдЕрд╕рд╛рдорд╛рдиреНрдп рдЕрдЬрдЧрд░ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ


рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рд▓реИрдВрдЧреНрд╡реЗрдЬ рдХреЛрд░реНрд╕ рджреЗрдЦрдиреЗ рдФрд░ рдлрдВрдХреНрд╢рдирд▓ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдкрдврд╝рдиреЗ рдХреЗ рдмрд╛рдж , рдореИрдВ рдЕрдЬрдЧрд░ рдореЗрдВ рдЗрди рд╕рднреА рд╢рд╛рдВрдд рдЪреАрдЬреЛрдВ рдХреЛ рджреЛрд╣рд░рд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ред рдХреБрдЫ рдЪреАрдЬреЗрдВ рд╕реБрдВрджрд░ рдФрд░ рдЖрд╕рд╛рдиреА рд╕реЗ рдХреА рдЬрд╛рдиреЗ рд▓рдЧреАрдВ, рдмрд╛рдХреА рдЪреАрдЬреЗрдВ рдбрд░рд╛рд╡рдиреА рдФрд░ рдмреЗрдХрд╛рд░ рд╣реЛ рдЧрдИрдВред

рд▓реЗрдЦ рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реИрдВ:


рд▓реЗрдЦ рдХреЛ рдЕрдЬрдЧрд░ 3.3+ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

рдХреБрдЫ рднреНрд░рд╛рдордХ рд╢рдмреНрдж


рдЖрдк рдПрдХ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд╢реИрд▓реА рдореЗрдВ рдЕрдЬрдЧрд░ рдореЗрдВ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдХреЗ рдЕрдирд╛рдо рдХрд╛рд░реНрдп рд╣реИрдВ:
sum_x_y = lambda x, y: x + y print(sum_x_y(1, 2)) # 3 

рдЙрдЪреНрдЪ-рдХреНрд░рдо рдХреЗ рдХрд╛рд░реНрдп (рдЕрдиреНрдп рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рдирд╛ рдпрд╛ рд╡рд╛рдкрд╕ рдХрд░рдирд╛):
 def call_and_twice(fnc, x, y): return fnc(x, y) * 2 print(call_and_twice(sum_x_y, 3, 4)) # 14 

рд╢реЙрд░реНрдЯ рд╕рд░реНрдХрд┐рдЯ:
 def closure_sum(x): fnc = lambda y: x + y return fnc sum_with_3 = closure_sum(3) print(sum_with_3(12)) # 15 

рдЯрдкрд▓ рдЕрдирдкреИрдХрд┐рдВрдЧ (рд▓рдЧрднрдЧ рдкреИрдЯрд░реНрди рдорд┐рд▓рд╛рди):
 a, b, c = [1, 2, 3] print(a, b, c) # 1 2 3 hd, *tl = range(5) print(hd, 'tl:', *tl) # 0 tl: 1 2 3 4 

рдФрд░ рдХреВрд▓ рдореЙрдбреНрдпреВрд▓ рдХрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдФрд░ рдЗрдЯрд░реНрдЯреВрд▓ ред

currying


рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХрдИ рддрд░реНрдХреЛрдВ рд╕реЗ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдирд╛ рдЬреЛ рдПрдХ рд╕рдордп рдореЗрдВ рдЕрдкрдиреЗ рддрд░реНрдХреЛрдВ рдХреЛ рд▓реЗрддрд╛ рд╣реИред

рд╕рд░рд▓рддрдо рдорд╛рдорд▓реЗ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ, sum_x_y рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХрд░реЗрдВ:
 sum_x_y_carry = lambda x: lambda y: sum_x_y(x, y) print(sum_x_y_carry(5)(12)) # 17 

рдХреБрдЫ рд╢рд╛рдВрдд рдирд╣реАрдВ рд╣реИ, рдпрд╣ рдХреЛрд╢рд┐рд╢ рдХрд░реЛ:
 sum_with_12 = sum_x_y_carry(12) print(sum_with_12(1), sum_with_12(12)) # 13 24 sum_with_5 = sum_x_y_carry(5) print(sum_with_5(10), sum_with_5(17)) # 15 22 

рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЕрдзрд┐рдХ рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ, рдЕрдм рд╣рдо рджреЛ рддрд░реНрдХреЛрдВ рдХреЗ рд╕рд╛рде рдХрд░реА рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рдХрд╛рд░реНрдп рдХрд░реЗрдВрдЧреЗ, рдХреНрдпреЛрдВрдХрд┐ рд╣рд░ рдмрд╛рд░ lambda x: lambda y: zzzz рд▓рд┐рдЦрддреЗ рд╣реБрдП рд╢рд╛рдВрдд рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ:
 curry_2 = lambda fn: lambda x: lambda y: fn(x, y) 

рдФрд░ рдЗрд╕реЗ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ map рдлрд╝рдВрдХреНрд╢рди рдкрд░ рд▓рд╛рдЧреВ map :
 curry_map_2 = curry_2(map) @curry_map_2 def twice_or_increase(n): if n % 2 == 0: n += 1 if n % 3: n *= 2 return n print(*twice_or_increase(range(10))) # 2 2 3 3 10 10 14 14 9 9 print(*twice_or_increase(range(30))) # 2 2 3 3 10 10 14 14 9 9 22 22 26 26 15 15 34 34 38... 

рд╣рд╛рдВ, рд╣рд╛рдВ, рдореИрдВрдиреЗ рдбреЗрдХреЛрд░реЗрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рдШреБрдорд╛рд╡рджрд╛рд░ map рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдерд╛ рдФрд░ рдорд▓реНрдЯреА-рд▓рд╛рдЗрди рд▓реИрдореНрдмреНрдбрд╛ рдХреА рдХрдореА рдХреЛ рдСрдлрд╕реЗрдЯ рдХрд┐рдпрд╛ рдерд╛ред

рд▓реЗрдХрд┐рди рд╕рднреА рдлрд╝рдВрдХреНрд╢рдВрд╕ рдореЗрдВ 2 рддрд░реНрдХ рдирд╣реАрдВ рд╣реЛрддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЖрдВрд╢рд┐рдХ , curry_n рдФрд░ рдереЛрдбрд╝реА рд╕реА рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ curry_n рдлрд╝рдВрдХреНрд╢рди рдХрд░реЗрдВрдЧреЗ:
 from functools import partial def curry_n(fn, n): def aux(x, n=None, args=None): #   args = args + [x] #       return partial(aux, n=n - 1, args=args) if n > 1 else fn(*args) #     ,   aux       return partial(aux, n=n, args=[]) 

рдФрд░ рдПрдХ рдмрд╛рд░ рдлрд┐рд░, map рд▓рд╛рдЧреВ рд╣реЛрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди 3 рддрд░реНрдХ рдХреЗ рд╕рд╛рде:
 curry_3_map = curry_n(map, 3) 

рдФрд░ рд╣рдо рд╕реВрдЪреА рдЖрдЗрдЯрдо 1.10 рдЖрдЗрдЯрдо рд╕реВрдЪреА рдореЗрдВ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдХрд╛рд░реНрдп рдХрд░реЗрдВрдЧреЗ:
 sum_arrays = curry_3_map(lambda x, y: x + y) sum_with_range_10 = sum_arrays(range(10)) print(*sum_with_range_10(range(100, 0, -10))) # 100 91 82 73 64 55 46 37 28 19 print(*sum_with_range_10(range(10))) # 0 2 4 6 8 10 12 14 16 18 

рдЪреВрдБрдХрд┐ curry_2 рдХрд╛ рдПрдХ рд╡рд┐рд╢реЗрд╖ рдорд╛рдорд▓рд╛ рд╣реИ, рдЖрдк рдпрд╣ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
 curry_2 = partial(curry_n, n=2) 

рдФрд░ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЗрд╕реЗ filter рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд▓рд╛рдЧреВ рдХрд░реЗрдВ:
 curry_filter = curry_2(filter) only_odd = curry_filter(lambda n: n % 2) print(*only_odd(range(10))) # 1 3 5 7 9 print(*only_odd(range(-10, 0, 1))) # -9 -7 -5 -3 -1 

рдкреИрдЯрд░реНрди рдорд┐рд▓рд╛рди


рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдирдореВрдиреЛрдВ рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рдХреЗ рд▓рд┐рдП рд╕реВрдЪрд┐рдпреЛрдВ рдпрд╛ рдЕрдиреНрдп рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рдзрд┐ред

рдкреИрдЯрд░реНрди рдорд┐рд▓рд╛рди рдЬреЛ рдореБрдЭреЗ sml рдореЗрдВ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдкрд╕рдВрдж рд╣реИ рдФрд░ рдЕрдЬрдЧрд░ рдореЗрдВ рд╕рдмрд╕реЗ рдЦрд░рд╛рдм рд╣реИред
рд╣рдо рдПрдХ рд▓рдХреНрд╖реНрдп рдХреЗ рд╕рд╛рде рдЖрдПрдВрдЧреЗ - рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП:

рдЖрдЗрдП рдЗрд╕рдХреЗ "рдлреЗрдВрдХ" рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд╣рд╛рдпрдХ рдЕрдкрд╡рд╛рдж рдФрд░ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рдПрдВ, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╣рдо рддрдм рдХрд░реЗрдВрдЧреЗ рдЬрдм рддреБрд▓рдирд╛ рдкрд╛рд╕ рдирд╣реАрдВ рд╣реЛрдЧреА:
 class NotMatch(Exception): """Not match""" def not_match(x): raise NotMatch(x) 

рдФрд░ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдЬреЛ рдПрдХ рдЪреЗрдХ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рдпрд╛ рдПрдХ рдЕрдкрд╡рд╛рдж рдлреЗрдВрдХрддрд╛ рд╣реИ:
 match = lambda check, obj: obj if check(obj) else not_match(obj) match_curry = curry_n(match, 2) 

рдЕрдм рд╣рдо рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреА рдЬрд╛рдБрдЪ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ:
 instance_of = lambda type_: match_curry(lambda obj: isinstance(obj, type_)) 

рддреЛ int :
 is_int = instance_of(int) print(is_int(2)) # 2 try: is_int('str') except NotMatch: print('not int') # not int 

рд╕реВрдЪреА рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреА рдЬрд╛рдБрдЪ рдмрдирд╛рдПрдБ, рдкреНрд░рддреНрдпреЗрдХ рддрддреНрд╡ рдХреА рдЬрд╛рдБрдЪ:
 is_array_of = lambda matcher: match_curry(lambda obj: all(map(matcher, obj))) 

рдФрд░ рдлрд┐рд░ int :
 is_array_of_int = is_array_of(is_int) print(is_array_of_int([1, 2, 3])) # 1 2 3 try: is_array_of_int('str') except NotMatch: print('not int') # not int 

рдФрд░ рдЕрдм рдЗрд╕реА рддрд░рд╣ str :
 is_str = instance_of(str) is_array_of_str = is_array_of(is_str) 

рд╣рдо рдПрдХ рдлрд╝рдВрдХреНрд╢рди рднреА рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ рдЬреЛ рдЕрдкрдирд╛ рддрд░реНрдХ рджреЗрддрд╛ рд╣реИ, idempotent =)
 identity = lambda x: x print(identity(10)) # 10 print(identity(20)) # 20 

рдФрд░ рдПрдХ рдЦрд╛рд▓реА рд╕реВрдЪреА рдХреА рдЬрд╛рдБрдЪ рдХрд░реЗрдВ:
 is_blank = match_curry(lambda xs: len(xs) == 0) print(is_blank([])) # [] try: is_blank([1, 2, 3]) except NotMatch: print('not blank') # not blank 

рдЕрдм рд╣рдо рд╕реВрдЪреА рдХреЛ рдкрд╣рд▓реЗ рддрддреНрд╡ рдореЗрдВ рдФрд░ рд╢реЗрд╖ рдХреЛ "рдЪреЗрдХ" рдХреЗ рдЙрдкрдпреЛрдЧ рд╕реЗ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдлрдВрдХреНрд╢рди рдмрдирд╛рдПрдВрдЧреЗ:
 def hd_tl(match_x, match_xs, arr): x, *xs = arr return match_x(x), match_xs(xs) hd_tl_partial = lambda match_x, match_xs: partial(hd_tl, match_x, match_xs) 

рдФрд░ identity рд╕рд╛рде рд╕рдмрд╕реЗ рд╕рд░рд▓ рдЙрджрд╛рд╣рд░рдг рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:
 hd_tl_identity = hd_tl_partial(identity, identity) print(hd_tl_identity(range(5))) # 0 [1, 2, 3, 4] 

рдФрд░ рдЕрдм рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЗ рд╕рд╛рде:
 hd_tl_ints = hd_tl_partial(is_int, is_array_of_int) print(hd_tl_ints(range(2, 6))) # 2 [3, 4, 5] try: hd_tl_ints(['str', 1, 2]) except NotMatch: print('not ints') # not ints 


рдФрд░ рдЕрдм рдлрд╝рдВрдХреНрд╢рди рд╣реА, рдЬреЛ рд╕рднреА рдЪреЗрдХ рдкрд░ рдкреБрдирд░рд╛рд╡реГрддрд┐ рдХрд░реЗрдЧрд╛ред рд╡рд╣ рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИ:
 def pattern_match(patterns, args): for pattern, fnc in patterns: try: return fnc(pattern(args)) except NotMatch: continue raise NotMatch(args) pattern_match_curry = curry_n(pattern_match, 2) 



рд▓реЗрдХрд┐рди рдлрд┐рд░ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЕрд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ рдФрд░ рдЗрд╕рдХреЗ рд▓рд┐рдП рдХреЛрд╖реНрдардХ рдХреА рдПрдХ рдкреВрд░реА рджреБрдирд┐рдпрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдЬрд┐рд╕ рдлрд╝рдВрдХреНрд╢рди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рд╡рд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛:
 sum_or_multiply = pattern_match_curry(( (hd_tl_partial(identity, is_blank), lambda arr: arr[0]), # x::[] -> x (hd_tl_ints, lambda arr: arr[0] * sum_or_multiply(arr[1])), # x::xs -> x * sum_or_multiply (xs)  type(x) == int (hd_tl_partial(is_str, is_array_of_str), lambda arr: arr[0] + sum_or_multiply(arr[1])), # x::xs -> x + sum_or_multiply (xs)  type(x) == str )) 

рдЕрдм рдЗрд╕реЗ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдореЗрдВ рджреЗрдЦреЗрдВ:
 print(sum_or_multiply(range(1, 10))) # 362880 print(sum_or_multiply(['a', 'b', 'c'])) # abc 

рд╣реБрд░реНрд░реЗ! рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ =)

рдкреНрд░рддреНрдпрд╛рд╡рд░реНрддрди


рд╕рднреА рд╢рд╛рдВрдд рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ, рдХрдард┐рди рд▓реЛрдЧ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ map рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ, рд╣рдо рдмрджрддрд░ рдХреНрдпреЛрдВ рд╣реИрдВ? рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдХреИрд╕реЗ рдорд┐рд▓рд╛рди рдкреИрдЯрд░реНрди:
 r_map = lambda fn, arg: pattern_match(( (hd_tl_partial(identity, is_blank), lambda arr: [fn(arr[0])]), # x::[] -> fn(x) ( hd_tl_partial(identity, identity), lambda arr: [fn(arr[0])] + r_map(fn, arr[1]) # x::xs -> fn(x)::r_map(fn, xs) ), ), arg) print(r_map(lambda x: x**2, range(10))) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] 

рдЕрдм рдХрд░реА:
 r_map_curry = curry_n(r_map, 2) twice = r_map_curry(lambda x: x * 2) print(twice(range(10))) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18] try: print(twice(range(1000))) except RuntimeError as e: print(e) # maximum recursion depth exceeded in comparison 

рдХреБрдЫ рдЧрд▓рдд рд╣реЛ рдЧрдпрд╛ рдерд╛, рдкреВрдВрдЫ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЛред
рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, None рдкрд░ "рдЪреЗрдХ" рдмрдирд╛рдПрдВ:
 is_none = match_curry(lambda obj: obj is None) 

рдФрд░ рдПрдХ рдЬреЛрдбрд╝реЗ рдХреА рдЬрд╛рдБрдЪ рдХрд░реЗрдВ:
 pair = lambda match_x, match_y: lambda arr: (match_x(arr[0]), match_y(arr[1])) 

рдФрд░ рдЕрдм рдЦреБрдж map :
 def r_map_tail(fn, arg): aux = lambda arg: pattern_match(( (pair(identity, is_none), lambda arr: aux([arr[0], []])), #   None,   [] ( pair(hd_tl_partial(identity, is_blank), identity), lambda arr: arr[1] + [fn(arr[0][0])] #  (x::[], acc),     fn(x)    ), ( pair(hd_tl_partial(identity, identity), identity), lambda arr: aux([arr[0][1], arr[1] + [fn(arr[0][0])]]) #  (x::xs, acc),      xs   + fn(x) ), ), arg) return aux([arg, None]) 

рдЕрдм рд╣рдорд╛рд░реЗ рдЪрдорддреНрдХрд╛рд░ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЛ:
 r_map_tail_curry = curry_n(r_map_tail, 2) twice_tail = r_map_tail_curry(lambda x: x * 2) print(twice_tail(range(10))) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18] try: print(twice_tail(range(10000))) except RuntimeError as e: print(e) # maximum recursion depth exceeded 

рдпрд╣ рджреБрд░реНрднрд╛рдЧреНрдп рд╣реИ - рдЕрдЬрдЧрд░ рдкреВрдВрдЫ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХрд╛ рдЕрдиреБрдХреВрд▓рди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдЕрдм рдмреИрд╕рд╛рдЦреА рд╣рдорд╛рд░реА рд╕рд╣рд╛рдпрддрд╛ рдХреЗ рд▓рд┐рдП рдЖрдПрдЧреА:
 def tail_fnc(fn): called = False calls = [] def run(): while len(calls): #       res = fn(*calls.pop()) return res def call(*args): nonlocal called calls.append(args) #     if not called: #    ,   -   called = True return run() return call 

рдЕрдм рд╣рдо рдЗрд╕ map рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ:
 def r_map_really_tail(fn, arg): aux = tail_fnc(lambda arg: pattern_match(( #    (pair(identity, is_none), lambda arr: aux([arr[0], []])), #   None,   [] ( pair(hd_tl_partial(identity, is_blank), identity), lambda arr: arr[1] + [fn(arr[0][0])] #  (x::[], acc),     fn(x)    ), ( pair(hd_tl_partial(identity, identity), identity), lambda arr: aux([arr[0][1], arr[1] + [fn(arr[0][0])]]) #  (x::xs, acc),      xs   + fn(x) ), ), arg)) return aux([arg, None]) r_map_really_tail_curry = curry_n(r_map_really_tail, 2) twice_really_tail = r_map_really_tail_curry(lambda x: x * 2) print(twice_really_tail(range(1000))) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18... 

рдЕрдм рдпрд╣ рдХрд╛рдо рдХрд┐рдпрд╛ =)

рдЗрддрдирд╛ рдбрд░рд╛рд╡рдирд╛ рдирд╣реАрдВ


рдпрджрд┐ рд╣рдо рдЕрдкрдиреЗ рднрдпрд╛рдирдХ рдкреИрдЯрд░реНрди рдорд┐рд▓рд╛рди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рднреВрд▓ рдЬрд╛рддреЗ рд╣реИрдВ, рддреЛ рдкреБрдирд░рд╛рд╡рд░реНрддреА map рдХреЛ рдХрд╛рдлреА рд╕рдЯреАрдХ рд░реВрдк рд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:
 def tail_r_map(fn, arr_): @tail_fnc def aux(arr, acc=None): x, *xs = arr if xs: return aux(xs, acc + [fn(x)]) else: return acc + [fn(x)] return aux(arr_, []) curry_tail_r_map = curry_2(tail_r_map) 


рдФрд░ рдЗрд╕реЗ рд╕реВрдЪреА рдХреЗ рд╕рднреА рд╡рд┐рд╖рдо рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЛ 2 рд╕реЗ рдЧреБрдгрд╛ рдХрд░реЗрдВ:
 @curry_tail_r_map def twice_if_odd(x): if x % 2 == 0: return x * 2 else: return x print(twice_if_odd(range(10000))) # [0, 1, 4, 3, 8, 5, 12, 7, 16, 9, 20, 11, 24, 13, 28, 15, 32, 17, 36, 19... 

рдпрд╣ рдзреАрд░реЗ-рдзреАрд░реЗ рдФрд░ рдЕрдирд╛рд╡рд╢реНрдпрдХ рд░реВрдк рд╕реЗ рдХрд╛рдлреА рд╕рд╛рдл рд╣реЛ рдЧрдпрд╛ред рдХрдо рд╕реЗ рдХрдо рдЧрддрд┐ рдХреЗ рдХрд╛рд░рдгред рд╡рд┐рднрд┐рдиреНрди map рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреЗ рдкреНрд░рджрд░реНрд╢рди рдХреА рддреБрд▓рдирд╛ рдХрд░реЗрдВ:
 from time import time checker = lambda x: x ** 2 + x limit = 10000 start = time() xs = [checker(x) for x in range(limit)][::-1] print('inline for:', time() - start) start = time() xs = list(map(checker, range(limit)))[::-1] print('map:', time() - start) calculate = curry_tail_r_map(checker) start = time() xs = calculate(range(limit))[::-1] print('r_map without pattern matching:', time() - start) calculate = r_map_really_tail_curry(checker) start = time() xs = calculate(range(limit))[::-1] print('r_map with pattern matching:', time() - start) 

рдЬрд┐рд╕рдХреЗ рдмрд╛рдж рд╣рдореЗрдВ рдорд┐рд▓рддрд╛ рд╣реИ:
рдЗрдирд▓рд╛рдЗрди рдХреЗ рд▓рд┐рдП: 0.011110067367553711
рдирдХреНрд╢рд╛: 0.011012554168701172
рдкреИрдЯрд░реНрди рдорд┐рд▓рд╛рди рдХреЗ рдмрд┐рдирд╛ r_map: 3.7527310848236084
рдкреИрдЯрд░реНрди рдорд┐рд▓рд╛рди рдХреЗ рд╕рд╛рде r_map: 5.926968812942505
рдмрд┐рд▓реНрдЯ-рдЗрди рдореИрдк рдФрд░ рд╕рдмрд╕реЗ рддреЗрдЬрд╝ рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рдкреИрдЯрд░реНрди рдорд┐рд▓рд╛рди рд╡рд┐рдХрд▓реНрдк рд╕рдмрд╕реЗ рдзреАрдорд╛ рдирд┐рдХрд▓рд╛ред

рдирд┐рд╖реНрдХрд░реНрд╖


рдЗрд╕ рд▓реЗрдЦ рд╕реЗ, рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдореЗрдВ, рд╢рд╛рдпрдж рдХреЗрд╡рд▓ рдХрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдмрд╛рдХреА рдпрд╛ рддреЛ рдЕрдкрдардиреАрдп рд╣реИ рдпрд╛ рдПрдХ рдмреНрд░реЗрдХ рдмрд╛рдЗрдХ =)
рд╕рднреА рдЙрджрд╛рд╣рд░рдг github рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реИрдВред

Source: https://habr.com/ru/post/In193920/


All Articles