What's your experience with Kotlin?

My team is deciding whether to switch to Kotlin from Java this year. I think that a lot of training can be done during the summer quarantine, and therefore, if there’s any year we’re gonna make the switch, this is it. In particular, I had the following questions for teams that use Kotlin:

  • Does it slow down your training process? How long does it take, on average, to train a new programmer in Kotlin, assuming most of their programming experience has been AP CS A or equivalent? How does this compare to Java?
  • Are Java code examples, such as the ones in the WPI Docs, still useful?
  • Thoughts on using Kotlin libraries such as Meanlib?
  • Any resources you found helpful for training?
  • Do you find VSCode efficient for Kotlin development, or is it worth setting up IntelliJ on everyone’s machines?
  • Any other things to know about switching?

Thanks!
Jared
Team 7461

5 Likes

I haven’t had experience with a full team switch to Kotlin, but I have played around with Kotlin code on a robot. I will definitely vouch for IntelliJ, even for Java, as IMO IntelliJ offers a nicer experience overall compared to VSCode (there’s a FRC plugin too).

Kotlin is pretty easy to pick up from Java, and after you pick it up there’s a LOT of QOL stuff. Kotlin is interoperable with Java so you pretty much call the same methods, so WPILib docs are still relevant.

I’ve never used Kotlin, but it seems to me that the biggest reasons to choose between Kotlin and Java is your team’s experience with the two languages, and which is officially supported. If you are confident in your team’s ability to work in Kotlin without external support, I recommend that you carry on. If you think you might need support when you get to competition, I’d suggest switching back to Java because ir’s one of the three officially supported languages.

3 Likes

@goldtooth

I’m struggling with these decisions as well, and also have the “it’s this year or never” condition. I totally agree with what others have said here already, but I’ll add a bit:

  • On the note of FRC team libs - write your own lib, don’t depend on a different team’s lib. What your team wants/needs different things in a lib than the team that wrote the lib you’re depending on. Also, I would look at FalconLibrary (5190) and SaturnLibrary (4069).

  • Kotlin in VSC is terrible, there is only syntax coloring (VSC Intellisense isn’t good, and Kotlin is even worse) - use IntelliJ.

  • We recruit before CS lessons start, so any CS students we have learn from FRC before the school lessons.

  • For resources I would use the official Kotlin website, there are examples and more. The playground is also a good place for programmers to learn the more basic parts of the language without IntelliJ.

  • I think examples are always useful, as they show API usage. However, if you have your own lib, examples are less useful.

  • About training times, it depends on how you plan to train new programmers. IIRC, 5190 is mostly self-learning and depends on a background - that doesn’t work for all teams. It also changes whether you plan on teaching Java or not - teaching two languages obviously takes more time, but has its advantages.

  • Decide if this point is relevant for you - students outside your team with programming experience might want to join, and can skip most of your team’s curriculum since they already have experience with java. Having to learn a new language might make them decide it isn’t worth the effort.

  • Kotlin is a much more “niche” language nowadays (unlike java), so if your team wants alumni to leave the team with tools/knowledge for the “real world”, Java is much more helpful than Kotlin as it is used much more.

  • What GeeTwo said about sustainability and support at comps.

1 Like

That I don’t agree with, Google is fully embracing Kotlin for Android development and it is the recommended programming language for it (over Java), and afaik most of the new Android libs are written in Kotlin.

1 Like

[Disclaimer: have programmed in several languages, including in Java since 1.0]

Probably the most important question when switching languages is: what is it you are hoping to get out of the switch AND how likely is it that will be worth the cost of converting (and do you even have a good estimate of what that will be).

[My personal opinion of Kotlin]
It has a couple of good ideas, but seems to value writability over readability (as for example Perl did). As a former manager of programming teams, this gives me pause.

I’m not convinced that Kotlin’s approach to NPE is the panacea it’s made out to be.

YMMV

1 Like

Few panaceas ever truly are.

