Will Java always be a prerequisite to learning Kotlin and other JVM languages?


#1

Perhaps I am getting ahead of myself since Kotlin is so new, but I’m very excited by the language. I’m a technical writer and I am playing with the idea of proposing a beginner’s book on Kotlin in a year or two. The absolute beginner’s market has kind of become my niche, but I am wrestling with a question if there is or ever will be such a market for Kotlin. It seems every alternative JVM language requires prerequisite knowledge on Java, and almost all documentation requires it too.

It makes sense that Kotlin would need a rapid widespread adoption to become a “first language to learn” candidate. But there will always be Java code in both legacy and new applications, and arguably Kotlin requires you understand the abstraction and the implementations that are done for you (hashcode/equals, delegation, etc)

Do you think Kotlin will become a good “first language”? Or will Java knowledge always be a prerequisite for the foreseeable future?


#2

Right now it’s true that all/most existing learning materials on Kotlin are focused on people with Java experience. This happens because right now Kotlin is focused on applications within the Java ecosystem, and we can save efforts by not explaining things that Java developers already know about. In the future, when JavaScript becomes a first-class supported target for Kotlin, we will no longer be able to rely on the fact that people already know Java, and we will have to explain everything from the very beginning.

It’s difficult for me to judge whether Kotlin is good as a “first language”, but if not, it won’t be because all documentation relies on Java.


#3

I have some written material that might fit into this category which I
would be happy to share with the Kotlin community. The approach is not
to consider Kotlin as an improved Java but instead a new language.
Experience in Java is then not expected. Since Kotlin is a JVM language
it will, of course, have need to refer to some aspects of Java.

The notes present a tutorial introduction to programming in Kotlin.
Numerous small examples are included to show how to exploit the covered
topics. In addition, some chapters include larger case studies that aim
to visit the topics in a larger setting.

Perhaps the community could offer some feedback.


#4

That makes sense. It must not be easy to determine if Kotlin is a “first language” when you work with it at such a low level. But I did buy your Manning MEAP book and I was pleasantly surprised how accessible and well-written it is so far.

I never thought of the Javascript side, and perhaps Android will be a driving factor for adoption too. I guess we will just have to wait and see how ubiquitous Kotlin becomes.


#5

I can’t speak for everyone else but I’d at least be curious to see. I read an article late last night discussing whether or not Scala can be learned as a first language. The author made a good point saying there is no such thing as a “perfect first language” because there are always nuances and everybody wants something different. Some beginners want immediate practicality and usefulness, and that may mean learning a language that is not “beginner friendly”. But the term “beginner friendly” itself is subjective, and what is deemed as a “beginner friendly” language may not be very useful to most people looking for practical, not academic, value.

It sounds like in Java’s early days, C++ knowledge was assumed.


#6

Have you seen “Atomic Scala” by Bruce Eckel? That’s a book trying to teach Scala as a first language, and apparently it has some amount of success.


#7

I have not but now I am interested in checking it out. Thanks!


#8

I think the issue with trying to learn Kotlin without knowing Java would be that Kotlin expects you to know the Java standard library. It’s own stdlib is tiny and only really extends Java’s. Learning Java is really only 20% the language and 80% the tools and libraries. Also, Kotlin code relies on Java libraries and build systems like Gradle/Maven, so by the time you learned all of that, learning Java itself is not that big a deal.


#9

That’s a valid thought, but at the same time couldn’t someone learn the entire package from scratch, learning both standard libraries with the objective of learning Kotlin? With the current documentation, what you say is true at least.


#10

I did a presentation of kotlin in Geneva last month. An attendee was a computer programming teacher and he asked me about my thoughts on using kotlin as the first langage to learn programming. I found the question interesting because I think kotlin is more natural than java. For example, to start your first program in java you have to write a public static void method in a class. So many awkward concepts just to write a hello world.

Using kotlin, you can start with procedural programming, move to OO, and finish with functional.


#11

Yeah I was working on two projects with Kotlin for the past week, and I started to think about that too. I am writing my second book with O’Reilly “Getting Started with Java” and I found it necessary at times to say things like “Do not worry what static means yet, we will cover that later in Chapter X”. It is cumbersome to force OOP onto a procedural/functional design and often beginners have to blindly implement boilerplate and trust that they will understand what it means later.

I think that is one reason Python is so popular as a beginner language, and Kotlin has the same benefits. What needs to happen though is beginners must be made aware of Kotlin. Otherwise they will choose Java, C#, or Python as a first language strictly due to popularity.


#12

That is an interesting point.

All languages require the programmer to understand at least some of the implementation that the compiler creates. Kotlin is not worse. Its abstractions/implementations are not tied to Java idiosyncrasies in a way that would be difficult for a layperson to understand. To use your examples, hashcode, equality, and delegation are universal problems (at least, in OOP).

But, Kotlin is definitely a superset of Java in that it has more features and more to learn. However if that doesn’t keep beginner C# books from being printed, then it shouldn’t stop Kotlin.

The real problem, for a beginner, is the Googlability of problems. Does putting common compiler error messages into a search engine produce useful results? What about uncommon?


#13

Touche on C#. That did cross my mind yesterday. And your latter point is probably due to language maturity and adoption, as well as Kotlin being marketed heavily towards Java devs at the moment.


#14

I think it is possible to learn Kotlin without learning Java first. However such a book would need to teach some Java to be able to use Java libraries. But since Kotlin and Java are pretty similar it should be sufficient to have a chapter about using Java libs in a beginner book. It would be like a chapter about using C libs in a Python book.


#15

There is nothing in Kotlin that would disqualify it as a first language.
Earlier, mention was made of efforts to promote Scala as a first language.
Unquestionably Kotlin is a simpler language and should be more accessible.
No higher kinded types. No implicits.

