Three Modern JVM languages-Groovy, Scala, and clojure

Source: Internet
Author: User
Java will be a platform rather than a programming language.

The original engineers of Java made a wise decision to separate the programming language from the runtime environment, which eventually allowed over 200 languages to run on the Java platform. This architecture is crucial to the long-term vitality of the platform, because the computer programming language generally has a short life cycle. The annual JVM language summit, sponsored by Oracle, started in 2008, provided an opportunity for open cooperation between other JVM language implementations and Java platform engineers.

Welcome to Java. in the next column series, I will talk about three modern JVM languages-Groovy, Scala, and clojure-which provide the paradigm, an interesting mix between design choices and comfort factors. I will not take the time to introduce each language in depth here; this type of deep introduction is available on their respective sites. However, sites in these language communities, which primarily aim to spread these languages, lack objective information or examples of language inapplicability. In this series of articles, I will make an independent comparison to fill in the above gaps. These articles will give an overview of the Java. Next programming language and their benefits.

Java

The degree to which the Java programming language is superior is that, according to Bruce Tate's statement in his book beyond Java, perfect storm: the rise of Web applications, the existing web technology cannot meet the needs for various reasons, the rise of enterprise-level multi-layer application development has jointly created Java excellence. Tate also pointed out that the storm was a series of unique events, and no other language used the same way to achieve the same superior program.

Java has proved its powerful functional flexibility, but its syntax and inherent paradigm have long-term known limitations. Although some promised changes will be introduced into the language, Java syntax cannot easily support some important future syntax features, such as some features in functional programming. However, if you try to find a language to replace Java, you will be wrong.

Multi-language programming

Multi-language programming-a blog in 2006 that I made this term dynamic and popular-is based on the understanding that no programming language can solve every problem. Some languages have some built-in features to better adapt to specific problems. For example, due to the complexity of swing, Developers find it difficult to compile the swing UI in Java, because it requires that the type be declared in advance to define annoying anonymous internal classes for UI actions, there are other troubles. Using a language that is more suitable for building the UI, such as the swingbuilder tool in groovy, it is much better to build a swing application.

The increasing number of programming languages running on JVM has greatly stimulated the multi-language programming philosophy, because you can mix numbers and use the best matching language, however, the same underlying bytecode and class library are maintained. For example, swingbuilder does not replace swing, but is built on an existing swing API. Of course, for a long time, developers will mix programming languages outside of JVM-for example, SQL and JavaScript for specific purposes-but in the JVM world, hybrid programming will become more popular. Many projects in thoughtworks use multiple programming languages, while all tools developed by thoughtworks Studios use a hybrid language.

Even if Java is still your main development language, learning how other languages work will allow you to incorporate them into your future strategy. Java will still be an important part of the JVM ecosystem, but in the end it is mostly an assembly language for the platform-or for purely performance reasons, or it is used only when it meets special requirements.

Evolution of programming languages

When I was in college in the 1980s S, we used a development environment called pecan Pascal. Its unique feature is that it enables the same Pascal code to run on both Apple II and ibm pc. Pecan engineers used a mysterious thing called "bytecode" to achieve this purpose. Developers compile their Pascal code into a "bytecode", which runs on the native "Virtual Machine" compiled for each platform. It was a terrible experience! The program is surprisingly slow, even if it is just a simple class assignment. At that time, hardware could not cope with this challenge.

In the decade that followed pecan Pascal, Sun released Java using the same architecture, which was also constrained by the hardware environment in the 1990s S. Java also includes other developer-friendly features, such as automatic garbage collection. I have used a language like C ++, and now I don't want to use a language without the garbage collection function for encoding. I would rather spend time thinking about complex business problems at a higher abstraction level than complex pipeline problems like memory management.

One of the reasons why computer languages do not have a long life is the speed of language and platform design innovation. As our platforms become more powerful, they can handle more additional work. For example, the memory-based (memoization) feature of groovy (added in 2010) will cache the results of function calls. You do not need to write the cache code manually. This will introduce potential defects. You just need to call the memoize method, as shown in Listing 1:

Listing 1. Memory-based functions in groovy

def static sum = { number ->factorsOf(number).inject(0, {i, j -> i + j})}def static sumOfFactors = sum.memoize()

In listing 1, The results returned by the sumoffactors method are automatically cached. You can also use the memoizeatleast () and memoizeatmost () Methods to customize cache behavior. Clojure also contains the memory feature, which is also slightly implemented in Scala. Advanced features such as memory in the next-generation programming language (and some Java frameworks) will gradually enter the Java language. In the next version of Java, higher-order functions will be added, making it easier to implement memory-based functions. By studying the next-generation Java language, you can first see the future features of Java as soon as possible.

Groovy, Scala, and clojure

Groovy is the Java syntax of the 21st century-coffee concentrate replaces traditional coffee. Groovy is designed to update and eliminate obstacles in Java syntax and support the main programming paradigm in Java. Therefore, groovy needs to "know" such as JavaBean, which simplifies access to attributes. Groovy will quickly incorporate new features, including important features in functional programming, which I will focus on in subsequent chapters of this series. Groovy is still mainly an object-oriented imperative language. Groovy differs from Java in two basic differences: it is dynamic rather than static; it is a much better metaprogramming capability.

