8 ms·
You had me nodding in agreement until the last paragraph. Functions are first class in Python. You can pass them all over the place and use them the same way y
by whalesalad 7y ago
You had me nodding in agreement until the last paragraph. Functions are first class in Python. You can pass them all over the place and use them the same way you would in JS. You don’t have Lodash but frankly it’s not needed. The stdlib, functools and itertools are pretty much all you could ever ask for.
- AsyncAwait 7y agoIn fact, they're first class in Go too, in fact there's fewer languages where that's not the case than is, I'd imagine.
- zeugmasyllepsis 7y agoWhile functions are first class in Go, the limitations of the type system make them less ergonomic to use, I think. Without user defined generics, many of the common uses of first-class functions become a lot less convenient to use.
- hactually 7y agoDo you have an example where that's the case?
- edflsafoiewq 7y agomap, filter, fold, etc.
- TheDong 7y agoOne easy example is map functions. In typescript, if I have a bunch of "User" objects where each user has an "name" and "age" field, and I want to print a comma separated list of all those names formatted as "name -- age", it's simple. I write: let userNamesList = let userNames = users.map(u => `${u.name} -- ${u.age}`).join(", ") console.log(userNamesList). This is possible in no small part because map is generic. In go, to get the same level of expressiveness, I'd have to write the following stuff around it: func mapUsersToStrings(f func(u User) string, users []User) []string { result := make([]string, len(users)) for i := 0; i < len(users); i++ { result = append(result, f(users[i])) } } And after writing that boilerplate, I can finally write: userNamesList := strings.Join(mapUsersToStrings(func(u User) string { return fmt.Sprintf("%s -- %d", u.name, u.age) }), ", ") That boilerplate, of having to write a specialized map/filter/etc function with a for loop for every combination of types you transform between (mapUsersToStrings, mapUsersToAddresses, mapUsersToAges) is really annoying. It's harder to point to many other cases because, simply enough, people don't write such cases. The fact of the matter is just that go libraries make very sparing use of first-class functions because the lack of generics prevents it from working well, and so we end up with an entire language ecosystem where code is harder to read and with fewer simple abstractions reused across it. You can still write any code without good generics or first-class functions, you'll just have more programmers writing more code with less clean abstractions.
- thatswrong0 7y agoI think I meant the treatment of anonymous functions - lambdas are limited compared to normal functions.
- im3w1l 7y agoIf you need more power than a lambda you would use a nested function, e.g. def a(n): def b(): print(n) return b
- saagarjha 7y agoThat's a lot of boilerplate for a closure…
- earenndil 7y agodef a(n): return lambda: print(n)
- saagarjha 7y agoThat's a couple characters over most languages I normally use. Plus lambdas have a number of strange warts and restrictions (no multi-line lambdas?) that leave me feeling that Python really dislikes traditional functional programming constructs.
- WoodTree 7y agoPython has become less functional over time. It’s also not a particularly good OO language either. It’s really a more descriptive sort of bash that became ubiquitous despite its short comings.
- mlyle 7y agoThe trivial lambda case is short, and you can do what the parent said if you want to do something that doesn't fit into the trivial lambda case well.
- Scarbutt 7y agoIf you add in Typescript as he said, is a much better proposition than mypy.