1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 """C{squish [SQUISH_OP ...]}
19
20 Each input sequence is reduced to a single value, using C{SQUISH_OP}
21 to combine the values. C{SQUISH_OP} 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{SQUISH_OP}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{SQUISH_OP} is provided, then C{+} is assumed.
47 """
48
49 import types
50
51 import osh.core
52 from osh.function import _Function
53
54
57
58
60 """Each input sequence is reduced to a single value. Elements
61 of the input sequence are combined using a C{squish_op}, a binary function
62 that can be used for reduction, i.e. a binary associative function such as addition,
63 but not subtraction, (because x + y = y + x, but x - y != y - x).
64 If input sequences contain nested sequences, then multiple C{squish_op}s
65 can be provided, to do multiple reductions at once. The squish_op can be a function-valued
66 expression, a string function expression (e.g. C{'x, y: x + y'}), or a string describing
67 a binary associative operator, specifically one of: C{+, *, ^, &, |, and, or}.
68 """
69 return _Squish().process_args(*squish_ops)
70
72
73 _squisher = None
74
75
76
77
80
81
82
83
86
88 args = self.args()
89 squish_ops = []
90 while args.has_next():
91 arg = args.next()
92 if type(arg) in [types.FunctionType, types.BuiltinFunctionType]:
93 op = _Function(arg)
94 elif isinstance(arg, str):
95 f = operator_to_function(arg)
96 if f:
97 op = _Function(f)
98 else:
99 op = _Function(arg)
100 squish_ops.append(op)
101 if len(squish_ops) == 0:
102 squish_ops.append(_Function(lambda x, y: x + y))
103 if len(squish_ops) == 1:
104 self._squisher = _object_squisher(squish_ops[0])
105 else:
106 self._squisher = _sequence_squisher(squish_ops)
107
109 squished = self._squisher(object)
110 self.send(squished)
111
114
116 def all_ops(x, y):
117 return [ops[i](x[i], y[i]) for i in xrange(len(ops))]
118 return lambda input: reduce(all_ops, input)
119
121 if op == '+':
122 f = lambda x, y: x + y
123 elif op == '*':
124 f = lambda x, y: x * y
125 elif op == '^':
126 f = lambda x, y: x ^ y
127 elif op == '&':
128 f = lambda x, y: x & y
129 elif op == '|':
130 f = lambda x, y: x | y
131 elif op == 'and':
132 f = lambda x, y: x and y
133 elif op == 'or':
134 f = lambda x, y: x or y
135 elif op == 'max':
136 f = lambda x, y: max(x, y)
137 elif op == 'min':
138 f = lambda x, y: min(x, y)
139 else:
140 f = None
141 return f
142