Kotlin lacks the ability to do true functional programming that Swift has. Swift has pattern matching, recursive data structures (edit: specifically ADTs with enums or case classes is what I was thinking of here, should have written algebraic data types), tail call optimization, even some form of type classes, immutability (thanks @tmail21), and so on.
Kotlin does not have any of these (edit: this is now partly false, see below)
I'm sad that Google is supporting Kotlin and not Swift or Scala for Android, since at least with the latter two, you can use functional programming.
Edit: Actually, I'm looking into Kotlin again, and it looks like it's greatly expanded support for functional programming compared to a year or two ago. For example, algebraic data types can now be encoded in a similar manner to Scala, and kind of pseudo-pattern matched using `when`. TCO is now supported. There are lambdas, and support for closures. Destructuring assignment. But as far as I can see, still no immutable values (just immutable references), and no way to make extensible type classes, like in Scala and Swift.
I'm definitely going to take another look now. Last I checked a few years ago, Kotlin had very limited support for functional programming.
And I'm not sure what you mean by recursive data structures. Basically every C style language I'm aware of can contain a reference to another instance of its own type.
It's more java-y than Scala, but it's fundementally capable of a very FP style.
Those are not type-classes, at least not in the Haskell sense. They allow you to avoid an else branch, yes, which is actually quite useful; but one basic ability they're missing is the ability to define a new branch for a new instance of the type defined by library users.
Just as an example. They're really not much like type-classes at all.
I agree with Filligree that sealed classes are not really capable of emulating type classes. They can be used for algebraic data types, which is great, but for true extensible type classes you'd need something like Scala traits.
Tail recursion is a special case of tail calls that can be turned into loops. Their keyword is called tailrec, so it's probably not real TCO. Real tail call optimization can't easily be turned into loops in the general case.
pattern matching: swift has switf and kotlin has when, both are very similar
recursive data structures: I don't get this one, kotlin has all the java api available and all the third party libraries. As java has been here for much longer than swift I guess that swift is lacking more here than kotlin.
Tail call optimization: kotlin has the special word tailrec for this
Yes, kotlin has a lot of things. It also has co-routines like in go, it also compiles to java script and much more.
The reason Google is supporting kotlin and not swift or scaala is because they have to do nothing to support it. Kotlin compiles to bytecode, so it doesnt matter your code is written in java or kotlin because when you compile it it is bytecode at the end. Scala needs to add a runtime when compiling to bytecode, it takes much longer to compile than kotlin and it is not fully compatible with java as kotlin. And Swift it is just something completely different, they should change the virtual machine in order to support it.
Pattern matching: Kotlin has a `when` that desugars into if when statements, but it's pretty far from pattern matching like you see in Scala, Swift, and more traditional functional languages.
Recursive data structures: Yeah, for some reason I wrote recursive data structure when I was thinking of algebraic data types, like Scala can encode with case classes. I often use them in Scala or OCaml to make recursive data structures which is why I mistakenly used that term instead of ADTs.
TCO: glad to see I was wrong. Kotlin added support for this in the past year.
Android: I realize that to support Swift on Android, Google would need to do significant work, but they wouldn't have to change the VM since Swift could also be compiled to Dalvik bytecode. But obviously that would be a lot of work. I only mention Swift since there were rumors in the past that Google was considering fully supporting Swift on Android.
Plus, to be clear, you can run Swift on Android now using the native SDK, just not on Dalvik for making GUI apps.
> Kotlin has a `when` that desugars into if when statements
Actually not. Not now, probably it was the case at the begining of the language.
> algebraic data types
they removed some restriction of sealed classes in 1.1. So I am not sure this is true anymore.
The memory management in Swift is completely different than in Java. That is the main reason you need to make changes in the virtual machine. JVM uses the garbage collector while swift uses reference counter.
> Scala needs to add a runtime when compiling to bytecode
Last time I checked you needed like 500kb of libraries for any scala program compiled to Android. Kotlin is a few kb. Kotlin is a small addition to the java API, Scala needs much more things.
> it is not fully compatible with java as kotlin.
As far as I know, the way scala treats types and functions make it that sometimes you cannot call scala code from java. Well, you can most times but requieres a lot of wrappers. This doesn't happen in kotlin.
I learn scala few years ago, my memory is weak and things may change. But I wanted to use it for android and give up quite quickly because of lot of issues. For kotlin was like love at first sight. No problems at all.
> Last time I checked you needed like 500kb of libraries for any scala program compiled to Android. Kotlin is a few kb.
30kb for Scala is the figure elsewhere in this thread and that sounds a lot more in line with my experience. Note that you never have to use e.g. Scala collections if you don't want to (and thanks to typeclasses you can write elegant code that works with both Scala collections and Java ones, so you can reuse libraries across both).
> As far as I know, the way scala treats types and functions make it that sometimes you cannot call scala code from java. Well, you can most times but requieres a lot of wrappers. This doesn't happen in kotlin.
Nope. There's no difference, just kotlin propaganda.
Well, Google has to do extremely little to support Kotlin, as it runs on the JVM, does so fairly leanly, and does so on Java 6 JVMs.
Swift, they'd have to redo just about their entire stack, as Swift doesn't run on the JVM (Swift can be used with the NDK to build NDK libraries, but it's not standard to build a full app, outside of games, with that).
Scala has had big issues with the size of it's library that still haven't been resolved, and the new versions of Scala require Java 8, which only the beta version of Android supports right now.
What about immutability? A key part of functional programming is using immutable structures to avoid side effects.
My understanding is that Swift has these to some extent ("let" vs "var", structs being immutable etc). And since Kotlin is built on JVM compatibility I _assume_ that Kotlin does not support an immutable style of programming. Maybe someone here has more clarity on this.
> And since Kotlin is built on JVM compatibility I _assume_ that Kotlin does not support an immutable style of programming.
The underlying host doesn't imply anything about language support as that's handled at the compiler level, not at the machine or VM level.
Even in Haskell data isn't immutable if you have a debugger or modify the machine code. It's simply a tool provided and enforced solely by the compiler - other JVM languages do support it like Clojure or Scala.
You can have immutability by making the setters methods of a class private. So if you combine it with "val" you have immutable objects. It is a bit more job in kotlin but as it is also object oriented programming you can achieve exactly what you want.
And for structures you have list, mutablelist, map, mutablemap, etc.
For immutability to be practical one would need to implement structural sharing in their collections otherwise copying would be prohibitively expensive.
I get your point now. Yes, it is read-only, not immutable. For me, I only need read-only. I think kotlin wasn't meant to be pure functional. I see it as object oriented with some functional programming.
out of curiosity, what cases will you use an immutable collection instead of a read-only? I cannot imagine any use case where immutable is a gain over read-only.
"Read-only" would not implement structural sharing.
Consider the situation where you had a linked list with 10,000
elements and you wanted to return a new list with one new element added to the 'head' of the list. With "read-only" you would literally have to make a new linked list with 10,001 elements which would kill performance.
While semantically correct, immutability via deep-copying is very impractical. So, immutability (of Collections in particular) needs to be implemented via structural sharing of elements.
In the above example, with structural sharing, the new list would have the new element and inside would point to the old 10,000 element list but the whole 'structure' would appear to you as just a normal list.
Sorry, I don't see the difference. With read-only you can create a new object which is the first element of the list and also points to the rest of the list. Instead of an structure you have an "immutable" object.
Yes, but the resulting object is not a "List" and hence would not inter-operate with any function that took a List as input.
In essence if the original object implements a List _interface_, then the new one should as well. If you do all of this, then you've essentially implemented immutability and structural sharing. But then you have to do this for 10 other Collection types as well.
Now, you could do all this, but I could do it as well and do it differently. Then my function which took MyList as argument would not interoperate with your function that wants to pass YourList as argument.
Something as fundamental as an (immutable) collection needs to be standardized so that all functions can take these and return them and thus compose easily.
This is the case with languages that implement immutability like Elixir, Haskell etc.
There are already interfaces for Immutable collections in kotlin. And all the functional operators as map, filter, etc, returns them. But it is not true immutability as you said, because under the hood they are normal list. They aren't even read-only objects, but you encapsulate this behaviour under an interface.
This needs to be built into the language or somehow standardized by the community.
With lack of standardization of immutable collections, there would be lots of different ways that libraries would implement immutability. This would result in losing one of the main benefits of functional programming (i.e. awesome composability).
This is already in the language. It is just an interface which makes the common lists only visible as immutable objects. But inside they are a normal list. And in this case the object is read-only, not immutable, as we were discussing in the other comment thread.
> Kotlin lacks the ability to do true functional programming...
Same goes for Swift.
Any "hybrid oo functional" language will not do the functional thing as well as a dedicated functional language. If you're still gluing things together with types, functions will never be quite as first-class as they should be.
I feel like you could about as well write an article about how Go or Scala or TypeScript is like Kotlin. They all have some cases where they look similar or have some similar constructs borrowed from other sightly-less-recent languages. It doesn't seem like a very interesting or deep similarity.
If you want to compare them, going over the differences would be a lot more illuminating.
>Kotlin came across as strangely familiar, though, and eventually I realized it's because it looks like Swift -- which I was slow to notice because my iOS app is in Objective C for irritating legacy reasons. And of course now I know that's backwards: Kotlin predates Swift by several years, so it's more accurate to say that Swift is like Kotlin.
Past the syntax similarities, both of these languages are intended replacements for an 'old' language (Objective-C => Swift, Java => Kotlin) on a dominant mobile platform, with interoperability as a major selling point (requirement?). As a mobile dev (mainly iOS) this is awesome to see and although I love me some Objective-C, working with swift has been a pleasure. Now Java on the other hand... (shudders).
With Google making Kotlin an official/first-class language and the syntax being so similar to swift I could see myself spending more time working with Android.
I assume Google will try to replace Java with Dart, because they have recently been focused on Flutter [1] [2] and Fuschia [2] development which are (mostly) C++ and DartLang stack.
> I assume Google will try to replace Java with Dart
I would have expected this, but not after pushing Kotlin. Kotlin is shiny enough to temporarily distract the typical developer from the daily struggles with the abysmal Android API.
Kotlin and Java it will be for the next 10 years, for better or worse.
Dart is not very popular within Google itself, and Fuchsia is nothing more than a paid hobby project[0].
According to what Fuchsia developer Travis Geiselbrecht said in the public Fuchsia IRC channel,the OS “isn’t a toy thing, it’s not a 20% project, it’s not a dumping ground of a dead thing that we don’t care about anymore.”[0]
Given the level of activity on [Fuchsia's project repos][0], I find it very unlikely that it's just a hobby project. That amount of activity is on-par with Android itself. If it is just a hobby, it's an extremely expensive one.
> both of these languages are intended replacements for an 'old' language (Objective-C => Swift, Java => Kotlin)
It may be true for Swift but Google never claimed Kotlin is replacement of Java. I guess people are getting overly excited and making claims that Google did not. Kotlin is low effort developer friendly move by Google. Jetbrains will do work on language and tooling and Google would provide some Android-Kotlin related docs and support.
That's true Google never named Kotlin as a replacement to Java. Although naming it a first-class Android language seems like a pretty big move (actions over words), and given an official option between Java and Kotlin I believe most dev's will begin moving towards Kotlin. intended was probably the wrong word for me to use, should have been probable or likely.
It's strange that on the Kotlin side the author goes out of their way to show 'shorter' ways to do things that are also available in Swift but not illustrated.
let sorted = [1, 3, 6].sorted()
let sum = [1, 3. 6].reduce(0, +)
The article is missing the similarities between Swift Optionals and Kotlin Nullables.
Swift code:
var name: String?
name? ///returns a safe value
name! ///returns an unsafe value and throws an exception in case of a nil value
if name != nil {
///Now we can use name! forcing unwrap because we know it's not nil
}
if let unwrapedName = name {
/// Here we can use unwrapedName without forcing the unwrap
}
kotlin make it a bit simpler, once you do name != null you can use it as it is never null after than, there is not need to use let. It makes it more readable.
var name: String?
// some code
name?.let {
// here name is not nil and can be accessed via variable "it"
}
// or
name?.let { name ->
// here name shadows the previous variable, and is not nil
}
One has structures, ARC, proper extensions, good protocols/interfaces, flexible enums, and runs natively. The other one doesn't. I think I'll choose the former.
One has a top-notch IDE from a top-notch IDE vendor. The other has XCode.
Also, ARC aside, for the 3-4 items you mentioned, either Kotlin also also has them, or has just as good alternatives. And none of those are life-changing. ARC vs a good GC is just a different tradeoff (no cycle detection vs pauses, etc).
I'm sure you can find some things where Swift is better at, and others where Kotlin is. But not that many to proclare one or the other the definite winner, and surely not a major one.
> Xcode isn't perfect, but it's way better than JetBrains.
O_o Are you kidding me?
People whinge all the time about jetbrains subscriptions, but I've literally never spoken to someone who's actually used their products and think that the alternative editors available (visual studio, xcode, etc) are actually better.
There are some features like UI designers that you can't do without, but it's been a long time since I met anyone who actually liked xcode.
I tried AppCode to write in objc on mac and it felt way less transparent and smooth than Xcode. Idk if Xcode is missing some features, but all my real issues probably exist in different planes. My Xcode inconvenience points are: case-insensitive completion sometimes gets in my way, as it is with single lettered variables; it is easy to break constraints for non-trivial xib. I can live with both. What is it for you, in short?
I've attempted to use IntelliJ for javascript/typescript (React, Node.js) and Elixir. I've found myself continually going back to VSCode or other editors. Especially for the front-end ecosystem, VSCode's intellisense, syntax highlighting and plugin support blows everyone else out of water IMO.
I use IntelliJ/Android Studio for Java, and that's about it.
Yes, yes, and yes, plus Jetbrain IDEs have much superior code assistance and navigation compared to Xcode. Xcode is clearly worse than Visual Studio, JetBrains, Eclipse, and many other IDEs I've used over the past 20 years in the industry when it comes to code navigation, refactoring, and basic editing. Xcode does only one thing well and that's interface builder, but if you were writing a backend application with no UI would you choose Xcode? I'd rank it lower than emacs and vim for editing tasks.
Otoh, my colleagues were surprised seeing easy and good-looking two-panel diff and blame right in Xcode. Analyzis build (one that shows blue arrows for how we can get into trouble) was surprise too. It seems that preference depends on use cases and two products can differ in different ways, not only as superior vs. regular.
I never did anything in VS though, cause its interface always turned me 180 after first run. And I can write Makefile and .gvimrc from scratch much faster than it installs itself.
Refactoring is a dream with JetBrains. But it is very language dependent, with Java having most support. Haven't used Kotlin in Intellij so I don't know how well Kotlin is supported, though I imagine rather well given that it their own language.
I use PyCharm and refactoring works pretty well there too. Also I really like having an IDE that runs and presents itself just the same on all big three platforms, since I'm always hopping between computers.
I'll take good IDE support over any of the things you mention above. Seeing how my colleagues refactor in XCode makes me cringe every time... Kotlin support in IntelliJ is almost as good as Java.
Kotlin Native ships with an ARC. But depending on the application ARC can be a disadvantage since it can't automatically handle reference cycles like Kotlin on the JVM can.
> [Kotlin Native] features automatic reference counting with a cycle collector on top, but what the final memory management solution(s) will look like is unknown at this point.
They're not really in direct competition. Try writing an Android app in Swift, or an iOS app in Kotlin. Technically possibly either way, but one's definitely more suited than the other for each purpose.
Which one is easier? I need to write some cross-platform native code for my React Native app, and I'm having a really hard time deciding on the language.
I honestly didn't know that I could use either Kotlin OR Swift for both platforms. But which would be easier to get running on Windows? I also need to write a version that works on the web, and I've heard that Kotlin can transpile to JS. So that's pretty amazing if that works.
I find it very annoying that Google and Apple are creating new languages to solve similar problems and not worrying about cross platform. If you write for Apple you've been told to use Objective-C and Swift. If you're on Android it's Dart and now Kotlin. None of that stuff is used for Windows or Linux development or even mobile on the other OS.
I'm not a fan of proliferation of "platforms" but when it goes beyond libraries and into the language itself I consider that a very serious problem.
This is forcing developers to write apps twice, or use a 3rd party solution to run on both OSes. Yep, they're refusal to work together and create standards is allowing companies like Microsoft to have value by offering yet another solution that works on both phones.
I think you meant Java and now Kotlin? Google never recommended Dart for Android development. They have Flutter which uses Dart, but that positions itself as a cross-platform way to build apps and doesn't have any support from Android tooling or things like that. It also still positions itself as an alpha, so do with what what you will.
But Kotlin also works just fine on JVM. So Kotlin works on MacOS, Windows, Linux, and now Android. That sounds pretty cross platform to me. Kotlin is also not a language from Google, so I don't know why you're annoyed with Google on this one. Kotlin is from JetBrains.
Imagine having hundreds of languages with only trivial difference in syntax. Consider the fragmentation and effort wasted on re-inventing the same low level libraries again and again (here is the hundredth version of unit test library). Sure, only language would be bad but so is too many.
A language doesn't gain traction cause of syntax or anything like that. It gains traction because a platform developer promotes it.
C# and Java had what amounted to trivial differences, when they started.
Kotlin and Swift also aren't very far apart, both in terms of syntax and power (in Blub power continuum terms).
There's very Computer Science-y reasons for these languages to exist as separate languages, but they do cause of product differentiation and platform lock-in efforts.
I guess they think they are cool for being able to provide this feature through a library function rather than a language construct, but someone should tell them they really need to add some syntactic sugar that transparently invokes arrayOf while looking nicer.
It's worth nothing that Swift literals are mostly library constructs as well. Any type conforming to ArrayLiteralConvertible can be instantiated using [...] syntax, for example. All other literal types (integers, floats, strings, dictionaries, etc.) have their own corresponding protocols you can implement. The only thing that's special for types like Array, Int, or String is that the compiler will automatically infer those types for a literal if there's nothing that indicates otherwise.
For example:
let x = [1, 2, 3] // produces Array
let y: MyType = [1, 2, 3] // produces MyType
f([1, 2, 3]) // produces whatever type f() takes
It's not pretty, but it makes sense so that you actually think about whether you need an array vs list vs ? instead of just going for whatever datastructure [] is going to give you because it's most convenient.
In practice, it's something I stopped caring about within the first hour.
Then again, mikeash's comment pitches a more interesting idea: [] as generic collection literal syntax that depends on inference / annotation to pick a concrete implementation. Best of both worlds. I'd just remove the Array default.
I've had the same issue with Scala. It goes out of its way to provide every syntax convenience that has ever existed--pattern matching, custom string interpolation, literal syntax for tuples, optional parens on method calls--- and then requires Maps and Seqs to be created with syntax like
val shoppingList = Seq("catfish", "water", "tulips", "blue paint")
It's because to is an infix extension method, whereas : is not a valid identifier name (and so can't be used as the method name) and you can't define arbitrary operators like in C++ and Scala.
The to method constructs a Pair object from its arguments, so
"Foo" to "Bar"
is just a prettier way of writing:
Pair("Foo", "Bar")
The mapOf function (which is just a normal function) takes a variable number of Pair objects as parameters.
Ugh, I know it's something that literally every programmer on earth can and often does bikeshed, but Swift just got string interpolation syntax wrong. Parentheses are something that are often part of the interpolated expression... they shouldn't be part of the interpolation syntax itself.
Yes, agreed. IMO, curly braces would have made much more sense. It's not even bikesheding, really. It's just a fact that curly braces are less used in most written languages. I would also argue that curly braces are a better signal to the programmer that "something programmatic is happening here", due to their prevalence as scope delimiters in most popular languages.
Swift's string interpolation doesn't catch my eye like, say, Ruby's does: `#{my_var}`. It's very easy to gloss over `\(something_like_this)`. I suspect they were going for a more "elegant" syntax at the cost of pragmatism.
I definitely think a general guideline for language designers could be "when in doubt, make it look like Ruby". The language has its issues, sure, but damn if it didn't get syntax just right.
I think we will have to agree to disagree on this. Personally, Ruby code is only marginally better than Perl in terms of line noise I can't read, a dubious distinction.
It doesn't look hyperbolic to me. If I dislike the syntax of a language, I can probably find a better one with the syntax I prefer. Maybe this is a negative side-effect of having too many options, but I don't think it's unreasonable to pass up on something for purely stylistic choices.
There does seem to be broad agreement across a range of typed languages -- TypeScript, Swift, Kotlin, ES6 + Flow -- about notations for classes, control flow and data structure declaration.
Don't forget that Scala preceded all of the languages you've listed, which in my opinion shows where the inspiration came from for some of them. Of course, I'm sure that Scala drew inspiration from some of its predecessors.
// Type indicated with `:`, type follows variable; value follows type.
variable: Type
variable: Type = "value"
// Generics with <>
strings: List<String>
// Operator overloading.
text = "a" + "b"
num = 1 + 2
// Capitalize type names.
class TheClass { ... }
// Use braces for delimiting.
class TheClass { ... }
Most of the conventions we're talking about were adopted by Scala; but we can see they also predate Scala. Many can be found in C++. The type/variable notation is very old, going back to ML and truthfully going back to mathematical notation.
I think there is real convergence. All serious new languages have some form of static typing augmented with some form of type inference. All are lexically scoped. All have first-class functions and map/reduce/filter. None have unchecked manual memory management. None have checked exceptions.
There are still areas of debate, but at the same time I think there is real progress; we have learnt from past mistakes and they won't be repeated.
Some of it is due to theoretical alignment. For example, succinct function expressions come out of the the desire to simplify use of functional programming. Another example is the adoption of ML-style type notation: we want people to use static types, we want it to be easy, and we want types to be expressive -- <var>: <type> allows <type> to contain some spaces and punctuation while still being clear.
Pretty good list. I don't think the tuple comparison is accurate though, I thought a data class is basically a value type (like Swift's struct) except with some stuff like equals, hashcode, and toString calculated for you.
Minor nit: the sort example needlessly uses two lines for the Swift version.
Some considerations on the syntax (Swift first, Kotlin last in each pair)
bad: \(apples + oranges) # using \ is looking for troubles
good: ${apples + oranges}
good: label + String(width) # even Ruby requires a .to_s here
bad: label + width # surprises will follow
good: ["Anna", "Alex", "Brian", "Jack"]
super bad: arrayOf("Anna", "Alex", "Brian", "Jack") # make the long form optional
good: for index in 1...5 {
bad: for (index in 1..5) { # the useless ()
bad: extension Double { # why do we need to be so explicit?
var km: Double { return self * 1_000.0 }
good: val Double.km: Double get() = this * 1000
Are you referring to escaping and other special sequences (e.g. unicode codes)? Though it is odd-looking I actually find it rather smart that they decided to reuse an existing mechanism for that: aside from delimiters the only magical character in a string is \ rather than have e.g. both \ and $.
> # the useless ()
My beef is more with 1..5 being inclusive and there apparently being no exclusive range.
> # why do we need to be so explicit?
Why would you want syntax which is harder to parse, more magical, and has to be repeated for every addition, instead of an easily marked `extension` block which neatly parallels `struct` or `class` ones?
About \, yes it's the possible clash with a real quote. More an inconvenience to the reader that a source of bugs, but also that.
About ranges, Ruby has both .. and ... and after 12 years I don't remember which is what. Maybe an inclusive one is enough and 1..(n-1)
About syntax in general, it should be easy for developers no matter how hard it is for the compiler/interpreter to parse it. I don't like to have to type useless characters. Hence the () around if conditions and this extension thing. What else can it be? I'm defining a method of a class, no need for a special block. But I don't understand your "has to be repeated for every addition" so maybe I'm missing something important here.
> About \, yes it's the possible clash with a real quote.
Clash with a real quote? As in you paste random text from wherever and it turns out evaluated? You've got the exact same issue in Kotlin.
> About ranges, Ruby has both .. and ... and after 12 years I don't remember which is what. Maybe an inclusive one is enough and 1..(n-1)
That's why I like that Swift uses "a..<b" for exclusive, you clearly see the top-bound being excluded from the range. It's readable and smart design.
> Maybe an inclusive one is enough and 1..(n-1)
I have never missed inclusive ranges in languages with only exclusive ranges (e.g. Python), the opposite would not be true.
> About syntax in general, it should be easy for developers no matter how hard it is for the compiler/interpreter to parse it
That way lie Perl and C++ and undecidable syntaxes, I'm very much opposed to that.
> I don't like to have to type useless characters.
I don't see what's useless about saying what you're asking for. You define a struct your use a struct block, you define a protocol you use a a protocol block, you define an extension you use an extension block. It's readable and regular.
> But I don't understand your "has to be repeated for every addition" so maybe I'm missing something important here.
If you're adding more than one item in Kotlin you have to repeat the receiver e.g.
val Double.km = (thing)
val Double.miles = (thing)
val Double…
in Swift you just wrap it all in an extension block:
extension Double {
val km = (thing)
val miles = (thing)
val ...
}
"When you see that third dot, imagine opening the accordion slightly. Just enough to let one note from its chamber. The note is that end value. We’ll let the sky eat it." - http://poignant.guide/book/chapter-3.html#section2
it's always confusing, in languages with ranges, whether the range includes the second boundary element or not. it's purely a matter of convention, after all. ruby has a..b and a...b, but even after years of using the language i have to look up which is which. a..<b and a..b is perfect notation - once you know the language handles both cases, a..<b is very clearly "the range of numbers from a, and remaining strictly less than b", and "a..b" is "the range of numbers from a up to and including b".
as for the "count - 1", it's not too bad because i find "inclusive" more intuitive than "exclusive" for the a..b notation, and that does make it explicit that you're not including b, but it's visual clutter in much the same way that having to iterate an array via "for i = 0 to len - 1" is.
You only need to know that the language handles one explicitly, since there's two choices, so you might as well take the (more common | uglier to express) case and give it the "cleanest" special syntax: no special syntax.
I always remembered it as "the third dot makes it bigger so it pushes the range and the last item falls off". I can't remember where that came from, perhaps related to the poignant guide:
> I suspect `0..=n` would work similarly well, but I've not seen a real language to ever do that yet
This could be extended to cover `0=..=n`, `0<..=n`, `0<..<n` and `0<..=n`.
You can actually define that syntax in Haskell:
Prelude> let a =..= b = [a..b]
Prelude> let a <..= b = [(a+1)..b]
Prelude> let a <..< b = [(a+1)..(b-1)]
Prelude> let a =..< b = [a..(b-1)]
Prelude> (1 =..= 4, 1 <..= 4, 1 <..< 4, 1 =..< 4)
([1,2,3,4],[2,3,4],[2,3],[1,2,3])
As an alternative opinion, I personally hate when ranges are exclusive by default. In addition to it feeling somewhat unintuitive to me that I need to use range(0, 6) to include 5, it also makes downward ranges quite awkward, e.g. needing range(5, -1) to count from 5 to 0.
Exclusive by default is designed to fit with 0-based indexing (0..length(v), instead 0..(length(v)-1)). That said, this thinking is less relevant in languages with iterators/ranges and doubly so ones that offer a way to explicitly, but abstractly, iterate over the indices of a vector/array.
On the point of downward ranges, you can often reverse the range explicitly, rather than swapping the endpoints, like reversed(range(0, 6)) or range(0, 6)[::-1] in Python (vs. range(5, -1, -1)). Of course, this isn't nearly as syntactically nice as range(5, 0)... but that comes with its own problems: automatically iterating backwards in ranges has been really annoying every time I've encountered it (mainly in R), requiring extra care and a pile of extra ifs and/or mins & maxs.
Right-Exclusive ranges are superior to inclusive ranges because they can represent empty ranges, which removes one rare degenerate case and not overemphasizing it.
Another benefit: creating a series of right-exclusive ranges from a sequence [a, b, c, f] is easy: [a, b) [b, c) [c, f)
In the early beta release of Swift 0.x, they used x..y for half-open ranges and x...y for closed ranges. This confused people (especially since Ruby already used the same operators but the other way around), so they changed the half-open operator to x..<y.
How is the inclusive range operator implemented in Kotlin? Something like `for (i in 0..count)` needs to iterate count + 1 times, which may overflow the size of count's type - annoying to implement.
As someone who's never programmed in Scala, it's not intuitive to me at all that "until" means exclusive, given that "to" (which is basically a synonym) means inclusive.
Is there any language where the meaning isn't immediately clear? I haven't seen a language that didn't differentiate between '<=' and '<'. The syntax of just '..' is a little unclear at first however, but it is simply a requirement of learning the language and the idioms
it's not. i've never used swift, and the meaning was instantly obvious - i'd call that a very elegant solution to a common problem i've seen in several languages.
Read it as "For 0 to count" basically. "0... (spread operator) less than 0. It seems confusing to me as well at first read but I'm used to writing for loops by hand uphill both ways.
I personally think this exercise is rather odd in the first place. A lot of modern languages seem to have a same base syntax and these comparisons over simple operations is like taking all of the latin based languages and showing all the words that look similar.
Actually Kotlin is just Scala dumbed down by taking out the most powerful and interesting features like higher kinds, implicits, monads or macros. Which makes it just a Java 8 with a bit nicer syntax.
Two Kickstarter mobile engineers (Brandon Williams & Lisa Luo) just gave a talk on this at uikonf two days ago, where they walked through the similarities and small differences. Talk should be online soon.
The kickstarter apps are open source so you can compare it yourself.
As an iOS developer who's looking to port to Android, this makes it easier to manually port my Swift code to Kotlin. But I wish there were automated tools. If two languages are this similar conceptually, such a tool should be easy to write, and handle the majority of cases.
I don't mind if this tool prohibits a few features (pattern-matching in Swift, say), even if it's considered idiomatic, because not having to maintain another codebase saves more than enough productivity to make it worth it.
Kotlin is the same jvm crap like Java. Please do not dare to compare it to Swift with its amazing llvm complier. True programs runs on true machine specific bytecode, not on stupid virtual machines that consumers every available cpu and memory (which leaks like hell). Please new programmers, syntax is BS. Learn to compare by looking at internals and advanced feature set and capabilities. Kotlin is a fad!
Seems like they are very similar languages, with similar goals. They both want to be cross-platform. I suppose the competition is healthy, but at some point there's just a lot of duplicated effort. Although, I guess if they're both using LLVM, then it's not such a big deal. Maybe one day we'll see libraries that can be used by both Kotlin and Swift.
My hunch says that in order to be anywhere usable, any extra arithmetic must be done inside curly brackets, much like in Perl or PHP. It makes sense and is easy to parse for both human and compiler.
325 comments presently and sadly no one commented on what I find most exciting about Swift: integer overflow is trapped! FINALLY (the only other sane option is multi-precision integers, like in Scheme or Integer in Haskell). Does Kotlin do the same?
I presume Kotlin also traps out-of-range array accesses.
I think it is worst to have such similarities with very small different details than having completely different languages. For a developer working on both ecosystems it feels like hell to remember the tiny details.
Yes, it runs on the JVM and is 100% compatible with Java code. While it was fairly easy to use Kotlin with Android before, Google just announced first-class support for it at IO.
* Multiple receivers are possible enabling extension methods like this:
class EnglishToGermanDictionary {
val translations = mapOf<String, String>(
"dog" to "Hund"
)
/* extension method for string in the context of dictionary */
val String.inGerman get() =
translations[this@String]
}
/* usage */
with (EnglishToGermanDictionary()) {
val word = "dog"
println("The translation of $word is ${word.inGerman}")
}
"cat".inGerman ---> compile error, method not found
* Built-in Singletons are also very convenient. Swap the word `class` for `object` and you get a singleton.
* The article left out lambdas. The function:
fun greet(name: String, day: String): String {
return "Hello $name, today is $day."
}
Can also be written as
val greet = {name, day -> "Hello $name, today is $day."}
* The compiler is really smart in infering types. Extension values don't need type-specification, e.g.:
val Double.km get() = this * 1000
* "when" in Kotlin doesn't need an argument, you can write arbitray rule-sets with it, with correctly inferred conditions:
val myVar = when {
stack.isEmpty() -> true
x == null -> false
currentIdx >= a && obj is MyType -> true /* here x has been inferred to be not null from the previous branch! */
else -> when {
user.isPresent() -> calculateSomething()
else -> throw IllegalStateException()
}
}
* sealed classes allow you to limit inheritance and get error when you miss something in a when
/* you actually don't have to nest the classes this way, but you can */
sealed class Expr {
sealed class IntExpr : Expr {
class Plus(val left: Int, val right: Int): IntExpr
class Minus(val left: Int, val right: Int): IntExpr
}
sealed class StringExpr : Expr {
class Substring(val str: String, val start: Int, val end: Int): StringExpr
}
}
/* Usage: */
val x: Expr
when (x) {
is Substring -> ...
is Plus -> x.left + x.right
/* compile error, we forgot to handle "Minus" from above */
}
The receivers mechanism is kind of nice; reminds me of this[0], except that in Kotlin, everything is still statically typed. It's a really clean way to implement Trygve Reenskaug's DCI architecture.
In the above code, "with" and "to" are external names, and are only available when calling the function but are not available inside the function itself. So you would call this function like so:
greet(with: "Hello", to: "Bob")
Now if you want to exclude the external name to call the functions, you use the "_" syntax. So you're right that it denotes an unused parameter. In this case, it's an unused external parameter name.
Having never used Swift, it feels like the syntax is being optimized for the less-common case; are named parameters considered the "default" choice in Swift, and is using different external names so common that it's worth cluttering the syntax for functions without external parameters in order to make the their own syntax easier?
But of course, javascript APIs are hardly ever written like that. I think it's interesting how the norms of your ecosystem and very small differences in ergonomics in expression make a big difference in behaviour.
You can argue if it's useful or not on its own, but it makes sense when you consider that Swift is compatible with Objective-C. In Objective-C, that function would be a method like
Swift's external/internal parameters are built to allow the same style as was used with Objective-C and easy bridging. Swift's APIs tend to be terser than Objective-C ones, though.
> are named parameters considered the "default" choice in Swift
Most definitely yes. In fact it used to be that the first parameter was implicitly positional (in Swift 2 IIRC), this was removed to make all parameters named by default.
And do note that you can provide a single label for a parameter, it will be used as both "internal" and "external" names:
The reason is that named parameters is the default, so in your case greeting and personName are both "internal" and "external" names. "_ greeting" sets the external name to _ (aka positional) and the internal name to "greeting" instead.
For Obj-C fans though, named arguments are one of its best features. Yes, more verbose, easy to decipher, and led to great API design.
For the first versions of Swift, they actually had two versions. For functions (i.e not functions inside classes), you didn't have to have named arguments for the first parameter, but you did for methods (functions inside classes).
They explicitly added it for Swift 3 to make it more consistent with method.
I think I like the consistency more, but I do agree "_" is ugly. I don't have an idea of what else they could do though. I don't want Swift to make the parameter names optional, since no one would use it (like in Python, I rarely see named arguments being used)
That's not quite right, the special case was the `init`s, where all the parameters were named, whereas the first parameter of `func`s was not named. This kind of made sense, as you could put the name of the first parameter as part of the function name, which is impossible for an initializer. In the end, they normalised it to all parameters being named.
On a side note, I like the _, it's a clear signal of not caring about something and doesn't take up a lot of visual space.
I dunno, I think Swift's string interpolation is clever. Using the special-char backslash for opening string interpolation is a neat idea. Also keeps the number of special chars in in strings to a minimum.
Here in Ukraine it would be very hard to get adoption of a programming language that is named after a Russian military base. This is the rare case where bad naming choice really hurts. No matter how good is the language, you will have to hear and pronounce that name many times a day, and even associate yourself with it (e.g. "a Kotlin developer" in your resume). Not something to be taken lightly.
At first I read this as "Nobody cares about the politics of Indonesia" and found it quite offensive on multiple levels. Somehow, my mind just stopped processing input! Thankfully I reread your statement, but boy do I need caffeine – clearly!
With regards to the potential politics of naming things I think it's a tricky thing. When a brand has been established it's already too late and what started as "Naming something after a Russian island" ends up being problematic.
We're too global in software development to release a brand renamed in certain regions to solve this the traditional way, so libraries and languages have to be extra careful when dealing with naming.
Honestly, though, I would think we could all get past it by considering that maybe names are just names and we should be above the politics.
Without explicitly naming them, once you get into the realm of Stalinism or the holocaust, surely it wouldn't take too much imagination to come up with a few names too unsavoury even for you?
I don't see a line. Though if there's an element of humor I see an orthogonal anti-line that will annihilate any attempts at line-drawing.
I'm sure you could find a name that if not met with indifference or a laugh would elicit from me an eyeroll or a statement like "come on, that's dumb" or maybe "that's just asking to derail conversations" but I don't think you could 'trigger' me into a fit. (Of course you're welcome to try via email.) It's just a name.
Point taken, but the original point was being associated with the name, not throwing a fit. Having it on your CV/resume, for example. Potentially alienating clients because of words that stand out from the page in the wrong context. I can see a problem.
The point I responded to was maybe we should be above politics in names, to at least be capable of treating names with a professional indifference. To that end there's a simple test to see if someone you're considering working with believes that too. (Of course it's fully reversible, maybe the future will require passionate condemnation of names that might give offense in order to get hired.) For your point of unsavory associations, sure, but it depends on your expectations for audiences. What's the cost of association if no one throws a fit? What is alienation over a word if not a fit?
I can see a problem if you expect to pay that cost frequently when you bring up the word, and thus avoiding it, but if that's really the case it's worth wondering what other sorts of issues will come up that you don't expect when deciding to take the chance of alienation cost. If I made something as awesome as Stalin I'd put it on my resume, even if it resulted in periodic emails/comments about how insensitive a name it is. Even if some tech readers won't want to work with me because of it, I wouldn't want to work with them, so we're both happy, and we find that out before we actually try working together. I wouldn't put a 'I made Stalin' bumper sticker on my vehicle though. For a name like Kotlin, I really doubt Ukrainian programmers would be upset over it, it seems so absurd, but I can see the possible issue of the general public being sensitive about it in which case it's wise to only have the association in tech contexts.
There is no line. Expression is turing complete. That you might not like something I say does not have any effect on my right to say it as a human being.
Obviously the names are tongue in cheek jabs. There's no language called Auschwitz, afaik, and even if there was, it would have as much right to exist as Java or Python or whatever.
You don't get to tell people what to name things just because you're offended. You get to be offended, that's it.
> You don't get to tell people what to name things just because you're offended.
Sure you do, and you get to say your reasons too, refuse to adopt something based on those reasons and try to persuade other people and organizations to accept your reasons. You even get to apply mild sanctions - like not buying things from them or discouraging others from interacting with the person who did the thing that offended you.
You just don't get to forcibly compel anyone. If they disagree with your reasons and don't care about upsetting you, you can't make them change.
It seems that a lot of people want not just freedom to offend with their speech, but also freedom from the reasonable consequences of offending (including responding speech), which is even less coherent than wanting freedom from offensive speech.
This, thank you. So many people seem to think that freedom of speech == freedom from consequences. The reality is that freedom of speech == freedom from government consequences.
Kind of. That's the law of course. But freedom of speech, in America at least, is also a principle of our Republic. We should all strive to encourage this freedom. To attempt to quash someone from speaking their mind is morally wrong, and is actually un-American.
I genuinely struggle to think of a name that I would object to. I mean you could "name" your language a manifesto that I wouldn't want to be associated with, sure, but a name that's clearly (from context) acting as a name is just a name.
There are living people whose relatives were brutally killed by Stalin. He was responsible for more deaths than Hitler, if you ignore Hitler's role in initiating the wars.
It's reasonable to distance yourself from a bad name, just as many people have chosen to rename things that were named Isis.
In fact, ukrainians don't give a damn about few nationalists like this for whom it "hurts" and will never consider an origin of the language name, not to mention that idiotic [island name - country name - evil status] associativity. Most people in the world are sane, please don't get tricked into internet-bs easily.
I looked it up, and Kotlin is an island (https://en.wikipedia.org/wiki/Kotlin_Island) 1,000km north of Ukraine. Is it a case like Alcatraz, where the location has become idiomatically synonymous with the facilities?
Kotlin is a place where https://en.wikipedia.org/wiki/Kronstadt was founded. You can say that Kronstadt become idiomatically synonymous with the facilities. Not too sure about the Alcatraz, but Kronstadt is the pride of Russia (and I doubt many people would be happy to see it being compared to a prison-island, lol)
I have no issues with Kronstadt.
Kronstadt also is the germanic name of Brasov in Romania. Lovely city. There are probably many other Kronstadt's.
It just means "Crown City".
It's worth remembering that different names have different connotations to different people. And that different things may have the same name.
If you are trying to market something you obviously have to keep in mind the connotation to the name to the target demographic. And if someone outside your target demographic complains about the name you probably don't care.
On the other hand, in the land of open source those connotations are meaningless. Creators of open source tools don't really rely on marketing.
> Here in Ukraine it would be very hard to get adoption of a programming language that is named after a Russian military base.
This sounds really stupid, considering that many Ukrainian programmers are already using JetBrains products and that punishing a great company for the actions of politicians is kind of sad.
Equating a programming language named after a Russian island to Hitler is a real stretch, unless you think that everything Russian is like Hitler. It's just an island and a language named after it.
maybe the appropriate US version is "Pearl Harbour" - how would you feel about a language called PearlHarbour, and can see a situation where a (non-technical) hiring manager would take issue with that appearing on your CV?
> maybe the appropriate US version is "Pearl Harbour"
That doesn't quite work—Pearl Harbor was a US base, so most Americans would be okay with it. The negative associations we have with it are what was done to it & the people who served there. We're not angry or upset about the base itself.
> I think I wouldn't necessarily put that I use Hitler on my CV, due to the negative feedback I would receive from others not in the field.
But Kotlin IS NOT equivalent to Hitler AT ALL, Kotlin is like if you named your programming language "Texas" and somebody objected to the name, because "there are defence contractors located in Texas".
What does the name of an individual have to do with that of an island?
Wayland: I think it's the name of some America place. Should afghans, syrians, viets, [put whatever country the US invaded] stick to X11 because of this?
I think it depends on more nuance than that: I do think it would be reasonable for people to avoid a language called Guantanamo because of the name associations. Wayland happens to be a place in MA but I'm from near there and even I had no idea or prior associations with that name because of the place.
And Guantanamo Bay is a bay besides also having a base there.
I know nothing of Kotlin's specific name associations, but I don't think "it's the name of a place, therefore its fine" is valid in general. I think "Sandy Hook" would be an inappropriate name right now, while "Wayland" is fine, despite both being towns in the same general region of the world: one name invokes something specific in peoples minds and the other does not.
Its sort of like how its generally not a good idea to be named "Isis" right now, despite having plenty of harmless associations unrelated to ISIS. You might be named after the Egyption god but you are still invoking an association that you don't really want to:
Hitler is universally offending and I would question the motives of its creators. OTOH, I couldn't care less if a language would be called gomix or ibne (same word in Turkish) or fag.
It's not though, and there are many cultures in the world where people are so far removed from what happened that they don't have an understanding of why people would be upset about it. See:
I have a friend who's called, quite lovingly so, Hitler in our circle. The nick has nothing to do with any of his beliefs or opinions (we wouldn't be friends if it did). The icing on the cake is my kids talking about "uncle Hitler", that's just laugh-your-way-to-coma material.
Well, you already have java formal verification tool named Bandera http://bandera.projects.cs.ksu.edu/people.shtml (which name is obviously choosen by Oksana Tkachuk, one of the tool authors)
As a native Spanish speaker I'm not aware of any negative connotations of the word bandera. In Spanish it just means "flag", so any other meaning is hard to google for. What am I missing? Just curious.
If you want to piss off a clinical... eww, not a russian, but a post-soviet russian-speaking citizen of Russian Federation (with a little putin in his head), you may place a Stepan Bandera photo on your userpic and name youself as ukrainian nationalist.
If you want to piss off a real ukrainian nationalist, you may use a Stalin phono, or any other communist leaders.
From the point of sight of normal people, both of these sides is braindead. "A plague on both your houses".
Kotlin is just the geographic name of the island. A "military base" (Baltic fleet admiralty headquarters, which is military, but not "base") is located there, but it's location is the fortified city named Kronstadt.
I am a pro-Ukrainian Russian, and I know many Jetbrains employees, who are cool and bunch of hackers and totally apolitical. Don't worry, it is kosher. :)
I think the effect on adoption will actually be small. Most Ukrainian developers won't realize or won't care the island the language is named after houses a military base. Going by my experience, they will also have few qualms about using a language controlled by a Russian company. (Note I am not judging them positively or negatively, just predicting their behavior.)
Which is actually not the case for most Ukrainians of Russian descent:
Most of ethnic Russians in Ukraine signed for the
Ukrainian army, fighting against Putin’s invasion,
against the same Russians that came from the other side.
Less so though, as USA was from the onset a nation of hodgepodge nationalities from everywhere -- and without a much older local culture (except of the Indians, which were genocided away).
It was the constitution/law that held US together as a nation instead of a shared history/culture (well, except WASP culture, which is on the wane).
Russian descent appears not to be a necessary condition for a Ukrainian to "root for the home team". (Neither is it sufficient. But it does correlate.)
Ironically, the name "Kiev" would be no less offensive becuase this spelling of the name implies that this is a Russian city, not a Ukrainian one. The official and correct spelling is "Kyiv", see http://kyiv.of-cour.se/ for explanations why.
Ironically, the name "Kyiv" would also be no less offensive since it is written in Latin characters non native to Ukraine instead of the Ukrainian alphabet, which is a derivative of the Cyrillic alphabet. The official and correct spelling is "Київ"
Totally not. Many newly-installed signs in Kyiv are bilingual, in Ukrainian and in English. We have official rules for transliterating Cyrillic into Latin which the government uses.
>Ironically, the name "Kyiv" would also be no less offensive since it is written in Latin characters non native to Ukraine instead of the Ukrainian alphabet, which is a derivative of the Cyrillic alphabet.
Pedantically it would be much less, even none at all, offensive, since nobody will care whether a programming language's name is not written in Cyrillic, since the latin alphabet is the default for such names anyway.
> The official and correct spelling …
I think "official" and "correct" are two different things especially in countries where social networks and other internet services are prohibited like Ukraine.
Social networks, as a whole, aren't prohibited in Ukraine. Only a couple russian internet services are blocked as part of sanctions against Russia. Because of the... you know... war.
Kotlin is just an island. This name known from 17th century and have germanic-scandinavian origin - Kettusaari - Ketling inseln - Ketlingen - Ketling - Ketlin - Kotlin.
I don't think so. The main concern for someone with anti-russian stance would be using Russian tech at all, not it's name. But I don't remember JetBrains ever doing anything to align themself with state politics and it's not like one has to buy anything from them to use Kotlin. So I don't see it as a major factor.
> Here in Ukraine it would be very hard to get adoption of a programming language ...
just for curiosity, do you still have access to Internet and https://github.com/jetbrains/kotlin?
I have heard that social networks and many other services in Ukraine are prohibited by the government (after prohibiting other media like TV and newspaper) and now people are installing VPN and other tools by using experience of China to overcome these obstacles. Is it so?
Ukrainian here. Where did you hear that? Don't read news there anymore, they manipulate you. Ukraine introduced sanctions against russian businesses on its territory. As part of those sanctions, websites of three major russian IT companies have been blocked. That included Yandex (which is very similar to google, also has a lot of web services), and a couple of russian social networks.
I can say the same. Those services that were banned are either the most outrageous war propaganda outlets, or honeypots that gather intelligence information (imagine half of all Ukrainians communicating via a social network that is fully controlled by the enemy).
Kotlin does not have any of these (edit: this is now partly false, see below)
I'm sad that Google is supporting Kotlin and not Swift or Scala for Android, since at least with the latter two, you can use functional programming.
Edit: Actually, I'm looking into Kotlin again, and it looks like it's greatly expanded support for functional programming compared to a year or two ago. For example, algebraic data types can now be encoded in a similar manner to Scala, and kind of pseudo-pattern matched using `when`. TCO is now supported. There are lambdas, and support for closures. Destructuring assignment. But as far as I can see, still no immutable values (just immutable references), and no way to make extensible type classes, like in Scala and Swift.
I'm definitely going to take another look now. Last I checked a few years ago, Kotlin had very limited support for functional programming.