Syntactic Salt and Sugar was a presentation given by James Gould and Alex Holmes. They were talking about some recent developments and whether they are good (sugar) or bad (salt).
DSLs
DSLs are becoming ubiquitous. Everyone wants, needs and does DSLs today. But think of this for a moment: Is SQL a DSL?
Scary thought, eh? It’s certainly a limited language but since it’s Turing complete, the limits are more in the pain writing queries and not in the fact that it’s a language designed to query data sets.
The advantage of DSLs is that you can fine tune them to your domain. That can help to avoid a lot of confusion.
But …
- There are five people on this planet who can develop a nice syntax that is easy to use, easy to read, easy to understand and mostly consistent. Guido van Rossum is one of them. You’re not.
- It’s easy to fall for the “one more feature” trap in a DSL. The most important property of a DSL is that it’s limited. It’s not a general purpose programming language.
- Getting the syntax right is very, very hard. It’s easy to define syntax in the Xtext grammar editor – as long as you blissfully ignore the consumers of your DSL. As soon as you try to make their lives easier, all hell will break loose. Do you allow trailing commas? How do you handle ambiguities? Did you make sure all error messages make sense? Is it still readable? Can you add features without breaking all existing code?
- YALTL – Yet another language to learn
Default Methods in Java 8
In Java 8, you can add method bodies to methods defined in interfaces:
public interface Foo { String getName() default { return "Foo"; } }
Finally, you can have mixins in Java. Yay ^_^
Now, some people will wonder: Isn’t that multiple inhertiance?
Yup. And as usual, because of some “features” of Java, they had to implement this in a … surprising way. What does this code print?
public interface A { String getName() default { return "A"; } } public interface B { String getName() default { return "B"; } } public class C implements A, B { public void main() { System.out.println(new C().getName()); } }
public interface A { String getName() default { return "A"; } } public interface B { String getName() default { return "B"; } } public interface C extends B {} public class D implements A, C { public void main() { System.out.println(new C().getName()); } }
If you’re wondering: Instead of inheriting directly from “B”, I added a new interface “C”. Now, “A” is “closer” and it will print “A”.
That means changes in A or C can modify the behavior of D. If you’re lucky, the compiler will refuse to compile it. *sigh*
No Free Lunch
Again, it’s easy to see that each feature comes with a cost attached.