Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I think my answer: I have no idea what multi-line lambdas are, probably explains why I find Reflex (or Rio/Streamlit, etc) amazing, haha

For a person with zero front-end knowledge, it's a game changer.



In JavaScript you can do this:

    const f = (x, y) => {
      const z = x + y;
      const w = z * 2;
      return z - w + x;
    };
In Python, you cannot do this:

    f = (
      lambda x, y:
        z = x + y;
        w = z * 2;
        return z - w + x;
    )
Instead, you need to pull it out into a def:

    def f(x, y):
      z = x + y;
      w = z * 2;
      return z - w + x;
Sometimes, this is no big deal. But other times, it's damn annoying; the language forces you to lay out your code in a less intuitive way for no obvious benefit.


Actually you can. If you really want a multi-line lambda with your example...

```f = lambda x, y: [ z := x + y, w := z 2, z - w + x, ][-1]```

* That version does look strange, as it uses a list in order to get that last calculation. But I often use lambdas to check results in parametrized tests, and they naturally spread to multiple lines without the list hack since they're chains of comparisons.


Using a list combined with the walrus operator is a clever hack, but it's nice to not be limited to expressions. In JS you can define the equivalent of a multi-line lambda function with any number of statements (which is helpful when you're passing a function as a callback e.g. in a React hook).


It may be nice in the moment, but there's usually regret a few weeks/months down the line when trying to read that code, or angst for the next developer. There isn't that much more effort to just create a normal def to hold that increase in complexity suggested by the need for multiple statements. That's why functions were invented in the first place.


If a callback function gets really unwieldy then you should probably extract it from the call site and define it elsewhere, but that should happen because you decided to, not because the language's limitations coerced you into doing it. The lambda restrictions in Python are probably due to the complexities of parsing indentation based languages, and the clean code argument is just a helpful rationalization. I've never woken up in angst over the fact that I wrote a callback function with two statements in it.


There may be a few restrictions due to complexity, but lambdas isn't one. This is about decent and sane design choice[0] for readability.

[0] https://www.artima.com/weblogs/viewpost.jsp?thread=147358


From the blog post you linked: "But the complexity of any proposed solution for this puzzle is immense, to me: it requires the parser (or more precisely, the lexer) to be able to switch back and forth between indent-sensitive and indent-insensitive modes, keeping a stack of previous modes and indentation level."

He's saying exactly what I said: that parsing (or more precisely lexing) makes the problem complex, because Python uses indentation semantically. He then rationalizes avoiding the implementation complexity with a gut feeling: "But none of that takes away my gut feeling".


You see it as a rationalization, while I see it as good sense. After all he also mentioned the "puzzles solvers" who solved the "puzzle", and some would likely have happily provided an implementation if he had given the go-ahead. But he outright refused specifically because "... a user interface can handle only so much complexity or it becomes unusable". You don't need to try putting words in his mouth after he specifically stated that maintaining a simple user interface is higher priority.

And the really ironic thing is that we wouldn't even be having this discussion now if not for this focus, because Python wouldn't have gained such popularity to the point it's also attracting more folk who would destroy what makes it so popular in the first place.


> You don't need to try putting words in his mouth after he specifically stated that maintaining a simple user interface is higher priority.

I'm not trying to put words in his mouth (I'm pretty sure I delineated his direct quotes with quotation marks). But I saw him write multiple paragraphs about the complexity of lexing multi-statement lambdas in Python due to its whitespace sensitivity, and then conclude that the user facing interface must necessarily be complex too, which just feels fallacious to me. If the complexity of the implementation doesn't factor into the design then why go through so much effort to communicate how difficult it is to lex? He compares the implementation to a "2000 step [...] infinite-dimensional" mathematical proof.

I just fundamentally don't buy the argument that one statement in a lambda is fine, but two is dark magic that needs to be removed from the call site and quarantined in a separate def, and I think if the implementation were simpler GVR wouldn't have been so diametrically opposed to the feature. Even if he outsourced the "puzzle solving" to an external contributor, no one enjoys the increased maintenance burden of a complex implementation.

Anyone who's ever written customer facing code knows what it's like to receive a seemingly simple feature request that's actually difficult to implement because of prior architectural decisions, and the "gut reaction" is to convince the user that the feature itself is bad. I hate to invoke comedy but this reminds me of the microservices meme: https://www.youtube.com/watch?v=y8OnoxKotPQ


Maybe it seems fallacious because you've removed it from clarifying context. Keep in mind that he's also against any other form of statement grouping, and so I can definitely see where ambiguity could easily arise in nesting groups of statements. You should also note the "2 or 2000..." statement is just a jab toward mathematicians.

