Introduction
“While the community was skeptical that this new method could possibly outperform hand-coding, it reduced the number of programming statements necessary to operate a machine by a factor of 20, and quickly gained acceptance. John Backus said during a 1979 interview with Think, the IBM employee magazine, "Much of my work has come from being lazy. I didn't like writing programs, and so, when I was working on the IBM 701, writing programs for computing missile trajectories, I started work on a programming system to make it easier to write programs." (http://www.msnbc.msn.com/id/17704662/#.UGx3_K4QHVE)
John Backus didn't like writing programs, so he created a high-level programming language (Fortran) :) High-Level is of course relative. What we once called high-level (C, Fortran) is now low-level. You see this is happening to Java too. Mister Backus should have had Kotlin then he would had more fun writing programs. Still, I agree with him that the goals are programs, not writing programs. It's exciting to see how Kotlin develops to a new high-level JVM language to achieve this goal fast and without drawbacks. Especially because the current version already works very well and new stuff will be discussed in the webinar. Unfortunately I can't make it to the webinar tomorrow, but I hope that a recorded version will be available.
It all reminds me of the beginning of Firefox. Already at version 0.3 (when it was still called Phoenix) Firefox was better than IE (it had already tabs, a bookmark manager etc). Then there was the powerhouse Opera. It had everything under the hood and more, but it didn't gain market share. I've chosen FF because it was light, but expandable and it worked with most websites (while Opera didn't parse websites written for IE very well or not at all). I was not the only one. Firefox gained slowly market share, because of its open source nature (building a community that participated), code base (Netscape), extensibility (plugin framework, xul etc), but most important because it improves on every feature IE had and innovate on new ones.
This was all on the browser market. Comparing this situation to programming is another piece of cake. For programming there is more history, harder to migrate, more competing languages, less users. You could say that besides the giant Java (IE) and powerhouse Scala (Opera) there is a lot other languages to compete. Think of new kids on the block Xtend and Ceylon, but also Groovy, Fantom, Jython, JRuby and that's only one the JVM platform. To grow as a language the stakes are high and thus to create a snowball effect, the mountain to choose must be steep and high. Scala seems one step forward from Java, but Kotlin oneandhalf. Is this enough to walk away?
I don't know, but from the few Kotlin programs I wrote Kotlin is doing really great in creating the snowball that will in time become 1.0. In this post I wrote down some ideas to stimulate development even further. It's all written from the perspective of the lazy (or ignorant ...) programmer. I think this is the right attitude, because the lazy programmer is not lazy because he is afraid of work, but wants to achieve something in the fastest and easiest possible way.
Around the language
Not just the language, but the infrastructure, community and tooling are just as important to succeed. Most new languages tend to neglect this area (or just haven't enough people and infrastructure for it). Jetbrains is doing this very well in my opinion by integrating the language into IntelliJ, setting up a homepage with documentation, api, forum, blog, issue tracker, web demo, social media and FAQ. Last but not least there is the kontributor program. I hope this will succeed as I wish that the community can freely post code, libraries, functions, ideas etc on the Jetbrains infrastructure, so resources are centralized and not scattered like with Java. Below are some thoughts and ideas on infrastructure and tooling.
Infrastructure:
- Get a search from the main page (to search through all language resources)
2) Let developers vote for ideas (Like KDE’s brainstorm http://forum.kde.org/viewforum.php?f=83). Vote for solutions doesn’t mean the end decision has to be democratic. It’s up to the dev team to approve it at the end)
3) Clear and central Package Index (For example like http://pypi.python.org/pypi)
4) Tooling page with links (i.e. like http://www.sqlite.org/cvstrac/wiki?p=ManagementTools)
5) Combining documentation (the explanation), API (the structure of the funtions and classes) and working examples (that can executed right away in the IDE)
6) Documentation/API that is easily searchable (functions, libraries or keywords). More like Google than it’s right now with Javadoc (something that doesn’t hurt the modern eye).
7) Let users give direct feedback link in the webdemo. So when people run into something they can give feedback on the documentation, a function that they miss, an error they cannot understand and so on.
8) Use statistical analysis in the webdemo to find out where people run into.
Tooling:
1) Simple way to keep my code in sync with the latest version of the compiler. (Option to autoupdate the code and compiler just like updating Google chrome)
2) Three channels
Stable --> Production use (stays backwards compatible after 1.0)
Beta --> Test ideas that make it in the main language
Alpha (Playground) --> Testbed for programming ideas and new implementations (need not to be backwards compatible)
3) Use the source itself to derive the build instructions (like Google Go) and for autodocumentation.
4) Give documentation for every function at least one standalone working example (instead of have to look all over the internet).
5) Show only the root cause of an error (not the errors that because of just this error) (Have a clear divide)
6) Optionally give suggestions and tips on types of errors. A "did you mean" might be annoying and can make the programmer lazy ("Languages that try to disallow idiocy become themselves idiotic." --Rob Pike), but on the other hand who hadn't spent hours after realizing you missed a white space, misspelled something, copy-paste etc.
What I find important in a IDE (Some is fortunaly already is in place):
1) Live parsing of the code / Instant results
2) Fast or immediate deployment (Like JRebel)
3) Code inspection / optimization / tidy / clean (for example unused import and variables)
4) Debugging and project Management
5) Version Control Support (most notably SVN and GIT) → Integrating with Hosting site like Google Code, GitHub, SourceForge.
6) Plugins
7) Installer creator / Fat jar (don't let the user ever give bat/sh to start a program, don't bother him with paths/classpath). I still see this at new Java projects.
8) Search
9) Refactoring
10) SQL / Xquery client
11) Automatic closure creation
12) Use fragments or working sets instead of files
13) Live Syntax checking like MS Word
14) Code mode (only the code like Scite / Ecacs)
Eclipse and Netbeans are quite ok, but there also downsides. Netbeans breaks functionality the whole time, Eclipse is cluttered and slow. So now I am using IntelliJ, but there are some others that have interesting features too. For example Light Table, Scite/Emacs (don't got you off the code), Visual Studio, Mendix Business Modeler, Xdev, Progress OpenEdge and Wavemaker. Not all of these features suits Java/IntelliJ, but they might be very useful for Kotlin.
Round Trip Engineering
There are several aspects that can be modeled or designed very well, for example:
User interfaces
Web pages
Datamodels (ER-diagram)
Objectmodel (Classdiagram)
Flows
Reports
Sometimes it's however more convenient to write something in code. It would be inconvenient if you manually need forward and backward reengineering between code and model. It would be much nicer to have a design view and a code view that are in sync (For example http://www.uml-lab.com/en/uml-lab/ does this with UML and Java code).So design and source are just two perspectives on the program, instead of separate entities. In this way the model view is just part of the language. It maybe helpful to have some special language constructs that are derived from for example UML so that both perspective fit together.
One other perspective could be Java code. There is a lot of example code out there and so it maybe useful to synchronize (instead of convert) between Java code and Kotlin code. So then we have design, source and Java as tree perspectives to code in.
Modularization
To make the round trip engineering possible we probably need some additional framework and engines like the following:
Designers for GUI / creating queries / creating reports
Embedded engine / processors (in the application):
Database (i.e. H2, HSSQL or noSQL)
Query (SQL, XQuery (Zorba, Saxon))
Workflow Engine (i.e. Yawl or Activiti or jBPM)
Security (CRUD)
Forms
Webpage/CMS
Knowledge Base / Documentation Management
Debugger
Office support (word, tables, diagramming)
Embedded search engine (Lucene)
Wouldn't be nice to have these types as language modules, so the developer can decide what paradigm it will use (imperative, functional, object-orientated, aspect-orientated, data-driven etc).
So the following language constructs:
None (Imperative/Scripting)
Function{}
Object{} (Well the PoJo's)
Interface{}
Types → User
Data
Delegate
Data{}
Types → Relational
Document (JSON, XML)
Object
Columns
Aspect{} (Think of AspectJ)
Types → Authentication
Autorisation
Cryptography
Cache
Configuration Management
Session Management
Log Management
Validation
Notification
Error Handling
Dependency Checking
Transaction
Tracing/Auditing
Performance
Instrumentation
Internationalization
Fault Tolerance
Scheduling
(Etc, as long as it a cross-cutting concern)
Extensions{}
Type → Custom made DSL
Extension would support creating, embedding and using special purpose language which can be for example:
Query and data languages like query languages (SQL, XQuery)
Data structures (XML, JSON)
Mark up (html 5, css,tex)
Scripting (Powershell, Bash, Lua, Tcl)
Transformation (xslt)
Gui (Visage)
Build (Gradle)
System programming (C, Go)
Regular expression (Regex)
Logic (Prova)
Typesetting (Tex)
Graph visualization (Graphiz )
Or an own DSL (For example with the MPS technology http://www.jetbrains.com/mps/). Possible patterns are on http://martinfowler.com/dslCatalog/.
Some notes
1) For data there would be a common interface to all databases like http://metamodel.eobjects.org/index.html
2) GUI interface could be declarable (like Visage) and visually design. Most import that it looks good, so AWT and Swing are not in the picture. SWT or QT-Jambi would be fine
Application Lifecycle Management
OK, now we had infrastructure, tooling and engineering. There is another important aspect mostly not covered when creating a new language and that's lifecycle management. Somehow (especially in a business environment) we need a way to make changes during different versions of our software projects.
So of course we need version control, but also continuous integration (like Jenkins), Issue Tracking (Trac, Redmine, Bugzilla), Test software, Requirements, Deployment (rolling on multiple server for instance) etc. Visual Studio has Application Lifecycle Management (http://msdn.microsoft.com/library/fda2bad5%28VS.100%29.aspx) and on Eclipse you have Tasktop (Mylyn). Won't it be great if not only the IDE, but also lifecycle management is developed together with the language.
Last but not least there are numerous methodologies like Waterfall, Scrum, Agile, Scrum, XP, RAD, DAD. Wouldn't be good if the language is so constructed to make application lifecycle management lighter. On of the best base to take is IBM's Disciplined Agile Development (http://www.disciplinedagiledelivery.com/).
The language
In the 0.3 post on the Kotlin blog I found the most exciting enhancement scripting/REPL. This is something I really miss in Java. I think this area could really set Kotlin apart in the sense that it makes Kotlin more general purpose. Also both scripting and OO support like Python makes a language easier to evolve from script to application. Besides scripting there are some other areas with maybe good to extend Kotlin with
1) Automation and scripting
2) Other paradigms
3) 4GL languages features
4) Datatypes
5) Libraries and documentation
In these areas Java (and Scala) are not a lot of help to look. You can think about the question why do people commonly think the following languages are easy to program in: Python, Ruby, (visual) Basic, C# (http://gamenacho.com/top-5-easiest-programming-languages/).
Automation and scripting
Scripting languages allow writing code without package, class or method declarations etc. Python and Ruby are good examples that scripting and OO are not mutually exclusive. The quickness to start and see result as you go (REPL) is great to win new users over. Scripting is popular because:
- Direct link with human tasks
- Interactive and fast feedback (results, debug)
- Glue between humans, apps and system
- Sketch a program, instead of writing a program (http://www.oreillynet.com/pub/wlg/3190)
- Less concern about machine details and language constructs (like objects)
- Good libraries for automating tasks (for example file libraries which don't need complex buffers and writers).
- Defaults: Why setting up a whole gui when you just can have a default window with the statement gui.create()?
Often programs start by automating a small task. Why change language when the application evolves? Why change language after a prototype? And more important what makes scripting languages so quick in rapid prototyping? Of course with scripting you can find multiple variant like
General Scripting: Python, Lua, tcl, groovy
Browser scripting: Javascript, Dart
Automating script: Autoit, AutoHotkey
Automating builds: Ant, Gradle
Shell scripting: bsh,Powershell
So I really am curious how scripting will land in Kotlin. Right now we can write the following code (99 bottles of beer):
fun main(args : Array<String>) {
for (n in 0..99) {verse(99 - n,98 - n)}
}
fun verse(n : Int,n2 : Int) {
print(when(n) {
0 -> "nNo more bottles of beer on the wall, no more bottles of beer.nGo to the store and buy some more, 99 bottles of beer on the wall.n"
1 -> "n1 bottle of beer on the wall, 1 bottle of beer.nTake one down and pass it around, no more bottles of beer on the wall.n"
else -> "n$n bottles of beer on the wall, $n bottles of beer.nTake one down and pass it around, $n2 bottles of beer on the wall.n"
} )
}
But with scripting we code make it even shorter like this:
for (n in 99..0) {verse(n,n-1)}
function verse(n,n2) {
print(when(n) {
>2 -> "n$n bottles of beer on the wall, $n bottles of beer.nTake one down and pass it around, $n2 bottles of beer on the wall.n"
1 -> "n1 bottle of beer on the wall, 1 bottle of beer.nTake one down and pass it around, no more bottles of beer on the wall.n"
0 -> "nNo more bottles of beer on the wall, no more bottles of beer.nGo to the store and buy some more, 99 bottles of beer on the wall.n"
} )
}
Other paradigms
You see that functional approaches (and with good reason) are gaining momentum on the JVM platform. There are however some other interesting areas which are not covered a lot:
1) Lisp programming have a lot of good ideas (They have closures for ages). Clojure as a direct dialect of Lisp brings this to the Java platform. Definitely should Kotlin not only compete with for example Ceylon, but also with Clojure.
2) Rule based programming. Especially when working with natural languages or expertise software this kind of logic constructs are very helpful (see mandarax http://mandarax.sourceforge.net/ / prova http://www.prova.ws/)
3) Aspect-based programming; separation of cross-cutting concerns is the best thing since sliced bread and definitely keeps your code cleaner, as these concerns don't fit into objects or functions (http://www.eclipse.org/aspectj/)
4) Declaritive → Especially when looking at special purpose language (gui, query, regex etc) this way of programming clears sides-effects.
There are a whole lot more, but seems to be the most important to extend kotlin with.
4GL
One other area which is largely lacking on JVM is 4GL. Ok, 4GL sounds really eighties and doesn't real programming gets done in 3gl? Yes, but what about successful 4gl languages like Progress ABL, Clarion, Lansa, EGL. What I like is the focus on the end developer experience, lots of natural language constructs (FIND ALL RECORDS WHERE NAME IS "SMITH" ) and bring development closer to application.
Type system
I'm glad that there are no primitives as in Java as they are only confusing. Kotlin choose a static approach which is good when writing business applications. The question is this always necessary? In dynamic languages like Groovy and Python you have the option to compile statically. Haxe and Fantom are trying to find the right balance between static and dynamic (see http://haxe.org/ref/dynamic and http://fantom.org/sidewalk/topic/1581). Will there be options available on Kotlin or will it remain strictly static?
Entry point
Some remark about the main function. Why does there be a main (entry point) like this
main(args : Array<String>)
Why does a language need a function that is called main (if not there just imply one and call the first given function. In this way scripting will be easier). If you need an entry in larger projects you can of course use main. Also why we need "args : Array<String". If none is provided main() then it means that no parameters can be given (like main in Google Go).
Libraries and documentation
"I personally think it's the Java ecosystem and its libraries that needs to get thrown away, not the Java language itself. I think this will be especially true once Java finally gets closures. The Java culture has created an ecosystem of libraries that are often what I like to call "over abstracted, and under powered". That is obviously a blanket statement that doesn't apply to all Java frameworks or libraries. But when I look at Java projects, to me the greatest source of complexity isn't the bloated Java boiler plate code, but rather the fundamental design of the libraries and code itself. The Java culture rarely bases its design on simplicity. And the result is that Java projects tend to be massive teetering towers of 100s of "modules", each with own huge surfaces areas. " Brian Frank (Fantom)
I think Brian has a good point here, but personally I don't think that the language as well as the ecosystem should be thrown away. It is a good foundation to radical improve both :). But when I would have to choose what is most important than it would be simple, powerful and consistent libraries. The verbose or bad syntax you can get over it (this is mostly the toughest for beginners), but in practice most of time you spent with getting these strange libraries working.
For example I like the built-in xml library of Scala, but it's not always a pleasure to work with. The same counts for Java with date and times, so I hope Kotlin will have the 310 efforts built in (http://sourceforge.net/apps/mediawiki/threeten/index.php?title=ThreeTen). Important is that the experience across multiple libraries is consistent and instead of let the user define everything, use sane defaults (that can be changed of course).
Java interoperability is a strong asset. On the other hand it's a dangerous feature, because users may tend to look for existing java classes, instead of creating 'native' kotlin libraries (classes, functions). Good and clear guidelines for kontributing libraries are needed as well as review before a library get a higher status.
I also think that nowadays the core library can be larger (if you really need something that compact than use C). I don't want to import all those libraries to do just simple things like string manipulation or working with dates. For other things there could be an autoimport (that searches in the project folder and automatically set a classpath if needed).
Functions and naming
I can use a String object by assigning it as follows
var x = “text”
Accordingly I can do something like this to reverse the string to get “txet”
x.reverse()
This way you are dependent on proper naming of the variable to see what's going on. For example x says nothing and when the assignment and usage are far from each other it's hard to read. What is reversed? For me string.reverse(x) would be clearer, so you have functions like this:
string.compare(string1,string2)
string.concat(string1,string2..stringN) or string & string
string.contains(string1,substring)
string.equals(string1,string2..stringN) or string1 = string2
string.find(string1,substring)
string.format(string,format)
string.inequals(string1,string2) or string1 != string2
string.join(separator, list of string)
string.left(string,0,n) or string.substring(string,0,n)
string.lenght(string)
string.lowercase(string)
string.uppercase(string)
string.split(string, separator)
string.replace(string,find,replace)
string.reverse(string)
string.trim(string,parameters)
string.duplicate(string,times)
And so on. All with normal common sense defaults and this can be changed with parameters. Instead of setting all from the ground up. Another library to work with windows
win.activate Activates (gives focus to) a window.
win.active Checks to see if a specified window exists and is currently active.
win.close Closes a window.
win.exists Checks to see if a specified window exists.
win.flash Flashes a window in the taskbar.
win.getCaretPos Returns the coordinates of the caret in the foreground window
win.getClassList Retrieves the classes from a window.
win.getClientSize Retrieves the size of a given window's client area.
win.getHandle Retrieves the internal handle of a window.
win.getPos Retrieves the position and size of a given window.
win.getProcess Retrieves the Process ID (PID) associated with a window.
win.getState Retrieves the state of a given window.
win.getText Retrieves the text from a window.
win.getTitle Retrieves the full title from a window.
win.kill Forces a window to close.
win.list Retrieves a list of windows.
win.menuSelectItem Invokes a menu item of a window.
win.minimizeAll Minimizes all windows.
win.minimizeAllUndoUndoes a previous WinMinimizeAll function.
win.move Moves and/or resizes a window.
win.setOnTop Change a window's "Always On Top" attribute.
win.setState Shows, hides, minimizes, maximizes, or restores a window.
win.setTitle Changes the title of a window.
win.setTrans Sets the transparency of a window. (Windows 2000/XP or later)
win.wait Pauses execution of the script until the requested window exists.
win.waitActive Pauses execution of the script until the requested window is active.
win.waitClose Pauses execution of the script until the requested window does not exist.
win.waitNotActive Pauses execution of the script until the requested window is not active.
Also creating a simple gui windows could (creates simple window)
gui.create()
Kotlin Playground
One thing that Kotlin does well is that although improving Java, it stays familiar. Still I think, when something can be more general, simpler than you can give up this familiarity. Especially since there is not a 1.0 release there is a lot to experiment with. My suggestion is to get specialized branches of the mainline online (web demos) to introduce new ideas and controversial functionality. Here can people debate and test the implications of it.
Here is an example playground where I used:
- Different ways for assigning variables (similar to F#)
- Strings without quotes
- Reactive programming
- Compact and verbose mode
In the IDE I used colors to distinguish between different kind of variables
black --> no variable (string literals)
blue --> assigned variable (light blue = var, dark blue val / constant)
Instead of colors one could also use sigils (for example $ like in PHP one would recognize which words are variables and which are not. But on this playground we choose colors. Also we assign variables as following:
x <- a (assign string or variable a to variable x)
x << b (concat string or variable b to variable x if exist, otherwise new assignment)
x -> a (assign string or variable x to variable a)
x >> b (concat string or variable x to variable b if exist, otherwise new assignment)
x <-- a (assign reactively string or variable a to variable x) *
x --> a (assign reactively string or variable x to variable y)
http://en.wikipedia.org/wiki/Reactive_programming
= (checks equivalence)
<=> (checks if objects are the same)
For objects it will be
foo <- new Foo();
Instead of
Foo foo = new Foo();
Operators: like = and + as operators are not used for assignment and concatenation, but for maths.
# one line of comments
() one or more lines of comments
As you may have noticed on this playground I also don't use quotes to define literals and let the interpreter/compiler work this out. So the following are some examples in a REPL environment with their (expected) result/
x <- a
print(x)
result: a
---------------
y <- hello
y << world
print(y)
result: hello world
---------------
x >> y
print(y)
result: a hello world
---------------
x -> y
print(y)
result: a
---------------
print(x a)
result: a hello world a
---------------
print(xy)
result: xy
---------------
print("x")
result: "x"
---------------
print(literal(x))
result: x
---------------
print(z)
result: z
---------------
x <- world
y <- hello
print(x y)
result: hello world
---------------
x <- a (assign something to x)
print(x)
result: a
---------------
y <- a
print(x + y)
result: aa
---------------
print(literal(x +) y)
result: x + a
---------------
print(x = y)
result: true
---------------
a <- b
b <-- a
print(b)
result: b
---------------
a <- c
print(b)
result: c
So let take a twist on this playground. Early I described that code, design and Java code could just be different perspectives on the same application. It's up to developer in what perspective he works. So we have
1) Kotlin code (Default view)
2) Java code
3) Design (Model view)
Now we add the following
4) Compact code (aka the abbreviation view)
5) Verbose code (aka natural language descriptions/pseude-code)
For example the keyword function would be shown different in each perspective
Compact code Default code Verbose code
fn fun function
Some more example for verbose code:
string (instead of str)
variable (instead of var)
constant (instead of const)
printline (instead of println)
error (instead of throw)
dictionary (instead of Hash, Hashtable)
boolean (instead of bool)
not (instead of !)
and (instead of &&)
or (instead of ||)
We now can write some code in one view and can see the results in other views as well. Let's for example try this with a function that converts a string to uppercase. In this example each function is connected to another by its definition
Default code:
fun StringToUpperCase(Param1){
Short: 2UC
Desc: Convert text to uppercase
Param1: text
// some function code
}
Compact code:
fn StringToUpperCase(p1){2UC,Convert text to uppercase,p1:text}
Verbose code:
Function StringToUpperCase(parameter 1)
Abbrivation: 2UC
Description: Convert text to uppercase
Parameter 1: text
// Some function code
EndFunction
Using this function you could have something like this
Default:
StringToUpperCase(word)
result: WORD
Compact view
word.2UC
or
x <- word
x.2UC
result: WORD
Verbose code
Action: Convert text to uppercase
Where: text is word
result: WORD
Another example. Let's say there is function called FileReadLine where the first parameter is the path + filename and the second parameter is linenumber
short: readln
description: Read a line of text from a file
parameter 1: path and filename
parameter 2: linenumber
Third line contains the text "Hello"
Compact mode
file <- /root/documents/somefile.txt
Default code
action1 <- FileReadLine(file,3)
if action1 = hello then print(hello)
Compact code:
if file.readln(3) = hello {pt(hello)}
result: Hello
Verbose code
action: Read a line of text from a file
Where: path and filename is /root/documents/somefile.txt (or file)
and linenumber 3
assign: result to variabele action1
Final note
So probably you don't want to use a certain perspective all the time, but it may be convenient in some situations. Only by experimenting we can find this out and some real unique features can be implemented into Kotlin. I don't know if my post adds something to that discussion, but if the devs takes one of my ideas or from remarks of the webinar that makes it easier to write programs you have my 2 cents.