Thursday, April 18, 2013

Pattern-Aware Formatting

During the last year I had the pleasure to implement a formatter for a programming language. You know, this little but incredibly useful thing that arranges indentation, line-wraps and whitespace in your code nicely. If you know me, you may have guessed that the programming languages in question is Xtend. Version 2.4.0 is the first version to ship with this formatter.

In case you haven't heard of Xtend, it is a language that compiles down to human-readable Java code and integrates seamlessly with any Java project.

We like to advertise Xtend as a language that is more concise and expressive compared to Java. And indeed it is, due to powerful type inference, higher-order functions, and less syntactical noise. Furthermore, Xtend supports concepts that provide a great degree of syntactical freedom to the developer. Among them are extension methods, operator overloading, and an implicit variable called "it".

This conciseness, expressiveness and syntactical freedom gives a great deal of power to the developer. This is a power a developer can use to increase his/her efficiency and at the same time write code in exactly that way that he/she considers the most readable to a human. It makes Xtend a perfect match for internal DSLs.

This has interesting consequences for formatting:

  • People who care about the readability of their code do have a strong opinion about formatting. This is easy to explain: Unformatted code just isn't readable.
  • But the strong opinion is about more than just having the code formatted. It's about having the code formatted in exactly the way they consider the most readable. Suddenly the formatting strategy doesn't depend on which syntactical element is being formatted, but on how a syntactical element is being used. This is an interesting thing I had to learn, as it is completely different from how the Eclipse Java formatter does its job.

The question is, how can a formatter decide how a syntactical element is being used? The amount of APIs, internal DSLs and programming styles converges to infinite, so there is no way of considering all of them. However, there are a small number of recurring formatting patterns.

Example 1: The If-Expression

This is probably how you would express it in Java: Imperative programming style and formatted as one line per statement:

var String z
if(variable == 1)
  z = "it is one"
  z = "it differs from one"

In Xtend, however, the if-statement is actually an if-expression, i.e. it has a result value. Java has an If-Expression as well, it is the ternary operator: (variable == 1) ? "then" : "else". Instead of assigning values inside the bodies of the if-statement, we can directly assign the if-expression. Besides being more concise, this has the tremendous advantage that the variable can be immutable and will never exist in an uninitialized state. Here is the snippet, we choose to keep the formatting style from the example above:

val y = if(variable == 1)
    "it is one"
    "it differs from one"

We could also want to write it in a single line, just like you would do it with the ternary operator in Java:

val x = if(variable == 1) "it is one" else "it differs from one"

What we see here are two different formatting patterns that are alternative to each other. An if-expression can be formatted single-line as well as multi-line. You might argue that it should be formatted multi-line when it is used as a statement and single-line when it is used as an expression. While this might sound like a smart strategy at the beginning and it will probably work for most scenarios, it will frustrate the developer for the remaining cases. Frustration is something we should prevent by all costs. Therefore, the Xtend formatter leaves the choice to the developer: It recognizes which formatting pattern the developer had in mind. The decision strategy is as follows:

  1. If the then- or the else-body contain at least one line-wrap, format the if-expression multi-line.
  2. If the length of the full if-expression exceeds the maximum length of a line, format it multi line.
  3. Apply single-line formatting in all other cases.

This empowers the developer to choose for every individual if-expression, if he/she prefers the sing-line or multi-line style.

Example 2: Lambda-Expressions

Thanks to lambda-expressions you can choose a functional programming style when you work with Xtend. You can think of lambda-expressions as executable snippets of code that can be passed around in parameters and variables.

The following example calculates the total size of all files within the same directory. You can recognize the lambda-expressions by their square brackets "[" "]".

val file = new".")
val totalLength = file.listFiles.filter[isFile].map[length].reduce[x, y|x + y]
println("The size of all files in " + file + " is " + totalLength + " bytes.")

  • filter[isFile] removes all items from the list which are not files, such as directories.
  • map[length] converts a list of files into a list of integers, each representing the file size (length).
  • reduce[x, y|x + y] applies x + y to all list items until all are summed up to a single value.

I think there is some beauty in this code since you can understand it just by reading it from the left to the right. Furthermore, it is much more concise than anything you can do with loops in Java.

For this code to be readable, surely we want the lambda-expressions to be formatted without line-wraps, similar to parameters of a method call.

Another use case for lambdas is to provide handlers for events and asynchronous communication. The following example creates an instance of java.lang.Runnable that prints to stdout when run() is called.