Bit of correction: no statements and a single - arbitrarily complex - expression. An expression can be naturally delineated by parentheses; a statement stands on its own. End of the day, support for statements in a lambda would lead to a need for new symbols. Yet another thing that the user has to learn and remember, whether they're a professional software developer using the language regularly or a biology student using it for part of a one-off project. Again, the outcome of those decisions is clear today, given the general standing of the language.


> "2 or 2000..." statement is just a jab toward mathematicians.

It's a jab towards mathematicians in the context of criticizing a language proposal. He's comparing the complexity of mathematicians and their 2000 line proofs to the complexity of allowing statements in lambdas. He explicitly calls the proposal a "Rube Goldberg contraption".

> Bit of correction: no statements and a single - arbitrarily complex - expression.

I phrased it as a dichotomy between single and multiple statements because in many languages there's the concept of an 'ExpressionStatement', which is a single expression that acts as a statement. This makes the boundaries between a single statement and an expression somewhat murky. In JS for example the MDN docs have this to say about ExpressionStatements: "Apart from the dedicated statement syntaxes, you can also use almost any expression as a statement on its own." [1] GVR himself calls it "the problem of the multi-statement lambda" rather than "the problem of the statement lambda".

I don't want to get bogged down in pedantic debates about terminology though. I completely understand how it works, and said in my very first reply to you: "but it's nice to not be limited to expressions".

> End of the day, support for statements in a lambda would lead to a need for new symbols.

All it would require is a newline character. He calls this out in the blog post: "If the double colon is unpythonic, perhaps a solution could be found that uses a single colon and is still backwards compatible [...] I actually have one in mind: if there's text after the colon, it's a backwards-compatible expression lambda; if there's a newline, it's a multi-line lambda; the rest of the proposal can remain unchanged. Presto, QED, voila, etcetera."

There's absolutely nothing complex about allowing statements in lambdas from a user interface perspective (all of the complexity is in the implementation). Almost every modern language has support for this feature. Even Golang, which is perhaps the epitome of simplicity — the language that fought tooth and nail against generics, and doesn't have a ternary operator (or inline if), or string interpolation — supports defining inline callback functions with statements. There are even whitespace sensitive languages like CoffeeScript that bit the bullet and don't impose any restrictions on lambdas. The simplicity argument just feels really weak to me. At the time that blog post was written a Python user couldn't add a print statement to a lambda to debug their code. How in the world is that simple for biology students and people writing one-off projects?

[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...


That's pretty janky - I don't think it would pass review in many places!


Interesting. I see HN has mangled my code block onto 1 line and replaced a couple stars, but the fixup should be obvious...

Yes, it is, it should, and that's exactly the point. It'd look janky even without the `[-1]`, and this is what the core devs are trying to protect against. Lambdas are anonymous functions meant only to be used in places where expressions are valid, such as function parameters and return values. There's even a linter warning if you assign one to a variable. All to help reduce the creation of janky-looking code, and that's a huge benefit for most developers.


But what if I want to use lambdas for more things?

Imperative programming only gets you so far.

Maybe this is a sign that people are using Python for grander things than it was designed for?


I feel like there is something missing here. What's stopping you from using a normal def? Aside from the definition itself not being usable inline, there is nothing lambda does that def doesn't. And if you really want a definition close to the calling site, just define it there and then put the name where you want to pass it.

At the end of the day though there's really nothing to prevent you from creating janky code. Heck I saw a wild hack a couple weeks ago that allows for the creation of arbitrary custom syntax with pure Python, so you could create a multi-line lambda if you really want to that badly. But the widely adopted conventions exist for a reason.


> Aside from the definition itself not being usable inline, there is nothing lambda does that def doesn't

Being unable to position it inline is the problem.

You might not see the benefit, but many do. It prevents Python from being a good functional programming, for one thing.


There's 0 problem with doing:

    def outer(a):
        def inner(b):
            return a * b
        return inner
Though slightly longer, for most developers, it's still more grokkable (and related stack traces better) than:

    def outer(a):
        return lambda b: a * b
A very large part of Python's design is to emphasize readability for the majority. I still remember how long it took me to wrap my head around this "lambda thing" that I'd see pop up ever so often, even after a couple years of using Python. I eventually got fed up and took some time to really get to understand it. This shouldn't have to be the case for everyone reading random code.

Python is a primarily OOP-based language with functional aspects. And the design decisions that went into it are what makes it so popular today. It's not Haskell or Lisp or any of the other many that the majority avoid due to language complexity. Don't try to make it into one.


Ah I see! Thanks for elaborating! :)




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

Search: