Take this simple bit of code:
var line = "";
do {
println("Please enter a non-empty line: ")
line = readLine()
} while (line.isEmpty())
println("You entered a non-empty line: " + line)
It's definitely not particularly elegant, especially with the unfortunate scoping of line -- however, I think it's quite simple to read.
Now trying to translate this directly to scalaz effect, I have come up with:
def nonEmptyLine: IO[String] = for {
_ <- putStrLn("Please enter a non-empty line:")
line <- readLn
r <- if (line.isEmpty()) nonEmptyLine else IO(line)
} yield r
(for {
line <- nonEmptyLine
_ <- putStrLn("You entered a non-empty line: " + line)
} yield ()).unsafePerformIO
Which makes me feel like I'm missing something, as this doesn't feel like an improvement at all? Is there some higher order control flow stuff I'm missing?
You can make this (at least arguably) a lot prettier by skipping the for notation and using the combinators *> and >>= to pipe everything together:
import scalaz._, Scalaz._, effect._, IO._
val prompt = putStrLn("Please enter a non-empty line:")
def report(line: String) = putStrLn("You entered a non-empty line: " + line)
def nonEmptyLine: IO[String] = prompt *> readLn >>= (
(line: String) => if (line.isEmpty) nonEmptyLine else line.point[IO]
)
And then:
scala> (nonEmptyLine >>= report).unsafePerformIO
Please enter a non-empty line:
You entered a non-empty line: This is a test.
In general, though, I'm not sure you should expect code written using scalaz.effect to be more concise or easier to read than a straightforward imperative solution.
Related
object Main extends App {
val p1 = Promise[Option[String]]()
val p2 = Promise[Option[String]]()
val f1 = p1.future
val f2 = p2.future
val res = (for{
file1Opt <- f1
file2Opt <- f2
file1 <- file1Opt
file2 <- file2Opt
} yield {
combineFiles(file1, file2)
}).fallbackTo(Future.successful("Files not found"))
Thread.sleep(2000)
println("XXXXXXXXXXXXXXXXXXX")
p1.success(Some("file one"))
p2.success(Some("file two"))
val finalData = res.map(s =>
s + " " + "add more data to the file"
)
finalData.map(println(_))
def combineFiles(f1: String, f2: String): String = {
f1 + " " + f2
}
}
I have two functions that return Future[Option[String]] and I need to combine the two strings into one string.
I want the output to be either combination of two strings and footer: "file one file two add more data to the file" or default when one or both of the Futures return None: "Files not found add more data to file".
How can this be achieved?
Compiler error:
Error:(16, 11) type mismatch;
found : Option[String]
required: scala.concurrent.Future[?]
file1 <- file1Opt
^
Well, without doing anything fancy like monad transformers or stuff, one can just simply nest for comprehensions. It will be more wordy, but no extra dependencies.
val res = (for{
file1Opt <- f1
file2Opt <- f2
} yield for {
file1 <- file1Opt
file2 <- file2Opt
} yield combineFiles(file1, file2))
.fallbackTo(Future.successful(Some("Files not found")))
//or, alternatively, .fallbackTo(Future.successful(None))
Ultimately, the problem here is that you try to combine Future and Option in a single for comprehension. That just doesn't work for the reasons other respondents mentioned. Nesting, however, works just fine.
The downside of the nesting is that you end up with very complex data structures, which might not be easy to use elsewhere in your program. You should think about how you would flatten them, i.e. going from Future[Option[String]] to just Future[String]. Is your particular case you can do something like this: res.map(_.getOrElse("")).
Okay, may 2 levels of nesting is fine, but you nest more than that, consider flattening that hierarchy before letting your colleagues deal with it. :)
Like alf mentioned in his answer, you can use monad tranformers for this, in this case OptionT.
An example using cats :
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import cats.data.OptionT
import cats.implicits._
val file1: Future[Option[String]] = Future.successful(Some("file1"))
val file2: Future[Option[String]] = Future.successful(Some("file2"))
val combinedOT: OptionT[Future, String] =
for {
f1 <- OptionT(file1)
f2 <- OptionT(file2)
} yield s"$f1 $f2"
val combinedFO: Future[Option[String]] = combinedOT.value
val combinedF: Future[String] = combinedOT.getOrElse("Files not found")
Note that if you use cats, you can replace the for comprehension in combinedOT2 by using a cartesian builder (the |#|), because file2 doesn't depend on file1 :
val combinedOT2: Future[Option[String]] =
(OptionT(file1) |#| OptionT(file2)).map(_ + " " + _).value
You can still use fallbackTo if the "combined" Future fails, eventhough it is probably better to use recover or recoverWith to actually check which Throwables you want to recover from.
I think exactly this problem is covered in this 47deg blog post, as well as in this one: monads do not compose, so you need a transformer from one monad to another, as there's no flatMap operation that would (flat) map a Future into Option.
I want to do something like this:
def assuming[A](condition: => Boolean)(f: => A): A = {
require(condition, /* print source-code of condition */)
f
}
Sample usage:
def fib(n: Int) = n match { // yes, yes, I know this is not efficient
case 0 => 0
case 1 => 1
case i => assuming(i > 0) { fib(i-1) + fib(i-2) }
}
Now, for example, if you call fib(-20), I want it to throw an exception with a message like Assertion failed: -20 > 0 or Assertation failed: i > 0
Dude, isn't an assert macro one of the basic use cases you implement to learn how to use macros?
Well, that's what I thought, too.
By "glean snippets" in my other answer I meant what specs2 does in its s2 macro.
Or, you can do an arbitrary representation, as in my variant rip-off of expecty.
I thought I'd type your example into REPL, in a couple of lines. After all, you're just trying to print the snippet from the source that corresponds to the tree representing your conditional.
What could be easier?
Of course, it's easier under -Yrangepos, but we can postulate positions.
I'm willing to share how far I got before I lost interest.
People (e.g., paulp, who is the vox paulpuli) want trees to have attachments representing "the source I typed on my keyboard", because, you know, maybe I want it for a message or to figure out what the user was trying to accomplish.
It looks like the predicate p doesn't have a range position. So the other idea is that we know the start of the macro application, which is the paren of the second param list, so working backward through the source, matching the closing paren of the first param list, is doable.
Note that showCode isn't helpful because for a conditional like 10 < 5 it shows false, neatly folded.
object X {
import reflect.macros.blackbox.Context
def impl[A: c.WeakTypeTag](c: Context)(p: c.Expr[Boolean])(body: c.Expr[A]) = {
import c.universe._
def treeLine(t: Tree): String = lineAt(t.pos)
def lineAt(pos: Position): String = if (pos.isRange) pos.lineContent.drop(pos.column - 1).take(pos.end - pos.start + 1) else "???"
val msg =
if (p.tree.pos.isRange) { // oh, joy
treeLine(p.tree)
} else {
/*
Console println s"content ${p.tree.pos.lineContent}"
Console println s"column ${p.tree.pos.column}" // alas, that's the column of the point of the top of the tree, e.g., < in "a < b".
val len = body.tree.pos.start - p.tree.pos.start
p.tree.pos.lineContent drop (p.tree.pos.column - 1) take len
*/
// OK, I get it: positions are a big mystery. Make woo-woo ghost noises.
// What we do know is the start of the apply, which must have a close paren or brace in front of it to match:
// apply(condition)(body)
showCode(p.tree)
}
q"require($p, $msg) ; $body"
}
def x[A](p: Boolean)(body: =>A): A = macro X.impl[A]
}
It just occurred to me to get the rangy position this way:
object X {
import reflect.macros.blackbox.Context
def impl(c: Context)(p: c.Expr[Boolean]) = {
import c.universe._
def lineAt(pos: Position): String = if (pos.isRange) pos.lineContent.drop(pos.column - 1).take(pos.end - pos.start + 1) else "???"
val msg = lineAt(c.macroApplication.pos) // oh, joy
q"require($p, $msg) ; new { def apply[A](body: =>A): A = body }"
}
def x(p: Boolean): { def apply[A](body: =>A): A } = macro X.impl
}
That's close on usage x(10 < 5)(println("hi")): requirement failed: (10 < 5)(p. Margin for error.
Have you consulted the docs at:
http://www.scala-lang.org/api/2.11.0/scala-reflect/#scala.reflect.api.Printers
scala> show(q"-1 < 0")
res6: String = -1.$less(0)
scala> showCode(q"-1 < 0")
res7: String = (-1).<(0)
Alternatively, folks have used source positions to glean snippets to print.
If you are using Scala 2.11.x the best way to go is the showCode method. This method will correctly print an arbitrary Scala tree. For example:
scala> import reflect.runtime.universe._
import reflect.runtime.universe._
showCode(q"3.14 < 42")
res1: String = 3.14.<(42)
In the previous versions of Scala you would have to use the method show which does not guarantee correctness:
scala> show(q"3.14 < 42")
res2: String = 3.14.$less(42)
The method showCode was designed with correctness in mind so it will not necessarily print beautiful code. If beauty is of importance for you can either contribute to the Scala Printers or you can write your own printer. Another interesting printer for Scala trees is the PrettyPrinter from Scala Refactoring.
I've been learning/experimenting with Scala in the REPL.
By the way, and as a side note, I'm quite impressed so far. I'm finding the language beautiful.
The following happened and need an explanation of what is going on.
Thanks in advance for any help given.
At the REPL entered:
def withMarks(mark: String)(body: => Unit){
println(mark + " Init")
body
println(mark + " End")
}
val a = "Testing clojure with paremeter by name as control structure"
withMarks("***"){
println(a)
println("more expressions")
}
Everything worked as expected.
Than happened what I consider weird, out of ignorance I suspect. I entered some more stuff:
class FileAsIterable{
def iterator = scala.io.Source.fromFile("/Users/MacBookProRetina/Google Drive/NewControl.scala").getLines()
}
val newIterator = new FileAsIterable with Iterable[String]
When evaluating the last line the REPL prints:
newIterator: FileAsIterable with Iterable[String] = (def withMarks(mark: String)(body: => Unit){, println(mark + " Init"), body, println(mark + " End"), }, val a = "Hola Mundo", withMarks("***"){, println(a), })
I keep getting the same result even after restarting the terminal in the Mac, and running the scala REPL at different directory locations.
Don't know how the newIterator val got connected to the the withMarks def.
Nevermind. I was just confused by the contents of the file
I want to do something like this:
def assuming[A](condition: => Boolean)(f: => A): A = {
require(condition, /* print source-code of condition */)
f
}
Sample usage:
def fib(n: Int) = n match { // yes, yes, I know this is not efficient
case 0 => 0
case 1 => 1
case i => assuming(i > 0) { fib(i-1) + fib(i-2) }
}
Now, for example, if you call fib(-20), I want it to throw an exception with a message like Assertion failed: -20 > 0 or Assertation failed: i > 0
Dude, isn't an assert macro one of the basic use cases you implement to learn how to use macros?
Well, that's what I thought, too.
By "glean snippets" in my other answer I meant what specs2 does in its s2 macro.
Or, you can do an arbitrary representation, as in my variant rip-off of expecty.
I thought I'd type your example into REPL, in a couple of lines. After all, you're just trying to print the snippet from the source that corresponds to the tree representing your conditional.
What could be easier?
Of course, it's easier under -Yrangepos, but we can postulate positions.
I'm willing to share how far I got before I lost interest.
People (e.g., paulp, who is the vox paulpuli) want trees to have attachments representing "the source I typed on my keyboard", because, you know, maybe I want it for a message or to figure out what the user was trying to accomplish.
It looks like the predicate p doesn't have a range position. So the other idea is that we know the start of the macro application, which is the paren of the second param list, so working backward through the source, matching the closing paren of the first param list, is doable.
Note that showCode isn't helpful because for a conditional like 10 < 5 it shows false, neatly folded.
object X {
import reflect.macros.blackbox.Context
def impl[A: c.WeakTypeTag](c: Context)(p: c.Expr[Boolean])(body: c.Expr[A]) = {
import c.universe._
def treeLine(t: Tree): String = lineAt(t.pos)
def lineAt(pos: Position): String = if (pos.isRange) pos.lineContent.drop(pos.column - 1).take(pos.end - pos.start + 1) else "???"
val msg =
if (p.tree.pos.isRange) { // oh, joy
treeLine(p.tree)
} else {
/*
Console println s"content ${p.tree.pos.lineContent}"
Console println s"column ${p.tree.pos.column}" // alas, that's the column of the point of the top of the tree, e.g., < in "a < b".
val len = body.tree.pos.start - p.tree.pos.start
p.tree.pos.lineContent drop (p.tree.pos.column - 1) take len
*/
// OK, I get it: positions are a big mystery. Make woo-woo ghost noises.
// What we do know is the start of the apply, which must have a close paren or brace in front of it to match:
// apply(condition)(body)
showCode(p.tree)
}
q"require($p, $msg) ; $body"
}
def x[A](p: Boolean)(body: =>A): A = macro X.impl[A]
}
It just occurred to me to get the rangy position this way:
object X {
import reflect.macros.blackbox.Context
def impl(c: Context)(p: c.Expr[Boolean]) = {
import c.universe._
def lineAt(pos: Position): String = if (pos.isRange) pos.lineContent.drop(pos.column - 1).take(pos.end - pos.start + 1) else "???"
val msg = lineAt(c.macroApplication.pos) // oh, joy
q"require($p, $msg) ; new { def apply[A](body: =>A): A = body }"
}
def x(p: Boolean): { def apply[A](body: =>A): A } = macro X.impl
}
That's close on usage x(10 < 5)(println("hi")): requirement failed: (10 < 5)(p. Margin for error.
Have you consulted the docs at:
http://www.scala-lang.org/api/2.11.0/scala-reflect/#scala.reflect.api.Printers
scala> show(q"-1 < 0")
res6: String = -1.$less(0)
scala> showCode(q"-1 < 0")
res7: String = (-1).<(0)
Alternatively, folks have used source positions to glean snippets to print.
If you are using Scala 2.11.x the best way to go is the showCode method. This method will correctly print an arbitrary Scala tree. For example:
scala> import reflect.runtime.universe._
import reflect.runtime.universe._
showCode(q"3.14 < 42")
res1: String = 3.14.<(42)
In the previous versions of Scala you would have to use the method show which does not guarantee correctness:
scala> show(q"3.14 < 42")
res2: String = 3.14.$less(42)
The method showCode was designed with correctness in mind so it will not necessarily print beautiful code. If beauty is of importance for you can either contribute to the Scala Printers or you can write your own printer. Another interesting printer for Scala trees is the PrettyPrinter from Scala Refactoring.
For example suppose I have
for (line <- myData) {
println("}, {")
}
Is there a way to get the last line to print
println("}")
Can you refactor your code to take advantage of built-in mkString?
scala> List(1, 2, 3).mkString("{", "}, {", "}")
res1: String = {1}, {2}, {3}
Before going any further, I'd recommend you avoid println in a for-comprehension. It can sometimes be useful for tracking down a bug that occurs in the middle of a collection, but otherwise leads to code that's harder to refactor and test.
More generally, life usually becomes easier if you can restrict where any sort of side-effect occurs. So instead of:
for (line <- myData) {
println("}, {")
}
You can write:
val lines = for (line <- myData) yield "}, {"
println(lines mkString "\n")
I'm also going to take a guess here that you wanted the content of each line in the output!
val lines = for (line <- myData) yield (line + "}, {")
println(lines mkString "\n")
Though you'd be better off still if you just used mkString directly - that's what it's for!
val lines = myData.mkString("{", "\n}, {", "}")
println(lines)
Note how we're first producing a String, then printing it in a single operation. This approach can easily be split into separate methods and used to implement toString on your class, or to inspect the generated String in tests.
I agree fully with what has been said before about using mkstring, and distinguishing the first iteration rather than the last one. Would you still need to distinguish on the last, scala collections have an init method, which return all elements but the last.
So you can do
for(x <- coll.init) workOnNonLast(x)
workOnLast(coll.last)
(init and last being sort of the opposite of head and tail, which are the first and and all but first). Note however than depending on the structure, they may be costly. On Vector, all of them are fast. On List, while head and tail are basically free, init and last are both linear in the length of the list. headOption and lastOption may help you when the collection may be empty, replacing workOnlast by
for (x <- coll.lastOption) workOnLast(x)
You may take the addString function of the TraversableOncetrait as an example.
def addString(b: StringBuilder, start: String, sep: String, end: String): StringBuilder = {
var first = true
b append start
for (x <- self) {
if (first) {
b append x
first = false
} else {
b append sep
b append x
}
}
b append end
b
}
In your case, the separator is }, { and the end is }
If you don't want to use built-in mkString function, you can make something like
for (line <- lines)
if (line == lines.last) println("last")
else println(line)
UPDATE: As didierd mentioned in comments, this solution is wrong because last value can occurs several times, he provides better solution in his answer.
It is fine for Vectors, because last function takes "effectively constant time" for them, as for Lists, it takes linear time, so you can use pattern matching
#tailrec
def printLines[A](l: List[A]) {
l match {
case Nil =>
case x :: Nil => println("last")
case x :: xs => println(x); printLines(xs)
}
}
Other answers are rightfully pointed to mkString, and for a normal amount of data I would also use that.
However, mkString builds (accumulates) the end-result in-memory through a StringBuilder. This is not always desirable, depending on the amount of data we have.
In this case, if all we want is to "print" we don't need to build the big-result first (and maybe we even want to avoid this).
Consider the implementation of this helper function:
def forEachIsLast[A](iterator: Iterator[A])(operation: (A, Boolean) => Unit): Unit = {
while(iterator.hasNext) {
val element = iterator.next()
val isLast = !iterator.hasNext // if there is no "next", this is the last one
operation(element, isLast)
}
}
It iterates over all elements and invokes operation passing each element in turn, with a boolean value. The value is true if the element passed is the last one.
In your case it could be used like this:
forEachIsLast(myData) { (line, isLast) =>
if(isLast)
println("}")
else
println("}, {")
}
We have the following advantages here:
It operates on each element, one by one, without necessarily accumulating the result in memory (unless you want to).
Because it does not need to load the whole collection into memory to check its size, it's enough to ask the Iterator if it's exhausted or not. You could read data from a big file, or from the network, etc.