1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 """C{squish [BINARY_FUNCTION ...]}
19
20 Each input sequence is reduced to a single value, using C{BINARY_FUNCTION}
21 to combine the values. C{BINARY_FUNCTION} is a binary function that can be
22 used for reduction, e.g. C{+}, C{*}, C{max}, C{min}, but not C{-} or
23 C{/}.
24
25 B{Example}: If one of the inputs is the list C{[1, 2, 3, 4]}, then::
26
27 squish +
28
29 will generate C{10} (= C{1 + 2 + 3 + 4}).
30
31 The result is exactly equivalent to what would be produced by using
32 the Python function C{map}, e.g.::
33
34 map 'list: squish(lambda a, b: a + b, list)'
35
36 If input sequences contain nested sequences, then multiple C{BINARY_FUNCTION}s
37 can be provided, to do multiple reductions at once. For example, if
38 one input sequence is C{[[10, 20, 30], [1, 100, 1000], [111, 222, 333]]}
39 then::
40
41 squish + max min
42
43 will produce C{[122, 222, 30]}. C{122} is C{10 + 1 + 111}, C{222} is C{max(20, 100, 222)}, and
44 C{30} is C{min(30, 1000, 333)}.
45
46 If no C{BINARY_FUNCTION} is provided, then C{+} is assumed.
47 """
48
49 import types
50
51 import osh.core
52 import osh.function
53
54 create_function = osh.function._create_function
55
56
59
60
62 """Each input sequence is reduced to a single value. Elements
63 of the input sequence are combined using a C{squish_op}, a binary function
64 that can be used for reduction, i.e. a binary associative function such as addition,
65 but not subtraction, (because x + y = y + x, but x - y != y - x).
66 If input sequences contain nested sequences, then multiple C{squish_op}s
67 can be provided, to do multiple reductions at once. The squish_op can be a function-valued
68 expression, a string function expression (e.g. C{'x, y: x + y'}), or a string describing
69 a binary associative operator, specifically one of: C{+, *, ^, &, |, and, or}.
70 """
71 return _Squish().process_args(*squish_ops)
72
74
75 _squisher = None
76
77
78
79
82
83
84
85
88
90 args = self.args()
91 squish_ops = []
92 while args.has_next():
93 arg = args.next()
94 op = create_function(arg)
95 squish_ops.append(op)
96 if len(squish_ops) == 0:
97 squish_ops.append(create_function(lambda x, y: x + y))
98 if len(squish_ops) == 1:
99 self._squisher = _object_squisher(squish_ops[0])
100 else:
101 self._squisher = _sequence_squisher(squish_ops)
102
104 squished = self._squisher(object)
105 self.send(squished)
106
108 return lambda input: reduce(op, input)
109
111 def all_ops(x, y):
112 return tuple([ops[i](x[i], y[i]) for i in xrange(len(ops))])
113 return lambda input: reduce(all_ops, input)
114