汎用アプリケーション構築環境であるJavaとScalaとKoltlin

ウェブ技術 デジタルトランスフォーメーション技術 人工知能技術 機械学習 自然言語処理技術 推論技術 セマンティックウェブ技術 深層学習技術 オンライン学習 強化学習技術 チャットボットと質疑応答技術 ユーザーインターフェース技術 知識情報処理技術 プログラミング スパースモデリング 確率的生成モデル サポートベクトルマシン 本ブログのナビ 

JVMについて

JVMはJava仮想マシン(Java virtual mchine)の略となる。JVMの上で動作するJavaは、1996年にサンマイクロシステムズによってリリースされ、2010年に同社がオラクルに吸収合併された時に版権がオラクルに移り、以降オラクルにより開発が続行され、クライアント/サーバーモデルのwebアプリケーションで最も多く利用されている言語となる。

JVMが登場するまでのプログラミング言語は、下図の左に示すように、コンパイラーを通してCPUが理解できる命令に変換し実行していた。この手法で複雑な言語を構築した場合、ハードウェアのバリエーションに対する対応が困難であるという課題があった。これに対してJVMでは、Javaバイトコードと呼ばれるコンパイルファイルを一旦形成し、それを受け取ったJVMがホストが理解できる機械語に翻訳するという形式をとることで、よりフレキシブルに高度なプログラミングが可能とした。

このJVM環境を用いることで、同じJVM上で動作するScala、JRuby、JavaとClojureは高度な互換性を保つことが可能となっている。

Javaについて

Javaは以前”オブジェクト指向言語“等で述べたようなObject Oriented Programming:OOP)となる。詳細はそれらに任せるとして、OOPの基本的なプレイヤーは、クラス、オブジェクト、およびメソッドとなる。Clojureについての有用な入門書持つである”Clojure for Brave and True”によれば、このオブジェクトは、間抜けなアンドロイドに例えられ、命令に対応すること、データを保持することの2つだけしかできないものとされている。

このアンドロイドを製造する工場(ファクトリ)を考えた時、アンドロイドが理解するコマンドのセットも、アンドロイドが保持するデータのセットも、OOPの用語ではファクトリはクラス、アンドロイドはオブジェクト、コマンドはメソッドに対応する。

例えばScrayClownというファクトリ(クラス)があり、makBallonArtというコマンド(メソッド)に対応するアンドロイド(オブジェクト)を生成するとする。アンドロイドは持っている風船の数を記録し、風船の数が変わるたびにその数を更新する。バルーン数を報告するにはballonCountを使用し、バルーン数を受け取るにはrecieveBalloonsを使用する。それらの記述は以下のようになる。

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."

この例では、ScaryClownクラスを利用して、新しいオブジェクトbellyRubsTheClownを作成する方法について述べている。またこのオブジェクトのメソッド( balloonCount, receiveBalloons, makeBalloonArt など )を呼び出す方法も示している。

またOOPはファクトリにコマンドを送信することもできる。これはOOPの用語的に言うと、クラスもメソッドを持つということになる。例としては、組み込みクラスのMathには、数の絶対値を返すMath.absをはじめ多くのクラスメソッドがある。

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

ここでfacebookというディレクトリにPitatePhrases.javaを作り以下のように記述する。

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

このシンプルなプログラムは、実行すると “Shiver me timbers!!!”というフレーズをターミナルに表示する(海賊が “Hello, world!”と言うのと同じ)。これはPiratePhrasesというクラスと、そのクラスに属するmainというスタティックメソッドから構成されている。スタティックメソッドとは、本来はクラスメソッドのこととなる。

ここで(JVM環境が設定されているとして)ターミナルで”javac PitatePhrases.java”と入力すると、PiratePhrases.classというクラスファイルが生成され、”java PitatePhrases”と入力すると”Shiver me timbers!!!”と表示され、正しく動作(run)させたことが確認できる。

ここで行なったことは、javacというコンパイラを使って、PitatePhrases.javaをコンパイルしてPitatePhrasesという名のクラスファイルを作っている。このクラスファイルには大量のJavaバイトコードが詰め込まれている。

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

java PiratePhrasesを実行すると、JVMはまずクラスパスを見て、PiratePhrasesという名前のクラスを探す。クラスパスは、クラスを定義するファイルを見つけるためにJVMが検索するファイルシステムのパスのリストとなる。デフォルトでは、クラスパスは、javaを実行したときにいるディレクトリを含んでいる。Javaでは、1つのファイルに1つのパブリック・クラスしか許可されず、ファイル名はクラス名と一致しなければならない。こうしてjavaはPiratePhrases.classからPiratePhrasesクラスのバイトコードを探し、それを見つけると、そのクラスのmainメソッドを実行する。JavaはC言語と似ていて、「何かを実行し、このクラスをエントリポイントとして使用する」と言うと、常にそのクラスのmainメソッドを実行するものとなる。

マルチファイルプログラムとJavaライブラリの使い方