Definitely agree: try it out for fun in the off-season if you have time. But before you wholesale shift, makes sure you know and understand the end benefit that you will get from switching. Find some way, either quantitative or “gut feel”, to judge how much of that end benefit you actually achieved.

1 Like

Been developing in Kotlin for over a year for my job in Android Development. Honestly love the language, especially over Java. The syntax is very readable, and you don’t need the fluff and boilerplate java requires. But at the same time, they have removed some things about java that made it hard to read, like the ternary statement, instead, suggesting inline if/else statements. A little longer to write, but I tend to avoid ternary statements except in the simplest of cases because of how hard they are to comprehend at a glance.

When I’m developing in different languages, I also sorely miss being able to assign the results of various statements (like if/else or switch) directly to variables. Like val variable = if(x) y else z

Overall, it is a breath of fresh air. That being said, I have not suggested my team to move to it over java. Mainly because I am the only one with experience with it on my team, and it is not worth my own time when we have a programming team that is very well versed in teaching Java. Very proud of the work they have done.

Do whats best for your team. Kotlin support in the FRC community is very low, so you’ll be working with a very small community. But for some that is what causes the drive! I love seeing FRC Kotlin projects.

1 Like

Isn’t that just an ugly int variable = x ? y : z;

3 Likes

Java is currently used more than Kotlin…

Either I was confusing, or you didn’t read my entire comment.

But at the same time, they have removed some things about java that made it hard to read, like the ternary statement, instead, suggesting inline if/else statements. A little longer to write, but I tend to avoid ternary statements except in the simplest of cases because of how hard they are to comprehend at a glance.

I showed the simplest example to be terse. But lets translate the same statement between kotlin and java to show it’s use.

val variable = if(foo) {
    x
} else if (bar) {
    y
} else if (blah) {
    z
} else {
    a
}

Now java using the, apparently, less ugly ternary statement.

int variable = foo ? ( bar ? ( blah ? z : a) : y ) : x

I’m honestly not sure if I did that right because ternary statements are so utterly useless once you have additional conditionals.

Edit: Turns out I didn’t do it right. I reversed the true and false results. Leaving it for posterity.

And of course you wouldn’t use a ternary statement in that case. You would say

int variable;
if (foo) {
    variable = x;
} else if (bar) {
    variable = y;
} else if (blah) {
    variable = z;
} else {
    variable = a;
}

Or you might use a switch statement, which has the same drawbacks in java, now with additional break keywords. In kotlin, it’s replaced by the when statement that has the same benefits I showed before:

val variable = when {
    foo -> x
    bar -> y
    blah -> z
    else -> a
}
3 Likes

The thing about arguing for the general applicability of a language in industry is that in reality what you’re using in industry is going to depends on so many factors. How “niche” a language is doesn’t really matter if that’s what you need for a job. In my mind it’s basically a lie to tell a new programmer that they’ll need to work in only a single language.

Ask me about the year I spent working with Pro*C…

1 Like

It is exactly as easy to write unreadable Java code as it is to write unreadable Kotlin code; switching to a new language will not change the discipline in your codebase.

4 Likes

Kotlin is a great language. It’s approach to NPE eliminates the worry of NPEs completely. It’s use of operator overloading and more modern approach to language design really make coding in it a breeze.

With that in mind, choosing a language for an FRC team should not rely on any of those factors. It should rely solely on - how well do the students on the team know said language and how well can you teach the students said language.

To expand a bit, FRC programming is very domain specific. You generally are not writing sprawling codebases (cough 254) where the increased benefits/disadvantages of any language (excluding maybe LabView) on a technical level matters. What matters more is how well the FRC libraries are available for your language, and how well it can be used.

1 Like

Emphasis mine - I think this is confusing two different topics.

There is certainly discipline needed in every language to keep code maintainable, and agreed, changing languages will not add discipline where it did not exist before.