Kotlin has freed the function from the class so that it can play its full
part in developing solutions. That immediately opens the opportunity of
presenting Kotlin as an objects first or procedural first language. The
choice is yours. The first consequence is no more keyword soup in your
first hello world program!

Yes you cannot avoid the Java stdlib, but Kotlin’s stdlib only adds a
small number of extension. But a valuable set of extensions - no more
loops and temporary variables but simply:

val persons: List = …
val juvenileNames: List = persons.filter{p -> (p.age < 21)}.map{p -> p.name}

Nice.


#16

Good points. I think I’ve come to the conclusion that yes, Kotlin can be a first language. It will need to be marketed so there is awareness. But yeah the more I think about it I realize it arguably makes a better first language than Java.


#17

I taught a class last semester that tried to teach Java8 to college sophomores whose only prior experience was Python. (Many had Java7 in high school, many didn’t.) I dove directly into the functional aspects of Java8, and I forbade them from using most of the Java libraries. I instead had them build them up, from scratch.

With an approach like that, I imagine I could just as well have taught the very same class in Kotlin instead of Java8. Kotlin’s extension functions, alone, radically simplify a lot of the messy things that I had to have my students do. Now, the other professors here are insistent that the whole point of my class is teaching Java, and I can’t just go arbitrarily replacing Java with something else. So fine. We’ll stick with Java8 at least for now.

Honestly, the only place where Kotlin really shows the warts of the underlying Java system is type erasure. It’s at least something you can take advantage of for things like having a singleton-empty-list for all types of lists, but you have to do some sketchy annotations (either in Java or in Kotlin) to get the compiler to leave you alone.


#18

Do you have an example? The inability to cast and use instanceof comes to my mind, but not much else. You can go around that with reified type parameters (but it is a workaround, albeit comfortable).

I would have said that the parentage shows most in the API, esp. the collections API (haven’t really used the rest much) that has to be compatible with Java. Java collections are rather heavyweight and not very granular in their requirements (worse, some of the granularity is not encoded at the type level, but with Javadoc and UnsupportedOperationException). I would like to implement Map having just to define get, set (and maybe an iterator of entries, not sure), not having to return backing collections for keys, values and entries. This was well understood, and hence AbstractMap and AbstractSet. It’s hardly elegant and quite stupid: by default AbstractSet performs lookup by traversing an iterator…


#19

Here’s an example of a functional list class that I wrote in Kotlin (ported from a Java8 functional list class that I use with my college sophomores):

https://github.com/danwallach/K215-Export/blob/master/src/edu/rice/list/List.kt

The example I think you’re looking for is the way I convert a singleton empty list to a list of any type:

fun <T> List.Companion.makeEmpty(): IList<T> {
  @Suppress("CAST_NEVER_SUCCEEDS")
  val typedEmptyList = emptyListSingleton as IList<T>
  return typedEmptyList
}

The emptyListSingleton is an object of type IList<Any> which is cast to IList<T> here. This is safe because the only operations that might return an actual instance of type T will throw exceptions instead, and the rest generally do the obvious thing, e.g., the tail of an empty list is another empty list.

If you had reified generics, i.e., if makeEmpty<T1> needed to truly know that it was something different from makeEmpty<T2> (for T1 != T2), then you wouldn’t be able to have the one singleton empty list like this.

(Incidentally, putting the extension method on the companion object doesn’t seem to be standard usage for Kotlin, but it means that external users of the List class have a method that they get to by typing List. and then autocomplete will find the rest. This code was just an experiment of mine, but I’m curious if others have any thoughts about how you’d “properly” write a list class “from scratch” rather than the way kotlin.List wraps java.util.List.)


#20

Ah, I wasn’t judicious in my quoting. What I meant was example of “warts”. Like you said you can’t cast or perform instanceof. Reflection is also out.

Putting the extension method in the companion object is definitively judicious.

For linked list, I would have started like this:

import java.util.Collections

sealed class List<T>: Iterable<T>
{
    abstract fun isEmpty(): Boolean
    // more abstract methods

    class Cons<T> (val head: T, val tail: List<out T>): List<T>()
    {
        override fun iterator(): Iterator<T> {
            return object: Iterator<T> {
                var node: Cons<out T> = this@Cons
                override fun hasNext() = !node.isEmpty()
                override fun next() = node.head.apply { node = node.tail as Cons<out T> }
            }
        }

        override fun isEmpty() = true
        // implement more abstract methods
    }

    object Nil: List<Nothing>() {
        override fun iterator() = Collections.emptyIterator<Nothing>()
        override fun isEmpty() = true
        // implement more abstract methods
    }
}

fun <T> List(vararg elems: T): List<out T>
    = elems.foldRight<T, List<out T>>(List.Nil, { h, t -> List.Cons(h, t) })

val list = List(1, 2, 3, 4)

I’m not super convinced about needing an interface for linked list (your IList), it’s a bit specific. Also it’s rather too fat for my taste. Maybe make some of these interface methods extension methods instead*. At least consider giving them a default implementation.

(*) Although in that case they can’t be overriden in favor of a more efficient implementation. I would love a mechanism to be able to add dynamically dispatched methods to classes, which would alleviate this problem.

Dropping the interface also lets you use nice vals for head and tail.

As an aside, the type inference on foldRight was pretty nasty. I would have liked to write:

fun <T> List(vararg elems: T): List<out T> = elems.foldRight(List.Nil, ::List.Cons)

but ::List.Cons is a syntax error, and the type inference couldn’t figure out the types, which doesn’t seem right in this rather straightforward case. Casting List.Nil to List<out T> makes inference work. Replacing it by the nonsensical List.Cons(null as T, List.Nil) also makes inference work.