Hacker News new | ask | show | jobs
by lolinder 658 days ago
Are there things that you find easier to express in a list comprehension format than you do with Kotlin's standard library? I've always found comprehensions to be a bit of a workaround to the fact that Python doesn't have great support for anonymous functions, and I've never found a situation where I'm writing Kotlin really wishing I had a comprehension.
2 comments

A bit of a contrived example, but something like this (two for statements):

[x*y for x in range (10) for y in range(10)]

It's not often, but occasionally there are moments where I'm writing code in Kotlin and wish I could use a list comprehension. I do prefer Kotlin overall, but there's a few things that I think would be "nice to have" from Python. Especially the yield keyword, such a wonderful way to write your own iterators.

Like this?

  sequence { for (x in 0..<10) for (y in 0..<10) yield(x*y) }.toList()
Now, technically, Kotlin doesn't have list comprehensions, only the equivalent of generator expressions in Python, so you have to tack an extra `.toList()` on at the end if you want a list, but you can write pretty much any for comprehension in Python in a similar way in Kotlin.

On the other hand, you're not limited to for loops/ifs inside such a generator, but can use fairly arbitrary control flow.

You could also build the list directly.

  buildList { for (x in 0..<10) for (y in 0..<10) add(x*y) }
Hmm, I actually prefer Kotlin's version, but maybe that's just because it's what I'm used to:

  (0..10).flatMap { x -> (0..10).map { y -> x * y } }
The flow of the data is more intuitive for me because you don't use variables before they're defined.

> Especially the yield keyword, such a wonderful way to write your own iterators.

Maybe I'm missing something about `yield` in Python—can it do something that Kotlin generators can't?

It's mostly ease of semantics -- in your example you use two layers of map and as a result need to do flatMap instead of just map twice

In py, for list/set/dictionary/generator comprehensions, the format is always the same and always the same as if you were to do it as a normal nested loop, save for the statement being first instead of last (you can also do filters using normal if statement syntax, these go at the end/after all your loops).

I actually like statement first because it gets to the "meat" of the semantics before the context (which loop etc), but end do the day it's all a bit arbitrary

@ yield, there's literally no difference between Python and kotlin. Python also offers a generator comprehension, which is nice, but it has nothing to do with yield

i_am_a_generator = ( x+1 for x in range(10*100) )

Theres the zip function builtin, which I actually would have preferred

  oneToTen.zip(oneToTen2) { x, y -> x * y }
That's not actually equivalent. The initial version they included produces:

  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 ...]
Whereas yours is just:

  [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
I’ve always liked that the structure of list comprehensions mirror SQL with “SELECT, FROM, WHERE” sections.

But I know that I’m in the minority that likes SQL

They remind me of C#'s LINQ