5 ms·
fwiw, once Python's introduced there's the third option on the table, comprehensions, which will also be suggested by linters to avoid lambdas: authors_of_
by syklemil 2y ago
fwiw, once Python's introduced there's the third option on the table, comprehensions, which will also be suggested by linters to avoid lambdas:
authors_of_long_books: set[Author] = {book.author for book in books if book.page_count > 1000}
These are somewhat contentious as they can get overly complex, but for this case it should be small & clear enough for any Python programmer.
- davidw 2y agoWithout syntax highlighting, "book.author for book in books if book.page_count > 1000" requires a lot more effort to parse because white space like newlines is not being used to separate things out.
- xen0 2y agoSet comprehensions are normal in mathematics and, barring very long complex ones, I find them the easiest to parse because they are so natural. They're just a tad more verbose in Python than mathematics because it uses words like 'for' and 'in' instead of symbols.
- nicwolff 2y agoauthors_of_long_books: set[Author] = { book.author for book in books if book.page_count > 1000 }
- syklemil 2y agoYou've had some answers already, but I also think this is a good argument for syntax highlighting. With tools like tree-sitter it's pretty easy these days to get high quality syntax highlighting, which allows us humans to receive more information in parallel. A lot of the information we pick up in our daily lives is carried through color, and being colorblind is generally seen as a disability (albeit often a mild one which can be undetected for decades). Syntax highlighting in print is more limited because of technological and economic constraints, which might leave just bold, italics and underlines on the table, while dropping color. On screens and especially in our editors where we see the most code, a lack of color is often a self-imposed limitation.
- davidw 2y agoThat's not the point though. If you need the syntax highlighting to quickly make out the structure, perhaps the visual layout is not as good as it could be.
- syklemil 2y agoI consider syntax highlighting to be a part of the _visual_ structure. Visibility is more than just whitespace and placement!
- d0mine 2y agoSet comprehension are more idiomatic here (explicit syntax) though filter/map are not that bad too: {*map(_.author, filter(_.page_count > 1000, books))} It uses lambdas package.
- itsmeknt 2y agoI tried scaling up the original into an intentionally convoluted nonsensical problem to see how a more complicated solution would look like for each approach. Do these look right? And which seems the most readable? # Functional approach var favoriteFoodsOfFurryPetsOfFamousAuthorsOfLongChineseBooksAboutHistory = books .filter(book => book.pageCount > 100 and book.language == "Chinese" and book.subject == "History" and book.author.mentions > 10_000 ) .flatMap(book => book.author.pets) .filter(pet => pet.is_furry) .map(pet => pet.favoriteFood) .distinct() # Procedural approach var favoriteFoodsOfFurryPetsOfFamousAuthorsOfLongChineseBooksAboutHistory = set() for book in books: if len(book.pageCount > 100) and book.language == "Chinese" and book.subject == "History" and book.author.mentions > 10_000: for pet in book.author.pets: if pet.is_furry: favoriteFoodsOfFurryPetsOfFamousAuthorsOfLongChineseBooksAboutHistory.add(pet.favoriteFood) # Comprehension approach var favoriteFoodsOfFurryPetsOfFamousAuthorsOfLongChineseBooksAboutHistory = { pet.favoriteFood for pet in pets for pets in [book.author.pets for book in books if len(book.pageCount > 100) and book.language == "Chinese" and book.subject == "History" and book.author.mentions > 10_000] if pet.is_furry } FWIW, for more complex problems, I think the second one is the most readable.
- syklemil 2y agoI'm more partial to the first one because it keeps a linear flow downwards, and a uniform structure. The second one kind of drifts off, and reshuffling parts of it is going to be … annoying. IME the dot style lends itself much better to restructuring. Depending on language you might also have some `.flat_map` option available to drop the `.reduce`.
- deleted 2y ago[deleted]
- itsmeknt 2y agoTrue! Good point on the restructuring, I haven't thought about it in that way. I think I like the second approach because the loop behavior seems clearest, which helps me analyze the time complexity or when I want to skim the code quickly. A syntax like something below would be perfect for me if it existed: var favoriteFoodsOfFurryPetsOfFamousAuthorsOfLongChineseBooksAboutHistory = books[i].author.pets[j].favoriteFood.distinct() where i = pagecount > 100, language == "Chinese", subject == "History", author.mentions > 10_000 where j = is_furry == True