まずJavaでのパッケージはコードの整理を提供する。具体的にはパッケージはクラスを含み、パッケージ名はファイルシステムディレクトリに対応する。もし、ファイルに package com.shapemaster という行があれば、 com/shapemaster というディレクトリがクラスパスのどこかに存在していることとなる。

import Javaでは、クラスをインポートすることができる。これは基本的に、名前空間接頭辞を使わずにクラスを参照できることを意味する。つまり、com.shapemasterにSquareというクラスがある場合、.javaファイルの先頭でimport com.shapemaster.Square; または import com.shapemaster.*; と記述すれば、コード中でcom.shapemaster.Squareではなく、Squareを使用することができるものとなる。

ここでpackageとimportを使った例について述べる。ここではpirate_phrasesというパッケージを作成し、GreetingsとFarewellsという2つのクラスを作成する。まずphrasebookに移動して、そのディレクトリの中に、pirate_phrasesというディレクトリを作ります。Java のパッケージ名はファイルシステムのディレクトリに対応しているため、pirate_phrases を作成する必要がある。次に、pirate_phrasesディレクトリの中にGreetings.javaを作成する。

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

ここでpirate_phrasesフォルダー内にあるimportするFarewells.java、Greetings.javaファイルを以下のようにする。

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!!!");
    }
}

さらにそれらをimportして動作させるPirateConversation.javaファイルを以下のようにする。

import pirate_phrases.*;

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

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

一行目の、import pirate_phrases.*; は、Greetings と Farewells クラスを含む pirate_ phrases パッケージの全クラスをインポートする記述となる。

これらに対して”javac PirateConversation.java”でクラスファイルをコンパイルし、”java PirateConversation”で動作させると”Shiver me timbers!!! A fair turn of the tide ter ye thar, ye magnificent sea friend!!”と二つのクラスを使った動作を確認できる。

JARファイル

JARファイルを使用すると、すべての.classファイルを1つのファイルにバンドルすることができる。前述のphrasebookのディレクトリに移動して、以下を実行する。

jar cvfe conversation.jar PirateConversation PirateConversation.class

conversation.jarという圧縮ファイルが作成され、中のコンテンツは”jar tf conversation.jar”にて見ることができ、”java -jar conversation.jar”にて動作させることができる。

Scala

Scalaは、Javaプラットフォーム上で動作するプログラミング言語で動作できるプログミング言語で、2003年頃登場した比較的新しい言語となる。海外ではTwitterやFoursquareといった企業で実用化実゛きがあり、日本国内でも採用している企業が増えている。

言語名の「Scala」とは「スケーラブル(拡張可能)な言語」を意味している。ScalaはJava言語のGenericsのエス設計にも関わった、スイス工科大学のMartin Odersky教授によって設計・開発されたものとなる。開発の動機としては

  • 汎用言語はスケーラブルであり、同じ概念で小さいプログラムも大きいプログラムも記述できる。
  • スケーラビリティ(拡張性)は関数型言語とオブジェクト指向言語のプログラミング概念を統合し、一般化することにより実現できる。

Scala公式サイトではScalaの紹介にについて以下のように述べられている。「Scalaは、オブジェクト指向と関数型プログラミングを1つの簡潔で高レベルの言語で組み合わせています。Scalaの静的タイプは、複雑なアプリケーションのバグを回避するのに役立ち、JVMとJavaScriptランタイムにより、ライブラリの巨大なエコシステムに簡単にアクセスできる高性能システムを構築できます。」

JavaのソースコードとScalaのソースコードを比較すると以下のように非常に短く記述することが可能となる。

//Javaのコード
public class Person
{
  private  String firstName;
  private  String lastName;
  String getFirstName() { return firstName; }
  void setFirstName(String firstName) { this.firstName = firstName; }
  String getLastName() { return  lastName; }
  void setLastName(String lastName) { this.lastName = lastName; }
  int hashCode() ....
  boolean equals(Object o) { ....  }
}

//Scalaのコード
case class Person(firstName:String, lastName:String)
  

Koltlin

Koltlinはさまざまな言語の開発環境であるInteiliJを販売しているJETBRAINS社が開発したJVM上で動作する言語となる。Javaに望まれている機能であっても互換性を保つために実現できていない機能や、将来のJavaの仕様で実現が予定されている機能から、有用と思われる機能を採用した。また、Java仮想マシンで動く点で似ているスクリプト言語 Groovy関数型プログラミング言語の要素が強い Scala から、機能や簡易記法(糖衣構文)を採用した。そのほか、ジェネリクスの構文などでC#の影響を受けている部分もある。

コード例としては以下のようになる。

package org.kotlinlang.play         

fun main() {                        
    println("Hello, World!")        
}