val Runnable runnable = [ |
  println("Hello from " +

Here, a multi-line style of the lambda-expression may be preferable if the implementation of the handler follows imperative programming style. If the lambda-expression does nothing but delegate to another method, a single-line style may be preferable.

A third use case for lambda-expression are named parameter values. In this example the assignments to name and priority are compiled to thread.setName(...) and thread.setPriority(...).

val thread = new Thread(runnable) => [
  name = "my thread"
  priority = Thread::MIN_PRIORITY

Here as well, a multi-line style is usually preferable.

Similar to if-expressions, there is no automated way for the formatter to decide for single-line or multi-line formatting. Therefore, the decision strategy is as follows:

  1. If there is a line-wrap before the closing bracket "]", apply multi-line style.
  2. If the the length of the closure exceeds the maximum line length, apply multi-line style.
  3. Apply single-line style in any other cases.

I decided that the "magic line-wrap" that triggers multi-line formatting of a lambda-expression should only be the line-wrap before the closing bracket "]" to make it easier to convert a multi-line lambda back to its single-line style. In this scenario, you'll only need to remove one single line-wrap and re-run the formatter instead of removing multiple line-wraps.

Other Examples You Can Try

As of Xtend 2.4.0, the following formatting patterns are supported besides the ones listed above:

  • single-line/multi-line style for method parameter declarations, triggered by the line-wrap before the closing parenthesis ")".
  • single-line/multi-line style for method call parameters, triggered by the line-wrap before the closing parenthesis ")".
  • switch-exprssions can be formatted single-line or multi line.
  • case-blocks inside switch-expressions can be formatted single-line or multi-line.


navya said...

Thanks for the post, I am techno savvy. I believe you hit the nail right on the head.
I am highly impressed with your blog. It is very nicely explained.
Your article adds best knowledge to our Java Online Training from India. or learn thru Java Online Training from India Students.

navya said...
This comment has been removed by the author.
Unknown said...

nice blog
android training in bangalore
ios training in bangalore
machine learning online training

Unknown said...

useful blog
python interview questions
cognos interview questions
perl interview questions
vlsi interview questions
web api interview questions
msbi interview questions

Unknown said...

laravel interview questions
aem interview questions
salesforce interview questions
oops abab interview questions
itil interview questions
informatica interview questions
extjs interview questions

Unknown said...

sap bi interview questions
hive interview questions
seo interview questions
as400 interview questions
wordpress interview questions
accounting interview questions
basic accounting and financial interview questions

Anonymous said...

Actualyty postPT Lampung thx
Service HP Bandar Lampung

IT said...

Thanks for providing recent updates regarding the concern, I look forward to read more.
Contextual Awareness in Human Advanced Vehicle Systems A Survey Project For CSE
SeArch A Collaborative and Intelligent NIDS Architecture for SDN based Cloud IoT Networks Project For CSE
Hierarchical Adversarial Network for Human Pose Estimation Project For CSE
Analysis and Implementation of Message Authentication Code (MAC) Algorithms for GOOSE Message Security Project For CSE
An IOT oriented Privacy Preserving Publish/Subscribe Model Over Blockchains Project For CSE
A Review on the Application of Blockchain to the Next Generation of Cyber secure Industry 4.0 Smart Factories Project For CSE

Garrick Co Ida said...

The development of artificial intelligence (AI) has propelled more programming architects, information scientists, and different experts to investigate the plausibility of a vocation in machine learning. Notwithstanding, a few newcomers will in general spotlight a lot on hypothesis and insufficient on commonsense application. Machine Learning Final Year Projects In case you will succeed, you have to begin building machine learning projects in the near future.

Projects assist you with improving your applied ML skills rapidly while allowing you to investigate an intriguing point. Furthermore, you can include projects into your portfolio, making it simpler to get a vocation, discover cool profession openings, and Final Year Project Centers in Chennai even arrange a more significant compensation.

Data analytics is the study of dissecting crude data so as to make decisions about that data. Data analytics advances and procedures are generally utilized in business ventures to empower associations to settle on progressively Python Training in Chennai educated business choices. In the present worldwide commercial center, it isn't sufficient to assemble data and do the math; you should realize how to apply that data to genuine situations such that will affect conduct. In the program you will initially gain proficiency with the specialized skills, including R and Python dialects most usually utilized in data analytics programming and usage; Python Training in Chennai at that point center around the commonsense application, in view of genuine business issues in a scope of industry segments, for example, wellbeing, promoting and account.

easylearn said...

I have enjoyed reading your post,it looks very attractive.Thanks for sharing some useful information.Tableau can help anyone see and understand their data.Get Tableau certification from our institute.
Best tableau training institutes in Bangalore

Unknown said...

pinoy tambayan lambingan and all the filipino Tv replays you will be watch online in hd. We will share with you pinoy1tv replays online in hd.

technology said...

Institutes invite designers, campaign strategists, and expert marketers to deliver special lectures on various topics like pros and cons of different marketing tools, email marketing, online network building, search engine optimization, user experience designing and mobile marketing etc. data science course syllabus

aditya said...

Thanks for sharing this valuable information to our vision. You have posted a trust worthy blog keep sharing.

Derivative Calculator
How to find the height of a trapezoid
Area of a Rectangle

opbestcom said...

I’m really inspired together with your writing skills and also with the structure
on your blog. Is this a paid theme or did you customize it yourself?
Anyway keep up the nice high quality writing, it is
rare to see a nice blog like this one nowadays..

Please Visit My homepage ➤ 오피사이트