This post is Private. Only a writer or those who know its URL can access this post.

Ammoniteで使い倒す!ScalaのREPL環境

More than 1 year has passed since last update.

What's Ammonite?

REPLやスクリプティング、ファイルシステムライブラリ、スタンドアロンのシステムシェルとしてScalaを使う為のランタイム。

兎に角、Scalaを軽量に使えるようにすることを目標にしている。


Ammoniteは

  • Ammonite-REPL
  • Scala Scripts
  • Ammonite-Ops
  • Ammonite-Shell

から構成される。今回は、Ammonite-REPLにフォーカスする。


Install

Scala 2.12の場合

sudo curl -L -o /usr/local/bin/amm \
      https://git.io/vMF2M && sudo chmod +x /usr/local/bin/amm

以前のバージョンは、こちらを参照


使い方

REPL

> amm
Welcome to the Ammonite Repl 0.8.2
(Scala 2.12.1 Java 1.8.0_121)
@ 1 + 1 
res0: Int = 2
@  

普通のREPLと同じように使える


ファイルに記述も可

Hello.sc
println("Hello World!")
> amm Hello.sc 
Hello World!

(余談)

ファイルの先頭に↓を記述すると直接実行可能。

Hello.sc
#!/usr/bin/env amm
println("Hello World!")
> ./Hello.sc
Hello World!

(余談)トラブルシューティング

Q. amm実行時に以下のようなエラーに遭遇するのですが、どうしたらいいですか?

