6 ms·
I'm not sure how someone could see Kotlin as more expressive than Python, unless I am misinterpreting what expressive means. Python has a good language features
by Blot2882 2y ago
I'm not sure how someone could see Kotlin as more expressive than Python, unless I am misinterpreting what expressive means. Python has a good language features and helpful abstractions like list comprehensions.
What makes Kotlin more expressive? I understand it has some functional features but I've never seen anything dramatically flexible.
- jonesetc 2y agoThe biggest thing that wouldn't be available in Python would be the DSLs. Often they are not my favorite and overused, but they can be very expressive for things like their charting example https://kotlinlang.org/docs/data-analysis-overview.html#kandy https://kotlinlang.org/docs/data-analysis-overview.html#kand...
- lolinder 2y agoKotlin's standard library has ruined me for other languages, especially its collections library. The consistency and comprehensiveness of its approach to collections is unmatched in any language I've tried, including all the big name functional languages. It's hard to get across what's so great about the library in writing because it's not just one standard library function, it's how they all interact with each other and how they interact with the language design—you really just have to try it to understand. The net result is that transforming data from one shape to another flows effortlessly, with the dot operator seamlessly connecting a stream of transformations. The fact that it's the dot operator also means that you get really great autocomplete to help you on your way. Python, meanwhile, has always felt pretty awkward to me when it comes to data transformations. Comprehensions are okay, but they feel like they are special casing what should be a bunch of standardized helper functions operating on lambdas, as a sort of ugly workaround to the fact that Python refuses to implement proper lambdas. And when you can't use a comprehension, you're stuck with a pretty awkward collection of helper methods that are hard to find and use correctly and which are severely handicapped in expressivity by the lack of a proper lambda.
- Blot2882 2y agoThat's interesting. I've heard complaints about Kotlins standard library in comments like this[1]. I understand they may be nitpicks but they seem annoying in practice. [1] https://www.reddit.com/r/Kotlin/comments/mh2z5u/comment/gt2nv9o/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button https://www.reddit.com/r/Kotlin/comments/mh2z5u/comment/gt2n...
- lolinder 2y agoHmm, coroutines are definitely a bit of a mess, but in ways that aren't super relevant when you just want to use them and not implement a framework on top of them. They definitely sacrificed implementation simplicity in favor of interface simplicity. > don't even try to tell me that anyone uses sealed classes in practice I use sealed classes for errors all the time. > Nothing is concurrency safe. Yes, but I know of no stdlib of a serious alternative that is, so I don't think that's a major concern. Don't use concurrency and you're no worse off than Python (the alternative here), and if your point of comparison is Java or similar then it's the same story there. > All of the numbers suck. The fact that I can just call Long.toInt().toUByte() and lose a bunch of information and/or wrap a negative value into a positive value, etc, without any kind of help from the type system (maybe returning nullables) or the runtime (throwing exceptions for truncation) is gross. Similar to the above: yes, it could be better, but it doesn't bring Kotlin's stdlib below any other major language I'm familiar with. Heck, even Rust lets you do those downcasts without a word [0], you're just supposed to know that downcasts can lose information. Lints can help you here if you care, but I don't think a language gets points docked for not having them by default—there's a balance to be struck between too few and too many explicitly-typed failure cases. > The Map API sucks. Map::getOrElse is literally implemented incorrectly-it will call the "or else" function if the value is present in the map but is null. That... is fair. I've never actually noticed it before, but it's wrong. The rest of the Map API has always been good for me, though. > Dates and times suck. In every language ever. > I don't like how the default for the collection combinators is to be eager. They acknowledge that they have no answer here, and neither do I. There's no pattern for Kotlin to follow because only Haskell does lazy-by-default, and Haskell isn't a model most people would want Kotlin to follow. All in all, I read a comment like this as someone reaching for the things that irk them in a language that they actually really like—which means the items that irk them are either extremely small or actually just broken in all major programming languages. [0] https://play.rust-lang.org/?version=stable&mode=debug&edition=2015&gist=73921b7241fba3e42286c70ee1e974ff https://play.rust-lang.org/?version=stable&mode=debug&editio...
- Larrikin 2y agoAs someone who uses Kotlin for work and Python for side projects (and loved Python years ago in college), Python's list comprehension feature is one of the things I hate the most about the language now. As a simple example using only two collection functions I find it much easier to read val hundredOrLessEvenSeconds = (1..1000) .toList() .filter { it <= 100 } .filter { it % 2 == 0 } .map { it.seconds } than hundred_or_less_even_seconds = [timedelta(seconds=it) for it in range(1, 1001) if it <= 100 and it % 2 == 0] But there are tons of helper functions in the collections library to express that in a variety of different ways. But not in a gross code golf way, with clearly named functions Theres just so much built in https://kotlinlang.org/docs/collections-overview.html https://kotlinlang.org/docs/collections-overview.html Having lambdas built into the language from the start leads to a ton of expressibility I miss when using python
- wk_end 2y agoNot that I especially want to defend Python, but can you elaborate a bit on why you find that chain easier to read? The Python version is straightforward enough - if it's just the absence of newlines you can write hundred_or_less_even_seconds = [ timedelta(seconds=it) for it in range(1, 1001) if it <= 100 and it % 2 == 0 ] Also, I don't know Kotlin well enough, but is what you wrote going to be efficient? The Python version iterates once and creates one list (and you can actually turn it into a generator and make zero lists just by swapping the square brackets for parens); to my untrained eye, it looks like the Kotlin version is going to do more iteration and make four separate lists, three of which are just garbage to be thrown away immediately. Here that probably doesn't matter, but in other cases it might be a big problem; is there an easy/idiomatic way to avoid that?
- esafak 2y agoIt's easier to compose functions in Kotlin. The python version you showed is more ad hoc, and is really one list comprehension. I particularly like Kotlin's scope functions: https://kotlinlang.org/docs/scope-functions.html https://kotlinlang.org/docs/scope-functions.html
- FridgeSeal 2y agoPythons list comprehensions are sort of fun, but occupy that space because the language designers throttled the alternatives pretty hard. I used to write a lot of Python, I now write a lot of Rust, and the Rust iterator chains feel inordinately more powerful, and list comprehensions feel semantically backwards to me now: what you’re doing, what you’re doing it to, and whether to do it conditionally are all out of order. To me, Python feels “expressive” because you can “do stuff to make it work” not because of any inherent design that lets you properly express what you’re trying to do.
- rbehrends 2y agoAs somebody who uses and likes both Kotlin and Python (and quite a few other languages), I'd be cautious with using a subjective term such as "more expressive", too, but I can possibly shed some light on where such feelings come from. Personally, I see Kotlin as the closest thing to a statically typed Smalltalk that we have among major languages, and that's a major draw. A key part here is that Kotlin closures are fully-featured equivalents of Smalltalk blocks (up to and including even non-local returns [1]), whereas in many other languages that falls short. Java does not allow mutation of local variables and Python restricts lambdas to normal expressions. I find code whose behavior can be parameterized by code to be an essential feature of modern-day programming and this should be as frictionless as possible. This is also a situation where syntax matters, and while it isn't quite as nice as Smalltalk, Kotlin's syntax (esp. with trailing closures) make such code as readable as possible in a brace-style language with minimal additional syntactic noise. In a similar vein, the functionality of Smalltalk's cascades is offered through scope functions [2], especially `.run {}`. But ultimately, fully-featured closures (and the fact that they are widely used in the standard library) power a lot of the things that people seem to like about Kotlin. That does not mean that there aren't downsides. The limitations of running on the JVM are one (e.g. while Kotlin has workarounds for the JVM's type erasure, they're still workarounds), and then Gradle is arguably Kotlin's weakest point (which apparently even JetBrains are seeing, given their investment in Amper). That said, personally I'd say Kotlin's static typing and performance would be the primary reasons for me to reach for Kotlin over Python, not necessarily expressiveness. Type annotations in Python + mypy etc. just aren't the same experience, and writing performance-sensitive code in Python can be very tricky/hacky when you can't delegate the hot paths to numpy or other existing C/C++/Rust libraries. Conversely, Python often has a leg up when it comes to fast prototyping and scripting, even with Kotlin Worksheets in IntelliJ IDEA and with kscript. [1] Which, to be clear, are a nice-to-have thing, not essential, but still impressive that even that was covered, when previously Ruby was the only major language I know of that did it. [2] https://kotlinlang.org/docs/scope-functions.html https://kotlinlang.org/docs/scope-functions.html