[pypy-commit] pypy default: merge heads

gutworth noreply at buildbot.pypy.org
Wed Oct 12 17:22:29 CEST 2011


Author: Benjamin Peterson <benjamin at 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):


More information about the pypy-commit mailing list