Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Snake Snacks: Function Composition, The Dumb Way

Avatar for Brian Hicks Brian Hicks
September 07, 2017

Snake Snacks: Function Composition, The Dumb Way

Avatar for Brian Hicks

Brian Hicks

September 07, 2017
Tweet

More Decks by Brian Hicks

Other Decks in Technology

Transcript

  1. WHAT WE WANT def inc(n): return n + 1 def

    double(n): return n * 2 # in the REPL >>> (inc >> double)(2) 6 >>> (double >> inc)(2) 5
  2. DUNDER METHODS, THE NICE WAY class Boss(object): def __init__(self, name):

    self.name = name def __str__(self): return self.name def __repr__(self): return '<%s: %s>' % (self.__class__.__name__, self) def introduce(self): return "Please meet my boss, %s" % self
  3. DUNDER METHODS, THE NICE WAY >>> b = Boss("Michael Scott")

    >>> b <Boss: Michael Scott> >>> str(b) 'Michael Scott' >>> b.introduce() 'Please meet my boss, Michael Scott'
  4. DECORATORS, THE NICE WAY def memoize(fn): cache = {} def

    inner(*args, **kwargs): key = str((args, kwargs)) if key not in cache: cache[key] = fn(*args, **kwargs) return cache[key] return inner
  5. DECORATORS, THE NICE WAY @memoize def hype(stuff): return "OH YEAH,

    IT'S %s" % stuff.upper() # is the same as... hype = memoize(lambda stuff: "OH YEAH, IT'S %s" % stuff.upper())
  6. DECORATORS, THE NICE WAY >>> hype("cheese") "OH YEAH, IT'S CHEESE"

    >>> hype("a moose") "OH YEAH, IT'S A MOOSE"
  7. BUT… OBJECTS! class memoize(object): def __init__(self, fn): self.cache = {}

    self.fn = fn def __call__(self, *args, **kwargs): key = str((args, kwargs)) if key not in self.cache: self.cache[key] = self.fn(*args, **kwargs) return self.cache[key]
  8. BUT… OBJECTS! >>> hype("cheese") "OH YEAH, IT'S CHEESE" >>> hype("a

    moose") "OH YEAH, IT'S A MOOSE" >>> hype.cache {"(('a moose',), {})": "OH YEAH, IT'S A MOOSE", "(('cheese',), {})": "OH YEAH, IT'S CHEESE"}
  9. __gt__ class ChessPlayer(object): def __init__(self, name, elo): self.name = name

    self.elo = elo def __gt__(self, other): return self.elo > other.elo
  10. __gt__ >>> carlsen = ChessPlayer("Carlsen, Magnus", 2827) >>> almasi =

    ChessPlayer("Almasi, Zoltan", 2707) >>> carlsen > almasi True >>> carlsen < almasi False
  11. OUR FIRST TRY! class composable(object): def __init__(self, fn): self.fn =

    fn def __call__(self, *args, **kwargs): return self.fn(*args, **kwargs) def __gt__(self, other): return self.__class__( lambda *args, **kwargs: other(self.fn(*args, **kwargs)) )
  12. OUR FIRST TRY! @composable def inc(n): return n + 1

    @composable def double(n): return n * 2 @composable def triple(n): return n * 3
  13. OUR FIRST TRY! ! 1 > 2 > 3 #

    is equivalent to 1 > 2 and 2 > 3 # NOT (1 > 2) > 3
  14. __rshift__ TO THE RESCUE! class composable(object): def __init__(self, fn): self.fn

    = fn def __call__(self, *args, **kwargs): return self.fn(*args, **kwargs) def __rshift__(self, other): return self.__class__( lambda *args, **kwargs: other(self.fn(*args, **kwargs)) )
  15. __rshift__ TO THE RESCUE! >>> (inc >> double)(2) 6 >>>

    (double >> inc)(2) 5 >>> (inc >> double >> triple)(2) 18