mike-neckのブログ

Java or Groovy or Swift or Golang

JavaにREPLがやってくる

表記の通り、今(2015/06/26)現在KullaというプロジェクトでREPL機能が開発されていて、Java 9で(今更ながら)搭載される予定です(jshellと呼ばれるらしい)。

以前はこのJava REPLを試すのが大変だった(@zephiransasさんブログ記事を参照)ようですが、今はかなり簡単に、ナイトリービルドを試すことができます。Kullaのコミッターの@bitter_foxさんのブログを参考にインストールが可能です。

d.hatena.ne.jp

概要を書くと…

  • Java 9 early access版を入手する
  • Project KullaのJenkinsから最新版の成果物を入手する
  • Java 9 eaにパスを通す(java -versionjava version "1.9.0-ea"と出てくればよい)
  • java -jar kulla-0.xxx-yyyymmddhhmmss.jarで起動する

で使うことができます。

以下は昨日(2015/06/25)の最新バージョンを元に書いてあります。

  • Javaのバージョン : 1.9.0-ea-b68
  • Kullaのバージョン : 0.610-20150625005844

起動の仕方

先ほども書いた通り、Java 9 eaにパスを通した上で、次のコマンドで実行できます。

$ java -jar kulla-0.610-20150625005844.jar
|  Welcome to JShell -- Version 0.610
|  Type /help for help

->

終了の仕方

上の実行結果を見ればわかるとおり、ヘルプを表示する方法が/helpとあり、それを呼び出せばよいのにもかかわらず、ヘルプを見る方法がわからなくて、Ctrl + Dで終了していたりしましたが、/xで終了できます。

-> /x
|  Goodbye
$

コマンド

上記にあるように/helpあるいは/?で見ることができます。

内容は@yy_yankさんのブログでも見られます。

JavaのREPL、project kullaがスッゴイ便利! - Javaプログラマーのはしくれダイアリー

恐らくよく使うものを再掲します。

コマンド(短縮形) コマンド コマンドの内容
/? /help ヘルプを表示する
/x /exit Java REPLを終了する
- ! 前回と同じ式 or コマンドを実行する
(下記の/-1と同じ)
- /-数字 指定した数の分前の式 or コマンドを
実行する
/r /reset 入力したすべての変数、クラス定義
などをクリアする
/h /history 入力した履歴を表示する
/v vars 定義された変数を表示する
/m /methods 定義されたメソッドを表示する
/c /classes 定義されたクラスを表示する
/o <file-name> /open <file-name> 指定したテキストファイルを読み込み
コンパイルする
/cp <path> classpath <path> ライブラリーを読み込む
- seteditor <editor-name> 外部エディターを指定する
/e <name> /edit <name> 指定した変数やクラスなどの定義を
指定した外部エディターで
編集する
(設定していない場合は
JShellToolというSwingっぽいエディター)
`/d /drop <name> 指定した変数やクラスなどを
クリアする
/s [all or history] <file-name> save [all or history] <file-name> 入力した履歴をすべて(all)
あるいはヒストリーだけ(history)、
指定したファイルに保存する
- /setstart <file-name> 指定したファイルを初期ロード定義
として読み込む
(/r実行の後に有効になる)
- /savestart <file-name> 指定したファイルにデフォルトの
初期ロード定義を書き込む
/p /prompt プロンプトの前にある->の表示有無を
切り替える

よく使うものだけと言ってたけど、全部書いちゃった(・ω<)

個人的には、scalaとかgroovyshとかghciを使ってて、

  • :q -> 終了
  • :l -> ファイルのロード

的な動作に慣れてしまっているので、合わせてもらいたかった気がしなくもなくもない…

【2015/06/27 15:08 補足】scala:quitだった…。まあ、ここで言いたいのは、多くのREPLが:で始まっていて、Kullaが/で始まることにちょっと違和感を感じているということです

とりあえず使ってみる

では、単純に使ってみたいと思います。

-> 1
|  Expression value is: 1
|    assigned to temporary variable $1 of type int

1を実行することで1が得られて、それが変数$1に代入されました。/rを実行しない間は、以前の式の実行結果はこの$1的な変数でアクセスすることができます。

-> 1 + 1L + 1_000l
|  Expression value is: 1002
|    assigned to temporary variable $2 of type long

Java7から導入された数値の途中の_も使うことが可能です。

-> $2 = 100
|  Variable $2 has been assigned the value 100

あ、実行結果の変数に別の値を代入できちゃうんだ…(´・ω・`)

