Live data from Hacker News

Stop writing lambda expressions in Python

treyhunner.com

131–140 of 202 posts

Re: Stop writing lambda expressions in Python

#131

Earlier quoted context omitted.

Private functions do not restrict the usage of that function to one point in the code. There's a world of difference between a coding convention - essentially a comment to say "please don't access this function from outside the current class" versus it simply being impossible to do so. And the "private" convention does not say "don't use this function at any other point except one", it says "please don't access this…

As a user of JavaScript and es6, fat arrows are only necessary if you haven't started using async and await syntax, and I found myself almost never using fat arrows after moving to async/await. Indeed naming my functions resulted in more testable and clearer code.

Hmmmm. I don't see the relationship between async/await and fat arrows.

Can you explain more about how async/await obviates the need for fat arrows?

Re: Stop writing lambda expressions in Python

#132
post #86

Earlier quoted context omitted.

Also, wouldn't the existence of a library function (#3) imply that what you're doing is either non-trivial or common enough that someone has already given the function a name? Seems like #1 is sufficient.

To give an example based on the article, I find it cumbersome to use itemgetter. I could use the library function: import operator sort(values, key=operator.itemgetter(2)) but it seems decidedly trivial and common to use a lambda: sort(values, key=lambda x: x[2])

The risk of identifier collisions with itemgetter seems really low. I've never had a problem with

  from operator import itemgetter
  sort(values, key=itemgetter(2))
The main problem is the effort of typing the import, but last time I checked itemgetter performed a bit better.

To me it depends on what I'm writing. If it's a library where performance will matter then it's the itemgetter approach. If it's a script it will be the lambda.

Re: Stop writing lambda expressions in Python

#133

Earlier quoted context omitted.

As a user of JavaScript and es6, fat arrows are only necessary if you haven't started using async and await syntax, and I found myself almost never using fat arrows after moving to async/await. Indeed naming my functions resulted in more testable and clearer code.

Hmmmm. I don't see the relationship between async/await and fat arrows. Can you explain more about how async/await obviates the need for fat arrows?

Just async is callback based.

You don't need callbacks with async/await. No callbacks, no need for fat arrow.

Re: Stop writing lambda expressions in Python

#134
post #4

all i could think of is "stop writing python". it seems to me that a lot of these problems are fundamental problems with python. i continue to not understand why anybody likes python the language. the fact that creating a function with lambda versus the normal way is different is bonkers. for example, in f# (and other sane languages), the following are identical: let test1 = fun x -> x * x let test2 x = x * x both re…

Guido seemingly has a strong distaste for functional ideas, so anything that comes from that paradigm ends up getting an almost half-assed implementation. See also: map and filter being the only 2 other functions implemented and both of them being less performant than their imperative equivalents; outright denial of any attempt at TCO because "Guido doesn't like recursion".

> outright denial of any attempt at TCO because "Guido doesn't like recursion".

No, don’t ignore problems of TCO by saying “guys don’t like functional programimg”. Guido cleary states why he doesn’t like it: [1]. Even though TCO is one of the ES6 standard, TCO also is largely denied by JS implementors (Firefox, Chrome, and Edge devs) because of the similar reasons. As a result, Safari is the only browser that supports TCO. [2][3] And Rust team is not eager to introduce TCO [4].

[1]: http://neopythonic.blogspot.com/2009/04/tail-recursion-elimi...

[2]: https://www.chromestatus.com/feature/5516876633341952

[3]: https://github.com/kangax/compat-table/issues/819

[4]: https://github.com/rust-lang/rfcs/pull/1888

Re: Stop writing lambda expressions in Python

#135

Earlier quoted context omitted.

"i continue to not understand why anybody likes python the language." As someone who has had a lifetime of on-off relationships with attempting to become a competent programmer, (BASIC, assembler, C, Pascal, Visual Basic, C++ and others that I can no longer remember), Python is the only language that has helped me become anywhere near useful or proficient as a programmer. I've managed to build a couple of -genuinely…

> I'm not going to be writing 3D games or real-time audio apps in it, but for what I've been trying to do (solve real-world problems) TIL 3D games and real-time audio apps are not "real-world problems".

I think the idea is that python is appropriate for solutions to some problems that are "real" problems (as opposed to being valuable purely as a toy) -- not that python is appropriate for solutions to EVERY "real" problem, and any problem that python would be a poor choice for isn't a "real" problem.

Re: Stop writing lambda expressions in Python

#136
post #81
post #71

