Kotlin gets support for S-expressions

Andrey Breslav

Please note that this post is an April Fool’s Day joke.

Kotlin is always happy to learn from other programming languages, and this is why we decided to support S-expressions, the empowering concept of LISP.

The main motivation behind this is the compatibility with Clojure, the LISP for the JVM. Clojure is well-known for its solid libraries, particularly the ones used for concurrency and read-only data structures.

To facilitate interoperability with LISP (and Clojure libraries in particular), Kotlin now allows expressions like this one:

 (println (
        (lambda (arg1)
            (+
                "first lambda: "
                arg1
                (lambda (arg2)
                    (+ "second lambda: " arg1 arg2)
                )
            )
        ) foo "bar"
    ))

This is only to give you the taste. Now, let’s explain the constructs one-by-one.

S-expressions explained

First of all, there’s only one new syntactic construct added, namely the S-expression. It has the form

(A B C ...)

where A, B, C … may themselves be S-expressions or other Kotlin expressions.

Now, most operations in LISP are written in prefix form, and if you want, you can write addition in this style in Kotlin:

(+ 1 two 3)

Note that literals (‘1’, ‘3’) can be mixed with other expressions (e.g. ‘two’).

LISP originally stands for LISt Processing, so the literals for lists are very important:

(list abc "def" ghi "jkl")

This create a list of four objects.

Normal Kotlin functions can be called in the LISP-manner, so to print the list above, we can say:

  (println
       (list abc "def" ghi "jkl")
  )

Lambda expressions also have a LISP-form:

(lambda (arg1) (+ 1 arg1 2))

And the following code demonstrates closures:

    (println (
        (lambda (arg1)
            (+
                "first lambda: "
                arg1
                (lambda (arg2)
                    (+ "second lambda: " arg1 arg2)
                )
            )
        ) foo "bar"
    ))

Try it out!

You can find the above examples (and some more) here. They are runnable, and you can play with the code. Disclaimer: it’s only a prototype.

Limitations

Unfortunately, at this stage our support for S-expressions is somewhat limited. Due to some issues connected with parsing, an S-expression can only be of odd length. We are working on removing this limitation.

Also, when defining a named function as an S-expression, its name has to be preceded with a dot (not to be confused with the Dot operator mentioned below):

(defun .baz (a, b, c) (+ a b c)) 

Dot Operator

Many of you were waiting eagerly for us to release the Dot operator. Now it’s implemented, compiler and IDE plugin are downloadable here, thanks to jgl87.

Comments below can no longer be edited.

