Hacker News new | past | comments | ask | show | jobs | submit login
Multi-Line Lambdas in Python Using the With Statement (billmill.org)
44 points by jcsalterego on Aug 21, 2009 | hide | past | favorite | 11 comments



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.


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.


About these problems point by point:

1) Agreed. I'd never want to see this technique in my programs.

2) What stops you from giving it a name?

3) Putting code inline is presumably a conscious decision not to extract it into a wider scope.

4) How's it hard to decorate? For mocking and dynamically replacing, again, that goes for any inline code. Objections 3 and 4 have to argue against functions appearing in non-global scopes in general.


Totally agree. I think, more importantly than being 'ugly' or hard to mock, your second example is hard to understand. It took me too long to realize it was identical to your first example.


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.


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


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


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.


neat hack!


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.


nm. i must be confused.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: