Package osh :: Package command :: Module squish
[frames] | no frames]

Source Code for Module osh.command.squish

  1  # osh 
  2  # Copyright (C) Jack Orenstein <jao@geophile.com> 
  3  # 
  4  # This program is free software; you can redistribute it and/or modify 
  5  # it under the terms of the GNU General Public License as published by 
  6  # the Free Software Foundation; either version 2 of the License, or 
  7  # (at your option) any later version. 
  8  # 
  9  # This program is distributed in the hope that it will be useful, 
 10  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 11  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 12  # GNU General Public License for more details. 
 13  # 
 14  # You should have received a copy of the GNU General Public License 
 15  # along with this program; if not, write to the Free Software 
 16  # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 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  # CLI 
57 -def _squish():
58 return _Squish()
59 60 # API
61 -def squish(*squish_ops):
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
73 -class _Squish(osh.core.Op):
74 75 _squisher = None 76 77 78 # object interface 79
80 - def __init__(self):
81 osh.core.Op.__init__(self, '', (0, None))
82 83 84 # BaseOp interface 85
86 - def doc(self):
87 return __doc__
88
89 - def setup(self):
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
103 - def receive(self, object):
104 squished = self._squisher(object) 105 self.send(squished)
106
107 -def _object_squisher(op):
108 return lambda input: reduce(op, input)
109
110 -def _sequence_squisher(ops):
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