nodes: 0, module; 1, function_definition; 2, function_name:fixed_point; 3, parameters; 4, block; 5, identifier:is_zero; 6, identifier:plus; 7, identifier:minus; 8, identifier:f; 9, identifier:x; 10, expression_statement; 11, decorated_definition; 12, return_statement; 13, comment:"""
      Get the least fixed point when it can be computed piecewise.
  
      .. testsetup::
  
          from proso.func import fixed_point
  
      .. doctest::
  
          >>> sorted(fixed_point(
          ...    is_zero=lambda xs: len(xs) == 0,
          ...    plus=lambda xs, ys: xs + ys,
          ...    minus=lambda xs, ys: [x for x in xs if x not in ys],
          ...    f=lambda xs: [x + 1 for x in xs if x < 10],
          ...    x=[0, 5, 8]
          ... ))
          [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  
      Args:
          is_zero: function returning True if the given value is zero
          plus: function taking two values and returning their addition
          minus: function taking two values and returning ther difference
          f: function computing the expected value
          x: initial value
  
      Returns:
          The least fixed point.
      """; 14, decorator; 15, function_definition; 16, call; 17, identifier:memo_Y; 18, function_name:_fixed_point; 19, parameters; 20, block; 21, identifier:_fixed_point; 22, argument_list; 23, identifier:fixed_point_fun; 24, function_definition; 25, return_statement; 26, identifier:x; 27, call; 28, function_name:__fixed_point; 29, parameters; 30, block; 31, identifier:__fixed_point; 32, identifier:f; 33, argument_list; 34, identifier:collected; 35, identifier:new; 36, expression_statement; 37, if_statement; 38, return_statement; 39, identifier:x; 40, assignment; 41, call; 42, block; 43, call; 44, identifier:diff; 45, call; 46, identifier:is_zero; 47, argument_list; 48, return_statement; 49, identifier:fixed_point_fun; 50, argument_list; 51, identifier:minus; 52, argument_list; 53, identifier:diff; 54, identifier:collected; 55, call; 56, call; 57, identifier:new; 58, identifier:collected; 59, identifier:plus; 60, argument_list; 61, identifier:f; 62, argument_list; 63, identifier:collected; 64, identifier:diff; 65, identifier:diff
code: def fixed_point(is_zero, plus, minus, f, x):
      """
      Get the least fixed point when it can be computed piecewise.
  
      .. testsetup::
  
          from proso.func import fixed_point
  
      .. doctest::
  
          >>> sorted(fixed_point(
          ...    is_zero=lambda xs: len(xs) == 0,
          ...    plus=lambda xs, ys: xs + ys,
          ...    minus=lambda xs, ys: [x for x in xs if x not in ys],
          ...    f=lambda xs: [x + 1 for x in xs if x < 10],
          ...    x=[0, 5, 8]
          ... ))
          [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  
      Args:
          is_zero: function returning True if the given value is zero
          plus: function taking two values and returning their addition
          minus: function taking two values and returning ther difference
          f: function computing the expected value
          x: initial value
  
      Returns:
          The least fixed point.
      """
  
      @memo_Y
      def _fixed_point(fixed_point_fun):
          def __fixed_point(collected, new):
              diff = minus(new, collected)
              if is_zero(diff):
                  return collected
              return fixed_point_fun(plus(collected, diff), f(diff))
          return __fixed_point
  
      return _fixed_point(x, f(x))