Someone already mentioned immutability. Another example is sound concurrency support: a language which is using non-blocking synchronization is not going to have threads constantly blocked monitoring locks (I'm not talking about Scala particularly: but in Java the language, the "synchronized" SNAFU is really totally messed up if you've done any serious concurrent programming and it's very hard to get "right").
Then another example it's also a fact that crazy optimization can be achieved by using macro pre-processing at compile-time. Java the language doesn't offer this. It's actually so problematic in certain cases that there have been specific tools developed (e.g. by Nokia for accessing the J2ME Nokia API) that did add macro support to Java.
Another example where macro do shine: an API like trove, using primitives-backed maps/set, runs circles around, say, a normal HashMap{Integer,Long}. But Java cannot automate/duplicate the code needed to offer this for all the primites types (which, some may argue, is precisely the reason why such performant maps/sets have never been part of the stock Java APIs). So how do you do if you want to "run around circle" of these default totally lame HashMap{Long,Integer} like if you're say, the Trove author? You write your own code generator generating all the .java files needed from a template. Pretty cool (from the Trove author) but also pretty lame (from "Java the language").
With real macros this one is a no-brainer. So much for "semantics".
These are just two examples: you're belief that language differences can be resumed to semantics is incorrect.
No comments yet.