

Multi-Line Lambdas in Python Using the With Statement - jcsalterego
http://billmill.org/multi_line_lambdas.html

======
njharman
First I don't see how naming a function '_' translates into calling it a
lambda. Also, i18n much?

Doesn't like this

    
    
      def handle_click(self):
        foo = self.flim()
        if foo:
          self.flam(foo)
    
      onClick(handle_click)
    

And thinks this mess is better

    
    
      with onClick():
        def _(self):
          foo = self.flim()
          if foo:
            self.flam()
    

My problems with 2nd include 1) it's ugly, convulted and I'd argue misusing
with, 2) by no longer having a name for flimflamfunc you loose documentation,
3) hard to reuse flimflamfunc, 4) hard to decorate, mock, dynamically replace
flimflamfunc.

Author's main dislike about first code block is "we're required to define the
function body before the place where it will be actually used." Which I think
is preferable but accept that's my opinion. They're ways to solve that which
are easier, cleaner, and more pythonic than author's proposed solution.

    
    
      def callback(onFoo):
         def inner(func):
            onFoo(func)
            return func
         return inner
    
      @callback(onClick)
      def handle_click(self):
         pass
    
    

There might be good reasons for multi-line lambdas, but I don't see any
presented here. And if we assume multi-line lambdas are awesome, this is not
an acceptable implimentation.

~~~
scott_s
To be fair, I believe problems 2), 3), 4) and your preference to define the
function before it's used would all apply to an in-language multiline lambda
as well.

------
abecedarius
Seems like you can write code in this style, if that's the style you like,
without the magical and error-prone stack/environment inspection. Like, this
example:

    
    
      with bmap([1,2,3]) as foo:
        def _(x):
          return (float(x) + 1) / 2
      print foo # [1.0, 1.5, 2.0]
    

could be done with decorators:

    
    
      def flip(f, x): # from Haskell's standard library
          return lambda y: f(y, x)
    
      @flip(map, [1,2,3])
      def result(x):
          return (float(x) + 1) / 2
      print result # [1.0, 1.5, 2.0]
    

though the way 'result' is bound is, er, unconventional.

------
apgwoz
A while back I used a similar technique to build out a "sinatra"-esque way to
declare handlers in python <http://sigusr2.net/2009/Mar/04/dispatching-with-
with.html>

~~~
jcsalterego
Speaking of Sinatra and Python, have you seen <http://github.com/breily/juno>?

~~~
apgwoz
I've not. While I'm a fan of decorators in practice, I'm not a fan of the
syntax. Part of what makes Sinatra so interesting to me is the way you define
your resources, which is what I was going for. I never actually built anything
more than a small proof of concept demo, since ultimately the value of the
technique is pretty minimal.

------
jaekwon
This is cool, I've always wondered whether Ruby blocks could be implemented in
Python, and it looks like you can get there 99% of the way. You'd still need
to implement a feature to check to see if the defined function is a generator,
and do something different for generators.

~~~
jaekwon
nm. i must be confused.

