Cooperation between Clojure and Java

Machine Learning Technology   Artificial Intelligence Technology  Digital Transformation Technology  Java   Clojure

Clojure is a Lisp that runs on top of the JVM and can be integrated with Java at various levels, allowing full use of Java assets.

JVM

Java, which runs on the JVM, was released by Sun Microsystems in 1996, and when Sun Microsystems merged with Oracle in 2010, the copyright was transferred to Oracle, which has continued to develop the language ever since. Since then, it has continued to be developed by Oracle and has become the most widely used language for web applications in the client/server model.

Until the JVM appeared, programming languages were converted into instructions that the CPU could understand and execute through a compiler, as shown on the left in the figure below. When a complex language was built using this method, it was difficult to support hardware variations. The JVM, on the other hand, enables more flexible and advanced programming by forming a compiled file called Java bytecode once and then translating it into a machine language that the host can understand.

This JVM environment allows Clojure to maintain a high degree of compatibility with Scala, JRuby, and Java, which all run on the same JVM.

Java

Java is an Object Oriented Programming (OOP) language as previously described in “Object Oriented Languages” and others. According to “Clojure for Brave and True,” a useful introduction to Clojure, the object is likened to a dumb android, capable of only two things: responding to commands and holding data. It can only do two things: respond to commands and store data.

When we consider the factory that manufactures the android, the set of commands that the android understands and the set of data that the android retains correspond, in OOP terms, to the factory as a class, the android as an object, and the commands as methods.

For example, suppose we have a factory (class) called ScrayClown that generates an android (object) corresponding to a command (method) called makBallonArt. The android keeps track of the number of balloons it has and updates that number whenever the number of balloons changes. To report the number of balloons, use ballonCount, and to receive the number of balloons, use recieveBalloons. Their descriptions are as follows.

ScaryClown bellyRubsTheClown = new ScaryClown(); 
bellyRubsTheClown.balloonCount();
// => 0
bellyRubsTheClown.receiveBalloons(2); 
bellyRubsTheClown.balloonCount();
// => 2
bellyRubsTheClown.makeBalloonArt();
// => "Belly Rubs makes a balloon shaped like a clown, because Belly Rubs
// => is trying to scare you and nothing is scarier than clowns."

This example shows how to create a new object bellyRubsTheClown using the ScaryClown class. It also shows how to call this object’s methods (balloonCount, receiveBalloons, makeBalloonArt, etc.).

OOP can also send commands to the factory. In OOP terms, this means that the class also has methods. For example, the built-in class Math has many class methods, including Math.abs, which returns the absolute value of a number.

Math.abs(-50)
// => 50

Now, create PitatePhrases.java in the directory named facebook and write the following

public class PiratePhrases
{    
   public static void main(String[] args)
   {
      System.out.println("Shiver me timbers!!!");
   }
}

This simple program, when run, displays the phrase “Shiver me timbers!!!” phrase in the terminal (just like a pirate saying “Hello, world!”). It consists of a class called PiratePhrases and a static method called main that belongs to that class. Static methods are essentially class methods.

If we type “javac PitatePhrases.java” in the terminal (assuming the JVM environment is set up), a class file named PiratePhrases.class will be generated, and if we type “java PitatePhrases”, we will get “Shiver me timbers!!!” and you can confirm that you have made it work (run) correctly.

What we have done here is to compile PitatePhrases.java using a compiler called javac to create a class file named PitatePhrases. This class file is packed with a large amount of Java bytecode.

cafe babe 0000 003d 001d 0a00 0200 0307
0004 0c00 0500 0601 0010 6a61 7661 2f6c
616e 672f 4f62 6a65 6374 0100 063c 696e
6974 3e01 0003 2829 5609 0008 0009 0700

When you run java PiratePhrases, the JVM first looks at the classpath to find a class named PiratePhrases. The classpath will be a list of filesystem paths that the JVM will look for to find the file that defines the class. By default, the classpath contains the directory you are in when you run java. java allows only one public class per file, and the file name must match the class name. Thus, java looks for the bytecode of the PiratePhrases class in PiratePhrases.class, and when it finds it, it executes the main method of that class. java is similar to the C language in that if you say “run something and use this class as an entry point ” will always execute the main method of that class.

How to use multi-file programs and Java libraries

First, packages in Java provide code organization. Specifically, packages contain classes, and package names correspond to filesystem directories. If a file has the line package com.shapemaster, then the directory com/shapemaster exists somewhere in the classpath.

import Java allows classes to be imported. This basically means that classes can be referenced without namespace prefixes. In other words, if com.shapemaster has a class called Square, you can write import com.shapemaster.Square; or import com.shapemaster.*; at the beginning of the .java file, and your code will refer to com. Square instead of shapemaster.Square.

Here is an example of using package and import. Here we create a package called pirate_phrases and create two classes, Greetings and Farewells. First, go to the phasebook and create a directory named pirate_phrases in that directory. pirate_phrases needs to be created because Java package names correspond to directories in the file system. Next, create Greetings.java in the pirate_phrases directory.

phrasebook
  |____pirate_phrases
           |_____Farewells.java
           |_____Greetings.java
  |_____PirateConversation.java
  |_____PirtaePhrases.java

Now, import Farewells.java and Greetings.java files in the pirate_phrases folder as follows.

package pirate_phrases;

public class Farewells
{
    public static void goodbye()
    {
        System.out.println("A fair turn of the tide ter ye thar, ye magnificent sea friend!!");
    }
}
package pirate_phrases;

public class Greetings
{
    public static void hello()
    {
        System.out.println("Shiver me timbers!!!");
    }
}

In addition, import them and make the PirateConversation.java file to work as follows.

import pirate_phrases.*;

public class PirateConversation
{
    public static void main(String[] args)
    {
        Greetings greetings = new Greetings();
        greetings.hello();

        Farewells farewells = new Farewells();
        farewells.goodbye();
    }
}

The first line, import pirate_phrases.*; imports all classes in the pirate_phrases package, including Greetings and Farewells classes.

Compiling the class file with “javac PirateConversation.java” and running it with “java PirateConversation” produces “Shiver me timbers! A fair turn of the tide ter ye thar, ye magnificent sea friend! and you can see the two classes in action.

 

JAR File

The JAR file allows you to bundle all .class files into one file. Go to the aforementioned phasebook directory and execute the following

jar cvfe conversation.jar PirateConversation PirateConversation.class

A compressed file named conversation.jar is created, and the contents can be viewed with “jar tf conversation.jar” and run with “java -jar conversation.jar”.

Java Class Access in Clojure

Classes defined in Java code can be used directly or in dot format without decoration by “importing” them in the namespace.

(.toUpperCase "By Bluebeard's bananas!")
; => "BY BLUEBEARD'S BANANAS!"
u(.indexOf "Let's synergize our bleeding edges" "y") 
; => 7

In addition, as described in “Natural Language Processing with Clojure,” it is possible to directly use Java’s kuromoji class or libraries created in Java such as LDA and SVM.

The aforementioned methods call methods of existing objects, but there are also methods to create new objects (new ClassName optinal-arges and ClassName. optional-arges).

(new String)
; => ""
(String.)
; => ""
(String. "To Davey Jones's Locker with ye hardies")
; => "To Davey Jones's Locker with ye hardies"

It is also possible to import and use class files created in Clojure on the Java side.

コメント

タイトルとURLをコピーしました