Author: Benjamin Peterson <benja...@python.org> Branch: Changeset: r47969:da18a97b974d Date: 2011-10-12 11:22 -0400 http://bitbucket.org/pypy/pypy/changeset/da18a97b974d/
Log: merge heads diff --git a/pypy/module/__builtin__/__init__.py b/pypy/module/__builtin__/__init__.py --- a/pypy/module/__builtin__/__init__.py +++ b/pypy/module/__builtin__/__init__.py @@ -21,6 +21,8 @@ 'all' : 'app_functional.all', 'sum' : 'app_functional.sum', 'map' : 'app_functional.map', + 'reduce' : 'app_functional.reduce', + 'filter' : 'app_functional.filter', 'vars' : 'app_inspect.vars', 'dir' : 'app_inspect.dir', @@ -88,9 +90,7 @@ 'min' : 'functional.min', 'max' : 'functional.max', 'zip' : 'functional.zip', - 'reduce' : 'functional.reduce', 'reversed' : 'functional.reversed', - 'filter' : 'functional.filter', 'super' : 'descriptor.W_Super', 'staticmethod' : 'descriptor.StaticMethod', 'classmethod' : 'descriptor.ClassMethod', diff --git a/pypy/module/__builtin__/app_functional.py b/pypy/module/__builtin__/app_functional.py --- a/pypy/module/__builtin__/app_functional.py +++ b/pypy/module/__builtin__/app_functional.py @@ -98,3 +98,68 @@ result.append(func(*args)) else: return result + +sentinel = object() + +def reduce(func, sequence, initial=sentinel): + """reduce(function, sequence[, initial]) -> value + +Apply a function of two arguments cumulatively to the items of a sequence, +from left to right, so as to reduce the sequence to a single value. +For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates +((((1+2)+3)+4)+5). If initial is present, it is placed before the items +of the sequence in the calculation, and serves as a default when the +sequence is empty.""" + iterator = iter(sequence) + if initial is sentinel: + try: + initial = next(iterator) + except StopIteration: + raise TypeError("reduce() of empty sequence with no initial value") + result = initial + for item in iterator: + result = func(result, item) + return result + +def filter(func, seq): + """filter(function or None, sequence) -> list, tuple, or string + +Return those items of sequence for which function(item) is true. If +function is None, return the items that are true. If sequence is a tuple +or string, return the same type, else return a list.""" + if func is None: + func = bool + if isinstance(seq, str): + return _filter_string(func, seq, str) + elif isinstance(seq, unicode): + return _filter_string(func, seq, unicode) + elif isinstance(seq, tuple): + return _filter_tuple(func, seq) + result = [] + for item in seq: + if func(item): + result.append(item) + return result + +def _filter_string(func, string, str_type): + if func is bool and type(string) is str_type: + return string + result = [] + for i in range(len(string)): + # You must call __getitem__ on the strings, simply iterating doesn't + # work :/ + item = string[i] + if func(item): + if not isinstance(item, str_type): + raise TypeError("__getitem__ returned a non-string type") + result.append(item) + return str_type().join(result) + +def _filter_tuple(func, seq): + result = [] + for i in range(len(seq)): + # Again, must call __getitem__, at least there are tests. + item = seq[i] + if func(item): + result.append(item) + return tuple(result) \ No newline at end of file diff --git a/pypy/module/__builtin__/functional.py b/pypy/module/__builtin__/functional.py --- a/pypy/module/__builtin__/functional.py +++ b/pypy/module/__builtin__/functional.py @@ -222,90 +222,6 @@ return space.newlist(result_w) result_w.append(space.newtuple(items_w)) -def reduce(space, w_func, w_sequence, w_initial=NoneNotWrapped): - """ Apply function of two arguments cumulatively to the items of sequence, - from left to right, so as to reduce the sequence to a single value. - Optionally begin with an initial value. - """ - w_iter = space.iter(w_sequence) - if w_initial is None: - try: - w_initial = space.next(w_iter) - except OperationError, e: - if e.match(space, space.w_StopIteration): - msg = "reduce() of empty sequence with no initial value" - raise OperationError(space.w_TypeError, space.wrap(msg)) - raise - w_result = w_initial - while True: - try: - w_next = space.next(w_iter) - except OperationError, e: - if not e.match(space, space.w_StopIteration): - raise - break - w_result = space.call_function(w_func, w_result, w_next) - return w_result - -def filter(space, w_func, w_seq): - """construct a list of those elements of collection for which function - is True. If function is None, then return the items in the sequence - which are True. - """ - if space.is_true(space.isinstance(w_seq, space.w_str)): - return _filter_string(space, w_func, w_seq, space.w_str) - if space.is_true(space.isinstance(w_seq, space.w_unicode)): - return _filter_string(space, w_func, w_seq, space.w_unicode) - if space.is_true(space.isinstance(w_seq, space.w_tuple)): - return _filter_tuple(space, w_func, w_seq) - w_iter = space.iter(w_seq) - result_w = [] - none_func = space.is_w(w_func, space.w_None) - while True: - try: - w_next = space.next(w_iter) - except OperationError, e: - if not e.match(space, space.w_StopIteration): - raise - break - if none_func: - w_keep = w_next - else: - w_keep = space.call_function(w_func, w_next) - if space.is_true(w_keep): - result_w.append(w_next) - return space.newlist(result_w) - -def _filter_tuple(space, w_func, w_tuple): - none_func = space.is_w(w_func, space.w_None) - length = space.len_w(w_tuple) - result_w = [] - for i in range(length): - w_item = space.getitem(w_tuple, space.wrap(i)) - if none_func: - w_keep = w_item - else: - w_keep = space.call_function(w_func, w_item) - if space.is_true(w_keep): - result_w.append(w_item) - return space.newtuple(result_w) - -def _filter_string(space, w_func, w_string, w_str_type): - none_func = space.is_w(w_func, space.w_None) - if none_func and space.is_w(space.type(w_string), w_str_type): - return w_string - length = space.len_w(w_string) - result_w = [] - for i in range(length): - w_item = space.getitem(w_string, space.wrap(i)) - if none_func or space.is_true(space.call_function(w_func, w_item)): - if not space.is_true(space.isinstance(w_item, w_str_type)): - msg = "__getitem__ returned a non-string type" - raise OperationError(space.w_TypeError, space.wrap(msg)) - result_w.append(w_item) - w_empty = space.call_function(w_str_type) - return space.call_method(w_empty, "join", space.newlist(result_w)) - class W_Enumerate(Wrappable): def __init__(self, w_iter, w_start): _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit