I have two statements like this:
val a = 1
val b = 2
In between the 2 statements, I want to pause for N seconds like I can in bash with sleep command.
You can try:
val a = 1
Thread.sleep(1000) // wait for 1000 millisecond
val b = 2
You can change 1000 to other values to accommodate to your needs.
Given:
package object wrap {
import java.time._
def delayed[A](a: => A): A = {
Console println Instant.now
Thread.sleep(1000L)
val x = a
Console println Instant.now
x
}
}
You can:
Welcome to Scala 2.12.0-M3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_60).
Type in expressions for evaluation. Or try :help.
scala> $intp.setExecutionWrapper("wrap.delayed")
scala> { println("running"); 42 }
2016-02-20T06:28:17.372Z
running
2016-02-20T06:28:18.388Z
res1: Int = 42
scala> :quit
Related
Is it possible to create (enter) nested environments in Scala REPL, such that after exiting the nested environment, all variable bindings created within the exited environment will be lost?
Here is what I wish a session could look like:
scala> val x = 1
x: Int = 1
scala> enter // How to implement this?
// Entering nested context (type exit to exit)
scala> val x = 2
x: Int = 2
scala> val y = 3
y: Int = 3
scala> exit // How to implement this?
// Exiting nested context
scala> assert(x == 1)
scala> y
<console>:12: error: not found: value y
y
^
scala>
This isn't possible with the current Scala REPL, but you can achieve something similar using the Ammonite REPL:
Welcome to the Ammonite Repl 0.8.2
(Scala 2.12.1 Java 1.8.0_121)
# val x = 1
x: Int = 1
# repl.sess.save("first")
res1_1: ammonite.repl.SessionChanged =
# val x = 2
x: Int = 2
# val y = 3
y: Int = 3
# repl.sess.save("second") ; repl.sess.load("first")
res4_1: ammonite.repl.SessionChanged =
Removed Imports: Set('y, 'res1_1, 'res1_0)
# y
cmd5.sc:1: not found: value y
val res5 = y
^
Compilation Failed
# x
res5: Int = 1
These sessions aren't nested exactly the way you describe, but are easy to track by name, and can overlap. That is after repl.sess.save("first"), you still have access to the original x if you don't override it.
After playing around with it some more, I was able to concoct a simple object that uses a stack to track the sessions and load/save them. It can be placed in ~/.ammonite/predef.sc to load automatically with the Ammonite REPL:
object SessionStack {
case class AmmSession(id: Int = 1) {
def name = s"session_${id}"
def next = AmmSession(id + 1)
}
private var sessions = collection.mutable.Stack.empty[AmmSession]
private var current = AmmSession()
def enter: Unit = {
sessions.push(current.copy())
repl.sess.save(current.name)
current = current.next
}
def exit: Unit = if(sessions.nonEmpty) {
current = sessions.pop()
repl.sess.load(current.name)
} else {
println("Nothing to exit.")
}
}
import SessionStack._
I haven't tested this rigorously, so there may be an edge-case that isn't covered, but I was able to go a few levels deep easily and then peel back the layers.
I am creating a very simple extension of scala.tools.nsc.interpreter.ILoop with the intent of adding some additional bindings, but even in the most basic use-case the tab-completion does not seem to work. If I type in code it interprets and works as expected, but I no tab-completion. Is there something specific that needs to be defined in order for tab-completion to be enabled in the interactive interpreter (REPL)?
My use-case is as simple as the following:
val repl = new ILoop
repl.process(new Settings {
usejavacp.value = true
deprecation.value = true
})
Is there something other than ILoop I should be using?
It kind of works for me, modulo version.
$ scalacm myintp.scala && scalam myintp.Test
Welcome to Scala 2.12.0-RC2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_101).
Type in expressions for evaluation. Or try :help.
scala> 42
res0: Int = 42
scala> 42.
!= < >>> doubleValue isNaN isValidShort shortValue toDouble toShort
% << ^ floatValue isNegInfinity isWhole signum toFloat unary_+
& <= abs floor isPosInfinity longValue to toHexString unary_-
* == byteValue getClass isValidByte max toBinaryString toInt unary_~
+ > ceil intValue isValidChar min toByte toLong underlying
- >= compare isInfinite isValidInt round toChar toOctalString until
/ >> compareTo isInfinity isValidLong self toDegrees toRadians |
scala> 42.s
self shortValue signum synchronized
scala> 42.self
res1: Int = 42
scala> :quit
Source:
$ cat myintp.scala
package myintp
import scala.tools.nsc._
import scala.tools.nsc.interpreter._
/* 2.12 */
object Test extends App {
val ss = new Settings {
usejavacp.value = true
deprecation.value = true
}
def repl = new ILoop {
override def createInterpreter(): Unit = {
super.createInterpreter()
}
}
repl process ss
}
/* 2.11
object Test extends App {
def repl = new ILoop {
override def createInterpreter(): Unit = {
def binder: Unit = intp beQuietDuring {
intp directBind ("foo", "bar")
intp bind ("baz", "boo")
}
super.createInterpreter()
intp initialize binder
}
}
repl process new Settings
}
*/
/* 2.9
object Test extends App {
def repl = new ILoop {
def binder: Unit = intp beQuietDuring {
intp bind ("baz", "boo")
}
override def loop(): Unit = {
binder
super.loop()
}
}
repl process new Settings
}
*/
I found this a bit confusing. I thought futures in scala are inmutable containers that once set, always return the same value.
So I have a future:
val y = future {Thread.sleep(1000); 1};
Now when i immediately (before the future resolves) pass it to Await.result block twice:
Await.result(for (r1 <- y; r2 <- y) yield (r1, r2), 60 seconds)
I get a TimetoutException.
However if i do it once the future is resolved, everything works fine and returns (1,1) as expected.
What is the reason of this behavior?
Edit:
I'm using implicit ExecutionContext.Implicits.global and scala.concurrent # scala 2.10.3
Edit2:
If I create another future instance doing the same thing and do Await.result on them both it doesn't block.
This appears to be an artifact of executing it in the REPL.
You can even reproduce it using 2 separate future instances, without any call to Thread.sleep,
and using only pre-fulfilled futures (which means that there is not even any future thread involed).
Yes, seriously:
import scala.concurrent._
import duration._
import ExecutionContext.Implicits.global
val x = Future.successful(1)
val y = Future.successful(2)
Await.result(x.flatMap{_ => y.map{ _ => 0 } }, Duration(10, SECONDS)) // triggers a timeout
Interestingly this does not trigger any timeout if you change the last line to this:
Await.result(x.flatMap{_ => Future.successful(2).map{ _ => 0 } }, Duration(10, SECONDS))
It seems that the culprint is that your whole code snippet, when evaled in the REPL, is actually wrapped in an object.
This means that x and y here are actually members of the object, rather than local variables
More importantly, the call to Await is now part of the constructor of this wrapper object.
For some reason that I have yet to investigate, it seems to be the fact that the call to Await is done in a constructor that triggers the blocking
(you can verify it easily by wrapping this call in a dummy class and instantiating it).
The reason you don't want to start threads from class initializers is that cycles in classloading will block. A Scala object is just an instance created in a static block. The closure's reference to y is a cycle. In 2.11, use -Yrepl-class-based to help it work.
Lets examine the stack trace for the hang when the closure class needs X.z:
apm#mara:~$ goof
Welcome to Scala version 2.11.0-RC3 (OpenJDK 64-Bit Server VM, Java 1.7.0_25).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import scala.concurrent._
import scala.concurrent._
scala> import duration._
import duration._
scala> import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.ExecutionContext.Implicits.global
scala> object X { val y = Future { 9 } ; val z = Future { 7 } ; val r = Await.result(for (a <- y; b <- z) yield (a+b), 5.seconds) }
defined object X
scala> X.r
java.lang.NoClassDefFoundError: Could not initialize class $line15.$read$$iw$$iw$$iw$$iw$$iw$$iw$X$
at $line15.$read$$iw$$iw$$iw$$iw$$iw$$iw$X$$anonfun$3.apply(<console>:14)
at $line15.$read$$iw$$iw$$iw$$iw$$iw$$iw$X$$anonfun$3.apply(<console>:14)
at scala.concurrent.Future$$anonfun$flatMap$1.apply(Future.scala:251)
at scala.concurrent.Future$$anonfun$flatMap$1.apply(Future.scala:249)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
at scala.concurrent.impl.ExecutionContextImpl$AdaptedForkJoinTask.exec(ExecutionContextImpl.scala:121)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
java.util.concurrent.TimeoutException: Futures timed out after [5 seconds]
at scala.concurrent.impl.Promise$DefaultPromise.ready(Promise.scala:219)
at scala.concurrent.impl.Promise$DefaultPromise.result(Promise.scala:223)
at scala.concurrent.Await$$anonfun$result$1.apply(package.scala:111)
at scala.concurrent.BlockContext$DefaultBlockContext$.blockOn(BlockContext.scala:53)
at scala.concurrent.Await$.result(package.scala:111)
... 34 elided
And just to show it working:
apm#mara:~$ goof -Yrepl-class-based
Welcome to Scala version 2.11.0-RC3 (OpenJDK 64-Bit Server VM, Java 1.7.0_25).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import scala.concurrent._
import scala.concurrent._
scala> import duration._
import duration._
scala> import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.ExecutionContext.Implicits.global
scala> object X { val y = Future { 9 } ; val z = Future { 7 } ; val r = Await.result(for (a <- y; b <- z) yield (a+b), 5.seconds) }
defined object X
scala> X.r
res0: Int = 16
-Hi. I'd like to embed Scala REPL with initialized environment into my app. I've looked at IMain class and it seems I could do it via instance of it. The instance is created and then stored into intp public var in process() of ILoop.
How can I bind some names and/or add some imports before process() (e.g. before REPL)?
Following code fails on line 3 because intp is not yet created (=> NPE):
val x = 3
val interp = new ILoop
interp.bind("x", x) // -> interp.intp.bind("x", x)
val settings = new Settings
settings.usejavacp.value = true
interp.process(settings)
Thank you-.
UPDATE: Overriding createInterpreter() unfortunately doesn't work:
val x = 3
val interp = new ILoop {
override def createInterpreter() {
super.createInterpreter()
intp.bind("x", x) // -> interp.intp.bind("x", x)
}
}
val settings = new Settings
settings.usejavacp.value = true
interp.process(settings)
Interpreter is stuck on input (looks like deadlock, happens only with code above):
x: Int = 3
Failed to created JLineReader: java.lang.NoClassDefFoundError: scala/tools/jline/console/completer/Completer
Falling back to SimpleReader.
Welcome to Scala version 2.9.2 (OpenJDK 64-Bit Server VM, Java 1.7.0_06-icedtea).
Type in expressions to have them evaluated.
Type :help for more information.
scala> println
<infinite_sleep>
Thanks dvigal for suggestion.
There is a github project called scala-ssh-shell which may do what you want, or at least get you closer.
-Hi, sorry I not Scala REPL hacker but i think you can do something like:
class YourILoop(in0: Option[BufferedReader], protected override val out: JPrintWriter)
extends ILoop(in0, out) {
override def createInterpreter() {
if (addedClasspath != "")
settings.classpath append addedClasspath
intp = new ILoopInterpreter
val x = 3;
intp.bind("x", x)
}
}
object Run {
def errorFn(str: String): Boolean = {
Console.err println str
false
}
def process(args: Array[String]): Boolean = {
val command = new GenericRunnerCommand(args.toList, (x: String) => errorFn(x))
import command.{ settings, howToRun, thingToRun }
new YourILoop process settings
}
def main(args: Array[String]) {
process(args)
}
}
Is there a hotkey to stop/exit the Scala REPL ?
Example: I start the Scala REPL from SBT with command console, then do something stupid like an endless loop and want to end the REPL without closing the shell at all. Something like Ctrl+C, Ctrl+D or Ctrl+Z (which all do not work).
Update:
Used OS: Windows 7 64 Bit.
Ctrl+D exists SBT and the REPL, but Ctrl+D does NOT exit the REPL when I am in an endless loop like
while(true) prinln("test")
Is there a way to get out of the endless loop with a hotkey without closing the shell ? Or is this not possible because the REPL will not react to hotkeys until the loop is through (which will, of course, not happen in this case) ?
The following works with Scala 2.10.0-M6, but in 2.9.2 you can probably achieve something similar using :wrap in REPL power mode.
Assume that the REPL is started from sbt via sbt console—without loss of generality (you may otherwise just put the ReplUtil class on scala's class path). Assume the following class is on the class path, e.g. its source is at src/main/scala/ReplUtil.scala:
import java.util.concurrent.{Executors, ExecutorService, TimeoutException, TimeUnit}
import concurrent._
object ReplUtil {
#volatile private var exec: ExecutorService = _
#volatile private var threads = Set.empty[ Thread ]
private def freshPool() { exec = Executors.newCachedThreadPool() }
freshPool()
private implicit def context = ExecutionContext.fromExecutorService( exec )
def panic() {
(new Thread {
override def run() {
try {
exec.shutdownNow()
exec.awaitTermination( 1, TimeUnit.SECONDS )
} finally {
val th = threads
threads = Set.empty
th.foreach( _.stop )
freshPool()
}
}
}).start()
}
def spawn[T](t: => T) = {
var futPrint = false
val fut = future {
val th = Thread.currentThread()
threads += th
val res = try { t } finally { threads -= th }
if( futPrint ) println( "<calculation done>\n" + res )
t
}
try {
Await.result( fut, util.Duration( 4, TimeUnit.SECONDS )).toString
} catch {
case e: TimeoutException =>
futPrint = true
"<ongoing calculation>"
}
}
}
Then the following will activate the semi-asynchronous REPL:
$ sbt console
...
Welcome to Scala version 2.10.0-M6 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_33).
...
scala> import ReplUtil.panic
import ReplUtil.panic
scala> :power
** Power User mode enabled - BEEP WHIR GYVE **
...
scala> power.intp.setExecutionWrapper("ReplUtil.spawn")
scala> 2+2
res1: Int = 4
scala> Thread.sleep(6000); 33
<ongoing calculation>
scala> <calculation done>
res2: Int = 33
scala> while(true) { Thread.sleep(2000); println( "Zzz" )}
Zzz
Zzz
<ongoing calculation>
scala> panic
scala> [error] (pool-5-thread-1) java.lang.ExceptionInInitializerError
java.lang.ExceptionInInitializerError
...
Caused by: java.lang.InterruptedException: sleep interrupted
...
related to the topic is a useful Shift+D key binding for exiting non terminating evaluations of a program when inside an eclipse scala worksheet.