I'm new on Scala and I'm trying to pass a function/method as parameter to another by using unit, but it gives me the following error:
Timer.<error: >
My code is the following:
object Timer {
def oncePerSecond(callback: () => unit) {
while (true) {
callback(); Thread sleep 1000
}
}
def timeFlies() {
println("The time passes...")
}
def main(args: Array[String]) {
oncePerSecond(timeFlies)
}
}
But I'm certainly my code is correct and I don't understand why I'm getting this. Can someone help me to find this bug?
The error seems to be in the word "unit" on line 2.
Unit with a capital U fixes the error. Classes in Scala begin with a capital letter.
Related
I wrote a code below in Scala .
object Main {
def main(args: Array[String]): Unit = {
println(main)
}
}
It gave output as :
Main$$$Lambda$3/1543727556#3930015a
Why is this value returned ?
Also, When I wrote a simple method like one below :
def wow(): Unit = {
println(wow)
}
But it gives compilation error.
Why putStrLn in flatMap followed by a result statement didn't get effectively write to stdout?
object Mgr extends App {
def main1(args: Array[String]) = getStrLn.flatMap { s =>
putStrLn(s) // Why this did not write to console?
UIO.succeed(s)
}
override def run(args: List[String]): URIO[zio.ZEnv, Int] = main1(Array()).fold(_ => 1,
{ x =>
println(x) // only this line wrote to console, why?
0
})
}
Your problem is basically, that you put two effects into single flatMap.
By invoking putStrLn(s) you're not actually printing to console, you're merely creating the description of the action that will print when your program is interpreted and run (when method run is called). And because in your flatmap only last value is returned (in your case UIO.succeed(s)), then only it will be taken into consideration while constructing ZIO program.
You can fix your program by chaining both actions.
You can do it with *> operator:
def main1(args: Array[String]) = getStrLn.flatMap { s =>
putStrLn(s) *> UIO.succeed(s)
}
or you could just put effects into separate flatMaps. But since you want to create side-effect (by printing value), but then pass value further unchanged, you need to use special function tap:
def main1(args: Array[String]) = getStrLn.tap { s =>
putStrLn(s)
}.flatMap { s =>
UIO.succeed(s)
}
Your issue is also described (with other pitfalls) in this great article (look at the first point).
I am fairly new to Scala macros, and am trying to write a very basic DSL.
I have the following Scala class:
abstract class SpecialFunction {
def apply(): Unit
}
and the following Scala macro:
def mImpl(c: Context)(bodyBlock: c.Expr[Unit]): c.Expr[X] =
c.universe.reify {
new X(new SpecialFunction {
override def apply() {
bodyBlock.splice
}
})
}
def m(bodyBlock: Unit): X = macro mImpl
So far so good. For example, it allows me to write:
def example = m {
println("Hello, world")
}
And this compiles down to:
def example = new X(new SpecialFunction {
override def apply() {
println("Hello, world")
}
})
But this formulation does not allow me to have local variables in such an "m block". For example, I cannot write:
def example = m {
val x = 7
println(x.toString)
}
At compile time I get the error:
symbol value x does not exist in example
However, what I want to achieve is this:
def example = new X(new SpecialFunction {
override def apply() {
val x = 7
println(x.toString)
}
})
(I think I understand why this is the case: sub-expressions are evaluated before being passed to the macro, and thus the reference to x is invalid).
So my question is this: How can I get the above to work? (I just want the extra code defined in the macro to be "copy-pasted" around the code in the "m block", like in a C++ macro.)
Any help would be greatly appreciated :-)
Your output expression is keeping a reference to the old x symbol, but instead it should be a reference to a new one. Therefore, you can reset all the junk references in the tree you aim to reuse by applying resetLocalAttrs from Context.
How about...?
def mImpl(c: Context)(bodyBlock: c.Expr[Unit]): c.Expr[X] =
c.universe.reify {
new X(new SpecialFunction {
override def apply() {
c.Expr[Unit](c.resetLocalAttrs(bodyBlock.tree)).splice
}
})
}
In this question, you can read a great explanation by the Scala Macros guy.
I am just starting out going through a tutorial on scala and have hit a block. I have merged together a couple of examples and am getting an error, but don't know why.
import java.text.DateFormat._
import java.util.{Date, Locale}
object FrenchDate {
def main(args: Array[String]) {
timer(println(frenchDate))
}
def frenchDate():String = {
val now = new Date
val df = getDateInstance(LONG, Locale.FRANCE)
df format now
}
def timer(callback: () => Unit) {
while(true) {callback(); Thread sleep 1000}
}
}
Brings the error
error: type mismatch;
found : Unit
required: () => Unit
println(frenchDate)
while the below works
import java.text.DateFormat._
import java.util.{Date, Locale}
object FrenchDate {
def main(args: Array[String]) {
timer(frenchDate)
}
def frenchDate() {
val now = new Date
val df = getDateInstance(LONG, Locale.FRANCE)
println(df format now)
}
def timer(callback: () => Unit) {
while(true) {callback(); Thread sleep 1000}
}
}
The only difference is that the date is printed out in frenchDate() in the second once whereas it is returned and printed in the callback on the first.
The difference is that this line:
timer(println(frenchDate))
is trying to call println(frenchDate) and use the return value (which is Unit) as the callback to pass to timer. You probably want:
timer(() => println(frenchDate))
or possibly
timer(() => { println(frenchDate) })
(I'm not a Scala dev, so I'm not sure of the right syntax, but I'm pretty confident about what's wrong in your current code :)
EDIT: According to comments, this should work too and may be more idiomatic:
timer { () => println(frenchDate) }
is there any way to have a tail-recursive function inside CPS not throwing a StackOverflow?
import scala.util.continuations._
object CPSStackOverflow {
def main(args: Array[String]) = {
reset {
def recurse(i: Int): Unit #suspendable = {
println(i)
shift { k: (Unit => Unit) =>
k( () ) // just continue
}
recurse(i + 1)
}
recurse(1)
}
}
}
results in following StackOverflowError:
1298
1299
1300
Exception in thread "main" java.lang.StackOverflowError
at java.nio.CharBuffer.wrap(CharBuffer.java:350)
at sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:246)
at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:106)
at java.io.OutputStreamWriter.write(OutputStreamWriter.java:190)
at java.io.BufferedWriter.flushBuffer(BufferedWriter.java:111)
at java.io.PrintStream.write(PrintStream.java:476)
at java.io.PrintStream.print(PrintStream.java:619)
at java.io.PrintStream.println(PrintStream.java:773)
at scala.Console$.println(Console.scala:198)
at scala.Predef$.println(Predef.scala:182)
at test.CPSStackOverflow$$anonfun$main$1.recurse$1(CPSStackOverflow.scala:9)
at test.CPSStackOverflow$$anonfun$main$1$$anonfun$recurse$1$2.apply(CPSStackOverflow.scala:13)
at test.CPSStackOverflow$$anonfun$main$1$$anonfun$recurse$1$2.apply(CPSStackOverflow.scala:10)
at scala.util.continuations.ControlContext$$anonfun$flatMap$2$$anonfun$apply$2.apply(ControlContext.scala:71)
at test.CPSStackOverflow$$anonfun$main$1$$anonfun$recurse$1$1.apply(CPSStackOverflow.scala:11)
at test.CPSStackOverflow$$anonfun$main$1$$anonfun$recurse$1$1.apply(CPSStackOverflow.scala:10)
at scala.util.continuations.package$$anonfun$shiftR$1.apply(package.scala:58)
at scala.util.continuations.package$$anonfun$shiftR$1.apply(package.scala:58)
at scala.util.continuations.ControlContext$$anonfun$flatMap$2.apply(ControlContext.scala:68)
at scala.util.continuations.ControlContext$$anonfun$flatMap$2.apply(ControlContext.scala:67)
at scala.util.continuations.ControlContext$$anonfun$flatMap$2$$anonfun$apply$2.apply(ControlContext.scala:73)
at test.CPSStackOverflow$$anonfun$main$1$$anonfun$recurse$1$1.apply(CPSStackOverflow.scala:11)
at test.CPSStackOverflow$$anonfun$main$1$$anonfun$recurse$1$1.apply(CPSStackOverflow.scala:10)
at scala.util.continuations.package$$anonfun$shiftR$1.apply(package.scala:58)
at scala.util.continuations.package$$anonfun$shiftR$1.apply(package.scala:58)
etc...
Any way to circumvent this error? trampolining? stack-unwinding by throwing exceptions?
Thanks!
You are calling another function inside the continuation. Scala doesn't support cross-method tail recursion, because the JVM doesn't.
You can run Java with -Xss2M, however that error might occur only a thousand iterations later. As long as your method is not tail recursive you will not be able to get around this problem.