However, there’s also elements of language design that can help drive certain behaviors. Depending on the application, certain languages might support features to help keep the code more streamlined and easily-comprehended.

I suspect John’s comments are targeted at the language features driving behavior he sees as less than desirable in his application, though I’ll let him speak for himself on the topic

1 Like

What elements would you consider that “code more streamlined and easily-comprehended”?

I know languages that make some things difficult (raw pointers in Rust, mutable state in FP languages, code bloat in non monorphized languages) in order to discourage them, but style is a thing that few languages can really enforce through it’s design (aka, I can write a nested if else chain in any language with if-else constructs, and even many without).

As a WPILib developer, I get to rewrite a lot of the same things in C++ and Java. I’ve noticed each language has an “expressiveness ceiling” for the solutions to certain problems. This seems to be a function of the size of the language’s toolbox and the problems they were intended for.

First, C++ can do zero-overhead unit conversions in the type system, and enforce correctness at compile-time. Units in the 2020 C++ controls classes were pretty seamless. In Java, on the other hand, our options were either spawn a bunch of objects to get GCed or annotate variable names with the unit (no type safety :slightly_frowning_face:). We went with the latter due to extreme GC overhead. You can see the impact on readability in the first C++/Java snippet on the trajectory generation docs page:

// C++
void GenerateTrajectory() {
  // 2018 cross scale auto waypoints
  const frc::Pose2d sideStart{1.54_ft, 23.23_ft, frc::Rotation2d(180_deg)};
  const frc::Pose2d crossScale{23.7_ft, 6.8_ft, frc::Rotation2d(-160_deg)};

  std::vector<frc::Translation2d> interiorWaypoints{
      frc::Translation2d{14.54_ft, 23.23_ft},
      frc::Translation2d{21.04_ft, 18.23_ft}};

  frc::TrajectoryConfig config{12_fps, 12_fps_sq};
  config.SetReversed(true);

  auto trajectory = frc::TrajectoryGenerator::GenerateTrajectory(
      sideStart, interiorWaypoints, crossScale, config);
}
// Java
class ExampleTrajectory {
  public void generateTrajectory() {

    // 2018 cross scale auto waypoints.
    var sideStart = new Pose2d(Units.feetToMeters(1.54), Units.feetToMeters(23.23),
        Rotation2d.fromDegrees(-180));
    var crossScale = new Pose2d(Units.feetToMeters(23.7), Units.feetToMeters(6.8),
        Rotation2d.fromDegrees(-160));

    var interiorWaypoints = new ArrayList<Translation2d>();
    interiorWaypoints.add(new Translation2d(Units.feetToMeters(14.54), Units.feetToMeters(23.23)));
    interiorWaypoints.add(new Translation2d(Units.feetToMeters(21.04), Units.feetToMeters(18.23)));

    TrajectoryConfig config = new TrajectoryConfig(Units.feetToMeters(12), Units.feetToMeters(12));
    config.setReversed(true);

    var trajectory = TrajectoryGenerator.generateTrajectory(
        sideStart,
        interiorWaypoints,
        crossScale,
        config);
  }
}

Note: Value types in Java would let us pivot to the former approach. See Valhalla.

Second, lack of operator overloading in Java makes math less readable.

// C++
m_xHat += K * (y - (C * m_xHat + D * u));

// Java
m_xHat = m_xHat.plus(K.times(y.minus(C.times(m_xHat).plus(D.times(u)))));

The geometry classes in WPILib for translations and rotations suffer from the same problem.

Third, value types in C++ and the general lack of the “new” keyword in idiomatic code means C++ robot code requires less typing than an equivalent Java version, and proper initialization is guaranteed (see RAII). The WPILib example projects demonstrate this across the board (C++ examples and Java examples).

Overall, I think Java’s expressiveness would massively improve by adding value types and operator overloading. Kotlin may get value types when Java gets Valhalla, but they support operator overloading now. Kotlin also has inline classes (experimental) to offer a zero-overhead unit conversion system.

1 Like