実行結果の変数はなるべくfinalっぽくしてほしかった気がしなくもなくもないですね…


-> URL url = new URL("http://mike-neck.hatenadiary.com/")
|  Added variable url of type URL with initial value http://mike-neck.hatenadiary.com/

-> URI uri = url.toURI()
|  Added variable uri of type URI with initial value http://mike-neck.hatenadiary.com/

URL#toURIURISyntaxExceptionという検査例外が投げられる可能性のあるメソッドなのですが、特にtry-catchを入れなくても実行できます。もちろん、try-catchで実行することも可能です。なお、try-catchの中のブロックでは式は;で終了する必要があります。

-> try {
>>   URL u = new URL("https://google.com");
>>   URI i = u.toURI();
>>   printf(i.toString());
>> } catch (URISyntaxException e) {
>>   printf(e.toString());
>> }
https://google.com

ファイルを読み込む

さて、現在fooというディレクトリーにいて、fooディレクトリーがこのような構造であるとします。

foo
┗ sample
   ┗ 00-sample.txt

そして、00-sample.txtの中身をこんな感じで自分自身を文字列として読み込む風にしておきます。

import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.nio.charset.StandardCharsets

Path sample = Paths.get("sample/00-sample.txt")
List<String> list = Files.readAllLines(sample, StandardCharsets.UTF_8)

これを/oコマンドで読み込みます。

-> /r
|  Resetting state.

-> /o sample/00-sample.txt

-> /v
|    Path sample = sample/00-sample.txt
|    List<String> list = [import java.nio.file.Files, import java.nio.file.Path, import java.nio.file.Paths, import java.nio.charset.StandardCharsets, , , Path sample = Paths.get("sample/00-sample.txt"), List<String> list = Files.readAllLines(sample, StandardCharsets.UTF_8)]

見事に読み込めたようですね。

jarファイルを読み込む

jarファイルなどを読み込んで試すこともできます。

とりあえず、先ほどのfooディレクトリーの下に次のようにtwitter4jを置いておきます。そしてKullaを起動します。なお、twitter4j.propertiesにはconsumer key、secret、access token、token secretを記述しておきます。

foo
┣ twitter4j-core-4.0.4.jar
┗ twitter4j.properties

次のようにコマンドを書いていきます。

-> /cp twitter4j-core-4.0.4.jar
|  Path twitter4j-core-4.0.4.jar added to classpath

-> import twitter4j.TwitterFactory

-> import twitter4j.Twitter

-> Twitter twitter = TwitterFactory.getSingleton()
|  Added variable twitter of type Twitter with initial value TwitterImpl{INCLUDE_MY_RETWEET=PostParameter{name='include_my_retweet', value='true', file=null, fileBody=null}}

-> twitter.updateStatus("project Kullaからツイート")
|  Expression value is: StatusJSONImpl{createdAt=Fri Jun 26 15:58:21 JST 2015, id=614326819064418305, text='project Kullaからツイート',...省略
|    assigned to temporary variable $1 of type twitter4j.Status

->

これでツイートしたツイートがこちらになります。

jarファイルも読み込めることがわかりました。これは、プロジェクトで作成したjarファイルをちょこっと試してみたいときなどに有効かもしれません。

【2015/06/27 15:08 追記】 さらにはJavaスクリプトとして使うこともできるかもしれませんね


project Kullaはまだ開発中ですので、今後動作が変わってくるかもしれませんが、教育用途やちょっとしたテスト用途、およびちょっとしたスクリプトの実行に用いることができそうです。また、今回は試していませんが、Jettyなどのwebサーバーを起動して、ちょっとしたwebサーバーのモックとしても使うことができるかもしれません。

おわり