21 Responses to Kotlin gets support for S-expressions

  1. Sergey says:

    April 1, 2014

    Where is my dot operator? You are promised it year ago !

    • Andrey Breslav says:

      April 2, 2014

      And there it is, look at the bottom of the blog post

  2. DloLoof says:

    April 2, 2014

    Are you sure you’re not going to literally fry some poor developer’s brains with these features?! That dot operator stuff is too powerful for mere mortals, and everyone knows lisp is impossible. I hope you have a strong limitation of liability statement in your licence.

  3. skin27 says:

    April 2, 2014

    Wow, this code even runs on the .Net backend! Unfortunately this will kill the keyword “fun”. Therefore I suggest for the final implementation something like this: (fun (main(args (Array(String()))))

  4. Ladislav Thon says:

    April 3, 2014

    I do know I’m writing this comment under the April Fools’ post, but I actually mean this: would you consider adding something like Scala’s for-comprehensions to Kotlin? It’s the best syntax sugar I’ve ever seen and it nicely supports all this mona*ic stuff that seems to be highly important in today’s reactive world. Pretty please? 🙂 I started on a prototype myself, but didn’t get much further than to parsing and type checking. Is there something like a lowering pass in the Kotlin compiler?

    • Andrey Breslav says:

      April 3, 2014

      It’s very likely that Kotlin will have something like this in the future

  5. John Kozlov says:

    April 3, 2014

    Did you steal this joke from ZeroTurnaround? http://zeroturnaround.com/rebellabs/frostbyte-the-new-jvm-language-from-zeroturnaround/

    • Andrey Breslav says:

      April 3, 2014

      Oh, that’s a terrific failure on our part. I forgot about this joke being made already by ZeroTurnaround. Apologies to them.

  6. Suminda Dharmasena says:

    April 7, 2014

    This is great. Is it possible to have Racket Redex / Racket, Typed Racket, Qi, Shen like meta programming / dilecting facilities. Also other interesting language to look at would be Red Language, Wolfram language and Mercury Language (Few 5th gen language available). Also the meta programming facilities can use term rewriting. Some languages using rewriting are Rascal, Metaborg, Pure. Also leverage your experience with Nitra and MPS.

    Ideal would be for Kotlin to have a simple core to which the syntax desugar to through meta programming.

    Also look at http://readable.sourceforge.net and Open Dylan to make it more readable.

  7. Mile says:

    April 23, 2014

    Why Kotlin tutorial hasn’t been updated with S-expressions?

    I’m wondering now, what else I’ll be missing if I start reading tutorial now?

    • Andrey Breslav says:

      April 23, 2014

      Please note the date of the publication of this post

  8. Mile says:

    April 23, 2014

    When I downloaded the whole tutorial tree, I got the file named “Kotlin-230414-1531-169424.pdf”.
    The name of the tutorial clearly points to today’s date and I expected to be updated for the latest Kotlin release, despite the fact that this blog is only 3 weeks old.

    E.g. look at this link in the tutorial: http://confluence.jetbrains.com/display/Kotlin/Compiler+Downloads
    It states “This page is no longer maintained”. Why you didn’t updated or deleted this page?

    Another thing I can’t find in this tutorial, is what version/build of Kotlin compiler it covers in full?

    Sorry for the off-topic. I wish you best luck for your efforts and work.

    • Andrey Breslav says:

      April 23, 2014

      What I meant by my comment is that this is an April Fools’ post.

      Otherwise, yes, the docs in their present state need many updates, and I hope to get around to updating them soon. Sorry for the inconvenience.

      • Suminda Dharmasena says:

        May 2, 2014

        Initially Parrot VM was supposed to be an April Fools joke but they in fact implemented it. Similarly this is something interesting to explore.

  9. Mile says:

    April 23, 2014

    Aha… But note that I haven’t read this article beyond its title.
    Also, I don’t consider your joke as a good style. Hope that you won’t update Kotlin tutorial in the same style as the “Poignant Guide to Ruby”.

  10. Guangyu HE says:

    June 24, 2014

    Would I ask a question here?
    I have written the following code:
    LocalDataBus.subscribe(“hello”) {
    val handler = it.annex as (m: Int)->Unit
    //val handler = it.annex as KFunction1
    handler(1)
    }

    And the type of it.annex is Any?, I want to have a check before have a type conversion by ‘as’.
    However, if I use ‘is’ to check it , I got a compiling error. How should I do to have a type check before the conversion?

    • Andrey Breslav says:

      June 24, 2014

      Since generics are not reified, you can not check whether something is exactly a function from Int to Unit. All you can do is check that it is some function that takes one argument, so Kotlin does not let you write a full is-check, only “is Function1”

      • Guangyu HE says:

        June 24, 2014

        Should I write it as:

        LocalDataBus.subscribe(“hello”) {
        if ( it.annex is KFunction1 ) {
        val handler = it.annex as (m: Int)->Unit
        //val handler = it.annex as KFunction1
        handler(1)
        }
        }

  11. Guangyu HE says:

    June 25, 2014

    I want to ask a question with Dependency Inject.

    For the code:
    [Inject] var ModuleName: String = “”
    ModuleName will be injected by DI Container.

    Can I write like this:
    [Inject] var ModuleName: String
    even:
    [Inject] val ModuleName: String

    • Andrey Breslav says:

      June 25, 2014

      At the moment you can’t, but we will do something about it.