以下に詳細を示す。

    詳細技術

    • Code as Dataの概要とアルゴリズム及び実装例について

    “Code as Data”は、プログラムのコード自体をデータとして扱う考え方やアプローチを指し、プログラムをデータ構造として操作し、分析、変換、処理することを可能にする方法となる。通常、プログラムはある入力を受け取り、それに対して特定の手順やアルゴリズムを実行し、結果を出力する。一方で、”Code as Data”では、プログラム自体がデータとして扱われ、他のプログラムによって操作される。これにより、プログラムをより柔軟に、動的に、抽象的に扱うことが可能となる。

    プログラミングを行うためには、それぞれの言語に合わせた開発環境を作る必要がある。ここでは、本ブログに述べているPython、Clojure、C、Java、R、LISP、Prolog、Javascript、PHPそれぞのケースでの具体的な開発環境の立ち上げについて述べている。個々の言語では、開発を容易にするためのプラットフォームが準備されており、それらを用いると容易な環境設定が可能となるが、ここでは最もシンプルなケースでのものを中心に述べている。

    プログラミングを行う際にファイルの入出力機能は最も基本的で必須なものとなる。またファイルの入出力機能は、手続き的な命令となるため、各言語ごとに実現の仕方も異なってくる。以下に様々な言語でのファイル入出力の具体的な実装について述べる。

    プログラミング言語の中でも基本機能は、”プログラミング言語の歴史“でも述べた「構造化言語」の3つの機能である(1)順次進行、(2)条件分岐、(3)繰り返しの中の一つの要素となる。ここではこの内繰り返しと分岐に対して様々な言語での実装を示す。

    データベース技術とは、データを効率的に管理・保存・取得・処理するための技術のことを指し、情報システムやアプリケーションにおけるデータの永続化や操作を支援し、データの正確性、一貫性、可用性、安全性を確保することを目的としたものとなる。

    以下にこれらのデータベースを実際に扱うための各種言語による実装について述べる。

    ここでは”サーバー技術“で述べているサーバーを各種プログラミング言語で活用する事例について述べる。ここでのサーバー技術とは、ネットワーク上でクライアントからのリクエストを受け取り、要求された処理を実行してレスポンスを返すサーバーシステムの設計・構築・運用などに関する技術のことを指す。

    サーバー技術は、WebアプリケーションやAPIサーバー、データベースサーバー、メールサーバーなど、さまざまなシステムやサービスで使用されており、プログラミング言語やフレームワークに応じて、サーバー技術の実装方法やベストプラクティスが異なる。

    静的型付け言語というのは、式の型がコンパイル時に決まっている言語となる。まず、静的型付け言語では、変数に型がある。Javaでa:と宣言したら、aはint型になる。そしてa+1というのは、int型の変数aにint型の1を加算したものなので、結果はint型となる。もしa+0.5なら、Javaではintはdouble型に拡張してから加算されるので、結果はdouble型となる。このように、静的型付け言語では、それぞれの式の型が部分式を含め、コンパイル時に決まっている。もちろん、メソッドの引数や戻り値の型も決まっている。そうでなければ式の形が決まらないからである。

    ClojureはJVMの上で動くLispであり、様々なレベルでJavaと連携することができ、Javaの資産をフルで活用することができる。

    PlantUML は、オープンソースの様々なデータモデルを自動で描画可能なツールとなり、AT&T研究所が提供しているオープンソースの描画ツールであるgraphvizをベースとしている。以下に示すような様々なダイアグラムを素早く作成するためのコンポーネントとなる。

    plantUMLの利用の仕方には様々な方法がある。(1)Jarファイルの利用、(2)Macでのbrewの利用、(3)Webサービス、(4)アプリケーションに仕込む方法

    Clojureのカンファレンスの一つであるClojure/Conj2018にてCODE GOES IN, ART COMES OUT“というジェネレーティブアートに関する講演を見た。

    ジェネレーティブアートとはwikiによると

    「コンピュータソフトウェアのアルゴリズムや数学的/機械的/無作為的自律過程によってアルゴリズム的に生成・合成・構築される芸術作品を指す。コンピュータの計算の自由度と計算速度を活かし、自然科学で得られた理論を実行することで、人工と自然の中間のような、統一感を持った有機的な表現を行わせる作品が多い。

    ジェネレーティブアートは、創作方法として自然科学的なシステムを主体として用いた芸術である。前提として、自律的に動作する機構を設計して作品制作を行わなければならない点が、他の芸術分野との違いであると言える。システムによる作品は、複雑系や情報理論といった科学理論を実行することがある。

    今回はApache Sparkの開発環境の構築方法、アプリケーションのビルド法および実行方法について述べる。SparkではRDDを直接操作する最も基本的なライブラリのほか、いろいろな用途に特化したエコシステムの各種ライブラリが同梱されており、さまざまなプログラミング言語むけのAPIが提供されている。今回はApache Sparkが記述されているScalaを用いたアプリケーションの構築について、Spark-clintを利用する前提で述べる。まず、Sparkアプリケーションは、ソースコードをコンパイルしてJARファイルにパッケージングする必要がある。今回はこのためにsbtを用いる。sbtはScalaやJavaで記述されたソースコードのコンパイルやライブラリの依存関係の管理、パッケージングなど、アプリケーション開発プロジェクトにおけるビルドプロセスを統合的に管理するためのツールとなる。

    • Scaleについて(Guide to Scala)

    コメント

    1. […] 禅とライフティップ 旅と歴史 スポーツとアート 機械学習と数学 Clojure Java 本とTVと映画と音楽 […]

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