Loading...
Exception in thread "main" java.lang.VerifyError: Uninitialized object exists on backward branch 162
Exception Details:
  Location:
    scala/util/matching/Regex.unapplySeq(Lscala/util/matching/Regex$Match;)Lscala/Option; @216: goto
  Reason:
    Error exists in the bytecode
  Bytecode:
    0x0000000: 2bc6 000a 2bb6 00ef c700 07b2 0052 b02b
    0x0000010: b600 f2b6 00f3 2ab6 0054 4d59 c700 0b57
    0x0000020: 2cc6 000d a700 c92c b600 f799 00c2 bb00
    0x0000030: 6059 b200 65b2 006a 043e c700 0501 bf1d
    0x0000040: 2bb6 00f8 b600 74b6 0078 2bba 0100 0000
    0x0000050: b200 93b6 0097 3a06 3a05 59c7 0005 01bf
    0x0000060: 3a04 1906 b200 93b6 009b a600 7619 04b2
    0x0000070: 00a0 a600 09b2 00a0 a700 71bb 00a2 5919
    0x0000080: 04b6 00a8 3a0b 2b19 0bb8 00fc b200 a0b7
    0x0000090: 00ac 3a07 1907 3a08 1904 b600 afc0 00a4
    0x00000a0: 3a09 1909 b200 a0a5 0034 bb00 a259 1909
    0x00000b0: b600 a83a 0b2b 190b b800 fcb2 00a0 b700
    0x00000c0: ac3a 0a19 0819 0ab6 00b3 190a 3a08 1909
    0x00000d0: b600 afc0 00a4 3a09 a7ff ca19 07a7 000c
    0x00000e0: 1904 1905 1906 b800 b9b7 00bc b02a 2bb6
    0x00000f0: 00ef b601 02b0                         
  Stackmap Table:
    same_frame(@11)
    same_frame(@15)
    full_frame(@39,{Object[#2],Object[#34],Object[#86]},{Object[#86]})
    same_frame(@46)
    full_frame(@63,{Object[#2],Object[#34],Object[#86],Integer},{Uninitialized[#46],Uninitialized[#46],Object[#98]})
    full_frame(@96,{Object[#2],Object[#34],Object[#86],Integer,Top,Object[#206],Object[#208]},{Uninitialized[#46],Uninitialized[#46],Object[#164]})
    full_frame(@123,{Object[#2],Object[#34],Object[#86],Integer,Object[#164],Object[#206],Object[#208]},{Uninitialized[#46],Uninitialized[#46]})
    full_frame(@162,{Object[#2],Object[#34],Object[#86],Integer,Object[#164],Object[#206],Object[#208],Object[#162],Object[#162],Object[#164],Top,Object[#4]},{Uninitialized[#46],Uninitialized[#46]})
    full_frame(@219,{Object[#2],Object[#34],Object[#86],Integer,Object[#164],Object[#206],Object[#208],Object[#162],Object[#162],Object[#164],Top,Object[#4]},{Uninitialized[#46],Uninitialized[#46]})
    full_frame(@224,{Object[#2],Object[#34],Object[#86],Integer,Object[#164],Object[#206],Object[#208]},{Uninitialized[#46],Uninitialized[#46]})
    full_frame(@233,{Object[#2],Object[#34],Object[#86],Integer,Object[#164],Object[#206],Object[#208]},{Uninitialized[#46],Uninitialized[#46],Object[#4]})
    full_frame(@237,{Object[#2],Object[#34],Object[#86]},{})

    at scala.collection.immutable.StringLike.r(StringLike.scala:287)
    at scala.collection.immutable.StringLike.r$(StringLike.scala:287)
    at scala.collection.immutable.StringOps.r(StringOps.scala:29)
    at scala.collection.immutable.StringLike.r(StringLike.scala:276)
    at scala.collection.immutable.StringLike.r$(StringLike.scala:276)
    at scala.collection.immutable.StringOps.r(StringOps.scala:29)
    at ammonite.runtime.SpecialClassLoader$.<init>(ClassLoaders.scala:40)
    at ammonite.runtime.SpecialClassLoader$.<clinit>(ClassLoaders.scala)
    at ammonite.runtime.Evaluator$$anon$1.initialFrame(Evaluator.scala:80)
    at ammonite.runtime.Evaluator$$anon$1.<init>(Evaluator.scala:89)
    at ammonite.runtime.Evaluator$.apply(Evaluator.scala:59)
    at ammonite.interp.Interpreter.<init>(Interpreter.scala:53)
    at ammonite.repl.Repl.<init>(Repl.scala:41)
    at ammonite.Main.instantiateRepl(Main.scala:68)
    at ammonite.Main.run(Main.scala:108)
    at ammonite.Main$.$anonfun$main$2(Main.scala:250)
    at ammonite.Main$$$Lambda$74/522764626.apply(Unknown Source)
    at ammonite.Main$.ifContinually$1(Main.scala:229)
    at ammonite.Main$.$anonfun$main$1(Main.scala:231)
    at ammonite.Main$$$Lambda$73/120694604.apply(Unknown Source)
    at scala.Option.foreach(Option.scala:257)
    at ammonite.Main$.main(Main.scala:231)
    at ammonite.Main.main(Main.scala)

A. あなたとJava今すぐアップデート


便利な機能たち


Syntax Highlighting

Ammonite Scala
スクリーンショット 2017-02-08 23.57.45.png スクリーンショット 2017-02-08 23.57.55.png

Multi-line Editing

REPL中で上下にカーソル移動ができる。最終行でEnterを押さない限りコードは評価されない。

コードを楽に編集できる。

※履歴もマルチラインに対応!


Import

ファイルインポート

.scファイルをインポートできる

Foo.sc
import $file.Bar, Bar._

println(message)
Bar.sc
val message = "Hello World"
> amm Foo.sc
Hello World

ライブラリインポート

Mavenリポジトリからライブラリをインポートできる。ちょっとライブラリを試してみたい時にすごく便利!!

ToJson.sc
import $ivy.`com.typesafe.play::play-json:2.4.6`, play.api.libs.json.Json

val json = Json.toJson(Map("hello" -> "world"))
println(json)
> amm ToJson.sc 
{"hello":"world"}

Save/Load session

REPLの状態を記録して、戻せる。

> amm
@ val foo = "foo" 
foo: String = "foo"
@ repl.sess.save() 

@ val bar = "bar" 
bar: String = "bar"
@ foo 
res3: String = "foo"
@ bar 
res4: String = "bar"
@ repl.sess.load() 
res5: ammonite.repl.SessionChanged = 
Removed Imports: Set('res1, 'res4, 'res3, 'bar)
@ foo 
res6: String = "foo"
@ bar 
cmd7.sc:1: not found: value bar
val res7 = bar
           ^
Compilation Failed

セッションに名前をつけることもできる。

// 保存
@ repl.sess.save("check point1")
// 読み込み
@ repl.sess.load("check point1")

最後に

紹介した以外にもAmmonite-REPLには便利な機能がたくさんあります

  • Repl API
  • Builtin Utilities
  • Compiler Flags
  • etc..

これであなたも富豪的REPL使い

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.