Scala is designed to use JVM, but its syntax is completely redesigned. Scala is a strong static type language-it has strict type requirements than Java, but it causes little trouble-it supports object-oriented and functional paradigms, but is better than the latter. For example, scala prefers Val declaration, which generates immutable variables (similar to declaring variables as final in Java) and VAR will create variable variables that are more familiar to everyone. With deep support for these two paradigms, scala builds a bridge between what you might want (Object-Oriented imperative programming) and what you should want (functional programming.

Clojure is the most radical. Its syntax is separated from other languages and is considered to be the dialect of lisp. Clojure is a strong dynamic language (just like groovy) that reflects a design decision without hesitation. Although clojure allows you to fully and deeply interact with legacy Java programs, it does not try to build a bridge to connect to the object-oriented paradigm. For example, clojure is a hardcore of functional programming and supports object orientation to allow interoperability with this paradigm. Although it supports all the features that the object programmer is used to, such as polymorphism, it is implemented in a functional style rather than an object-oriented style. Clojure follows a set of core engineering principles, such as software transactional memory, which breaks the old programming paradigm to cater to new features.

Programming Paradigm

Apart from syntax, the most interesting difference between these languages is the type and its internal programming paradigm: functional or imperative.

Static vs. Dynamic

Static types in programming languages require explicit type declarations, such as int X in Java. Dynamic type language does not require the type information to be provided during declaration. The language considered here is strongly typed, meaning that the program can reflect the type after being assigned a value.

Java's type system is widely criticized because its static type has too many inconveniences and does not provide enough benefits. For example, Java requires developers to repeatedly declare types on both sides of the value assignment statement before the current finite type derivation occurs. Scala type is more static than Java, but it is much less inconvenient to use in daily use, because it uses type derivation in large quantities.

At first glance, groovy seems to have a behavior that can bridge the gap between static and dynamic. Consider the simple object set factory shown in Listing 2:

Listing 2. Groovy collection Factory

class CollectionFactory {def List getCollection(description) {if (description == "Array-like")new ArrayList()else if (description == "Stack-like")new Stack()}}

The class in Listing 2 is a factory class. Based on the input description parameter, the factory returns one of the two implementations of the List interface-arraylist or stack. For Java developers, the code above ensures that the returned values comply with the conventions. Then, the two unit tests in listing 3 reveal a complexity:

Listing 3. Test the set type in groovy

@Testvoid test_search() {List l = f.getCollection("Stack-like")assertTrue l instanceof java.util.Stackl.push("foo")assertThat l.size(), is(1)def r = l.search("foo")}@Test(expected=groovy.lang.MissingMethodException.class)void verify_that_typing_does_not_help() {List l = f.getCollection("Array-like")assertTrue l instanceof java.util.ArrayListl.add("foo")assertThat l.size(), is(1)def r = l.search("foo")}

In the first unit test in listing 3, use the aforementioned factory class to obtain a stack object, verify that it is indeed a stack object, and then execute stack operations, such as push (), size () and search (). However, in the second unit test, I must declare an expected exception missingmethodexception to ensure that the test passes. When I get an array-like set and assign it to a list type variable, I can verify that the returned type is indeed a list object. However, an exception is triggered when I try to call the search () method because arraylist does not contain the search () method. Therefore, this declaration cannot ensure that the method call is correct during compilation.

Although this looks like a defect, this behavior is appropriate. The type in groovy only ensures the validity of the value assignment statement. For example, in listing 3, if the returned instance does not implement the list interface, a runtime exception groovycastexception is triggered. With this in mind, we can be sure that groovy and clojure can join the strong dynamic language family.

However, some of the latest changes in groovy make the gap between its static and dynamic become clearer. Groovy 2.0 adds the annotation @ typechecked, which enables you to perform strict type checks on class or method decisions. Listing 4 illustrates the usage of this annotation:

Listing 4. Use annotation type check

@TypeChecked@Test void type_checking() {def f = new CollectionFactory()List l = f.getCollection("Stack-like")l.add("foo")def r = l.pop()assertEquals r, "foo"}

In Listing 4, I added the annotation @ typechecked, which simultaneously verifies the value assignment and subsequent method calls. For example, the Code in listing 5 cannot be compiled:

Listing 5. Preventing invalid method call type checks

@TypeChecked@Test void invalid_type() {def f = new CollectionFactory()Stack s = (Stack) f.getCollection("Stack-like")s.add("foo")def result = s.search("foo")}

In listing 5, I must perform a forced type conversion on the objects returned by the collection factory so that I can call the search () method in the stack class. But this method has some limitations: When the type is static, Many of groovy's dynamic features will not work. However, the above life-saving proof that groovy will continue to improve to bridge the gap between static and dynamic nature.

All these languages have very powerful meta-programming functions, so more rigorous typing can be added later. For example, multiple branch projects have introduced selective type to clojure. However, it is generally considered that the selective type is optional and is not part of the type system; it is only a type verification system.

Imperative vs. functional

Another major dimension is imperative and functional. Imperative programming focuses on the structure of one-step execution. In many cases, it imitates the useful structure of the early underlying hardware. Function programming focuses on using functions as the first struct to minimize state transmission and variability.

Groovy is largely inspired by Java and is basically still a imperative language. But from the very beginning, groovy has added many functional command features, and will add more such features in the future.

Scala bridges the two programming paradigms that support both. While more (and more encouraging) functional programming, scala still supports object-oriented and imperative programming. Therefore, in order to use Scala appropriately, the team is required to be well trained to ensure that you do not mix and randomly select the programming paradigm. In multi-paradigm programming languages, this is always a danger.

Clojure is a hardcore functional programming language. It also supports the object-oriented feature so that it can easily interact with other JVM languages and does not try to bridge the gap between the two paradigms. On the contrary, clojure's decision-making without hesitation makes the statements considered by its designers a good engineering practice. These decisions have a profound impact, which enables clojure to solve some lingering problems (such as concurrency) in the Java World in pioneering ways ).

Many of the ideological transformations required when learning these new languages are derived from the huge difference between imperative and functional patterns, which is one of the most valuable fields to be explored in this series of articles.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.