I generally like coding with lambdas, but in Python one thing I hate is that they will capture a numeric loop index by ref and not by its current value. If you try generating some polynomials x -> x, x^2, x^3 ... in the "obvious" way you'll see what I mean, all polynomials will be the same as the last one after the loop or list compr is done. Theres a workaround using default arg value to capture by val but its ugly…

Do you mind fleshing out your example with some actual code? I'm not quite following, and I'm completely lost by the time you talk about the workaround.

Sure, what I meant by the "obvious" way of making some polynomials is:

    polys = []
    for i in range(0,4):
        polys.append(lambda x: x**i)
But that actually just yields the same polynomial x -> x^3 in each element of polys array:

    polys[0](2)
    > 8
    polys[1](2)
    > 8
    polys[2](2)
    > 8
The same thing happens if we use a list comprehension:

    polys = [lambda x: x**i for i in range(0,4)]
The trick is to add a default argument value to the lambda, which catches "i" by value instead of by reference:

    for i in range(0,4):
        polys.append(lambda x, i=i: x**i)
    
And now we get the different polynomials we expected:

    polys[0](2)
    > 1
    polys[1](2)
    > 2
    polys[2](2)
    > 4
    polys[3](2)
    > 8

Re: Stop writing lambda expressions in Python

#137
post #93

Earlier quoted context omitted.

FWIW, in many languages, "lambda expressions" and "anonymous functions" are two similar but different things. Specifically, a lambda expression is a shorthand syntax for writing anonymous functions whose body consists of a single expression. Which is pretty much what you get in Python.

Which languages?

C# offers three different ways to denote an anonymous function: Anonymous delegates, lambda expressions, and statement-bodied lambdas. Each of them are true closures and can be used to construct a "method" of a given delegate type (i.e. any one of them can be used to as a value for a given variable — interestingly, in any case, an anonymous method must be assigned to a variable (or parameter) before you can use it, unlike, say, the anonymous functions of Lisp, JavaScript, F#, or even the criminally underrated VB).

But they have some important difference:

1) Anonymous delegates (introduced in C# 2.0) allow you to elide the formal parameters when defining a method of a given type if the body of the method doesn't use those parameters. Even though this construct is basically obsolete, I still use it just for this feature.

2) Lambda expressions can be automatically transformed into expression trees, which means that you can use them to construct (awesomely powerful) fexprs[1]. But, they can't contain statements, which means you can't use them for any kind of imperative code. These are the most equivalent to Python's lambda as far as that limitation is concerned.

3) Statement-bodied Lambdas can contain statements (as the name implies), but the language won't convert them into expression trees for (you can do it manually – tedious but not at all hard). At the time that the lambda expression feature was introduced (as a member of the constellation of features that made up LINQ), the framework didn't even contain expression classes that corresponded to most of the imperative constructs, but that changed with the advent of C# 4.0 which implemented a meta-object protocol[2].

Another implementation detail (last time I checked, which has been a while) is that anonymous delegates get turned into instances of System.Multicast delegate, whereas a lambda expression either gets turned into a class with a method that corresponds to the lambda expression (and fields that correspond to closed over variables), or into an expression tree, depending on the class of the variable to which it's being assigned.

[1] https://en.wikipedia.org/wiki/Fexpr

[2] https://en.wikipedia.org/wiki/Metaobject

Re: Stop writing lambda expressions in Python

#138
post #72

Personally, I use them often and disagree with a lot of this sentiment. I also disagree with a significant portion of PEP8, however. Anonymous functions are vital to any modern high level language. I think most people get hung up on the word. If the keyword was changed from “lambda” to “fun” for example I think it wouldn’t be as obtuse to more intermediate developers. To be honest I think the lambda does Python a ser…

> Anonymous functions are vital to any modern high level language. I don’t think you’re wrong, but I am also not experienced enough to know why this would be the case. What is the virtue of having an anonymous function? I get that it makes code somewhat easier to read and write if you’re only using the function once and it’s short, but that seems like an edge case. What am I missing?

First class functions are vital. Not so sure that anonymity is vital.

Re: Stop writing lambda expressions in Python

#139
post #99

Earlier quoted context omitted.

Don't complain about design warts if you're using an old version. Python 2 is just a couple years from end-of-life, and that's after the support guarantee was extended.

i didn't choose python 2.7. it is what i have installed on my work computer because the three projects i have worked on at work that used python were all using python 2.7, and the projects were led by "python people". in a couple cases, it was me who got them to upgrade from 2.6 to at least 2.7, and i have tried communicating to people to use python3 if they insist on python. i wouldn't choose python for a new projec…

Sure, just like how it's Microsoft's problem that Windows 98 still gets used in a few places.
Post reply on HN