What are those features in Xtend lang!?
As nature of a programmer calls I need to express myself about Xtend. During development of The Console I have almost smashed my face a few times by gesture flying straight from internal cent****re of disbeliefs.
Xtend?
Xtend is a nice programming language that is transpiled directly to Java source code. Transpilation wins over compilation-to-bytecode on Java-like-but-not-really-Java platforms like Android.
Overall, I like the language, especially comparing to Java. However, few rules made me questioning whole thing.
Bitwise operations
Let’s say I got this beautiful snippet:
val paramRegex = Pattern.compile(
'''(\d+(\.\d*)?)|([\w:/\\\.]+)|\"([^\"]*)\"|\'([^']*)\'|`([^`]*)`''',
Pattern.UNICODE_CHARACTER_CLASS
)
First argument is a regex, second is for flags. Let’s add another flag:
Pattern.UNICODE_CHARACTER_CLASS | Pattern.MULTILINE
And it won’t compile! Xtend doesn’t support bitwise operators like OR (| ) or AND (& ) and (:)) few others. This is how we do that:
Pattern.UNICODE_CHARACTER_CLASS.bitwiseOr(Pattern.MULTILINE)
char
Quotes don’t matter. To define a character I found two options:
-
create a String and pick single character from it using charAt() method
val SPACE = ’ ‘.charAt(0)
-
write number and cast it to a char
val SPACE = 32 as char
loops: no continue, no break
Xtend creators emphasize functional programming so hard that there is no goto . OK, everyone says goto is evil. But what about instructions like continue or break ?
Xtend doesn’t support continue or break in loops. Just not. OK, this is challenge. Let’s implement algorithm that finds longest common substring in functional approach. Mysteriously, doesn’t look like fun or understandable code. Not to ask about performance.
No default value in functions
OK. Java lacks default values.
class Dog {
void bark(volume = 10) {
// let's bark
}
}
However, I’ve seen this in Scala (which works on JVM and compiles to bytecode). Note the fact Java implements function polimorphizm (multiple methods with different argument list) so I expected to see this synctatic sugar in Xtend. I was wrong, it’s not there.
arrays? are you using arrays?
This one is more a “be careful” than lack of something.
Looking back at lack of continue or break we would think that Java Streams rule them all. Well, sometimes you need to specify whether you work with a list or an array. Even more, sometimes you need to control what you create.
When you create an array of Strings like #[“a”, “b”] you have to be really careful when performance plays a major role.
This Xtend code:
val a = #["a", "b"]
val String[] b = #["a", "b"]
transpiles to this code in Java:
final List<String> a = Collections.<String>unmodifiableList(CollectionLiterals.<String>newArrayList("a", "b"));
final String[] b = { "a", "b" };
However, if you want to create an array that will be filled later then you don’t have a language construct to do this like new String[5] . Instead, there’s a function newArrayOfSize() . Be careful once again:
val arr1 = newArrayOfSize(5)
val String[] arr2 = newArrayOfSize(5)
transpiles to
final Object[] arr1 = new Object[5];
final String[] arr2 = new String[5];
String interpolation
This one is just weird.
Several languages introduce string interpolation like this:
`some string ${someVariable}`
and in Xtend you go with « and » :
'''some string «someVariable»'''
If your editor doesn’t support this then you’re screwed.
Variable pre-*
Variable pre-increment or pre-decrement. Oh, this? Doesn’t exist.
var a = 2
var b = (++a) + 1
That won’t compile but the following will:
var a = 2
var b = (a++) + 1
Intriguing.
Summary
Overall, Xtend is a fun language to play with. But few things are weird. Especially bitwise operations seems to be a hindrance for old school game developers who use multiple flags because it’s easier to implement network protocols this way rather than with Java enums.