Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 # Use of this source code is governed by a BSD-style license that can be | |
| 3 # found in the LICENSE file. | |
| 4 | |
|
Sharu Jiang
2016/12/02 23:47:18
nit: 2 empty lines.
wrengr
2016/12/05 18:50:45
Done.
| |
| 5 class Function(object): | |
| 6 """Base class for mathematical functions. | |
| 7 | |
| 8 The ``callable`` interface is sufficient for when you only ever need to | |
| 9 invoke a function. But many times we want to have more information about | |
| 10 the function, such as getting its domain or range or knowing whether | |
| 11 it's sparse. In addition, we often want to adjust the computational | |
| 12 representation of functions (e.g., adding memoization). So this class | |
| 13 provides a base class for functions supporting all these sorts of | |
| 14 operations in addition to being callable. | |
| 15 """ | |
| 16 def __init__(self, f): | |
| 17 self._f = f | |
| 18 | |
| 19 # TODO(wrengr): can we remove the extra indirection somehow? | |
| 20 def __call__(self, x): | |
|
Sharu Jiang
2016/12/02 23:47:18
So we assume all the Funtions take only one parame
wrengr
2016/12/05 18:50:45
Yes, we assume a single argument for the sake of s
| |
| 21 return self._f(x) | |
| 22 | |
| 23 def map(self, g): | |
| 24 """Return a new function that applies ``g`` after ``self``. | |
| 25 | |
| 26 Args: | |
| 27 g (callable): the function to post-compose. | |
| 28 | |
| 29 Returns: | |
| 30 An object of the same type as ``self`` which computes ``lambda x: | |
| 31 g(self(x))``. N.B., although mathematically we have the equivalence: | |
| 32 ``SomeFunction(f).map(g) == SomeFunction(lambda x: g(f(x)))``; | |
| 33 operationally the left- and right-hand sides may differ. For | |
| 34 example, with the ``MemoizedFunction`` class, the left-hand side | |
| 35 will memoize the intermediate ``f(x)`` values whereas the right-hand | |
| 36 side will not. If that's not desired, be sure to call ``Unmemoize`` | |
| 37 (or similar type coercions) before mapping. | |
| 38 """ | |
| 39 return self.__class__(lambda x: g(self(x))) | |
| 40 | |
| 41 | |
| 42 class MemoizedFunction(Function): | |
| 43 """A function which memoizes its value for all arguments.""" | |
| 44 def __init__(self, f): | |
| 45 super(MemoizedFunction, self).__init__(f) | |
| 46 self._memos = {} | |
| 47 | |
| 48 def _ClearMemos(self): | |
| 49 """Discard all memoized results of this function.""" | |
| 50 self._memos = {} | |
| 51 | |
| 52 # TODO(wrengr): can we remove the extra indirection somehow? | |
|
Martin Barbella
2016/12/02 23:50:21
I'd be surprised, especially for this case. Probab
inferno
2016/12/05 00:02:10
Are you planning to work on these TODOs in next f
wrengr
2016/12/05 18:50:45
Yes. Though I can file a bug instead if desired
| |
| 53 def __call__(self, x): | |
| 54 try: | |
|
inferno
2016/12/05 00:02:10
Docstring
wrengr
2016/12/05 18:50:45
saying what? __call__ is a standard part of Python
| |
| 55 return self._memos[x] | |
| 56 except KeyError: | |
| 57 fx = self._f(x) | |
| 58 self._memos[x] = fx | |
| 59 return fx | |
| OLD | NEW |