I have seen in some Scala code the use of ^^^ and don't understand its use, nor can see any documentation about it. Also I'm pretty sure it doesn't come from any external library, but it may be the case, maybe ? I know that ^^ is an operator for .map() but don't know if there is a similarity when you had a third ^.
Example of use :
case object TypeFoo extends Type {
override def toString() = "Foo"
}
case object TypeBar extends Type {
override def toString() = "Bar"
}
def repType= (
"Foo" ^^^ TypeFoo
| "Bar" ^^^ TypeBar
)
From what I may understand it could be "is defined by", but I'm really not sure, hence my question.
The Javadoc for the ^^^ method says:
A parser combinator that changes a successful result into the specified value.
p ^^^ v succeeds if p succeeds; discards its result, and returns v instead.
#param v The new result for the
parser, evaluated at most once (if p succeeds), not evaluated at all
if p fails.
#return a parser that has the same behaviour as the
current parser, but whose successful result is v
In other words, "Foo" ^^^ TypeFoo is just a shorthand for "Foo" ^^ (_ => TypeFoo).
Related
Consider the following example
def futureFoo() = {
Future.successful(true)
}
def recFoo(x: List[Int]): Unit = {
if (x.isEmpty) return
for {
b <- futureFoo()
v = getNewListOfValues(x.last)
_ = recFoo(v)
} yield b
}
I need to wait for futureFoo to finish and only then call recFoo again. The problem is no matter what I try I get the following error:
discarded non-Unit value
I also tried to convert it into a while loop but because of the future I either get the same error or the while condition doesn't update because it must be updated in a for comprehension or map.
Any ideas on how to prevent that error?
Try this.
def recFoo(x: List[Int]): Unit =
if (x.nonEmpty)
futureFoo().foreach(_ => recFoo(getNewListOfValues(x.last)))
The specific reason that you are getting
discarded non-Unit value
in your error message is that you have an expression after return.
Note that in Scala, the return keyword should almost never be used. Scala is an expression-oriented language; each block (such as a function body) evaluates to the value returned from the last line in the block.
So, for example, consider the following snippet:
val foo = {
import scala.util.Random
if (Random.nextInt() % 2 == 0) {
17
} else {
"bar"
}
}
Everything from if to the closing brace after "bar" is a single expression -- NOT a statement. Scala, in fact, does not have "if-statements" in the way that Java and other languages do. In particular, the compiler needs to infer a type for the name foo, and since foo could concretely be either the Int 17 or the String "bar", that inferred type is the closest common ancestor of both Int and String, which is Any.
In your question, the last expression in the body of recFoo is the following:
for {
b <- futureFoo()
v = getNewListOfValues(x.last)
_ = recFoo(v)
} yield b
What is the type of this expression? In many languages, for introduces a statement, but that's not true of Scala -- this is an expression, not a statement, and like all expressions it will have a value once we evaluate it. That value has type Future[Unit], and like all non-Unit values, the compiler is warning you that you are discarding a value, which is (almost) always a mistake. (Why would you go to the trouble of producing a non-Unit value and then not make use of it?, goes the thinking.)
I have a class Foo extends Bar and a List or other collection of base class:
val bars: Iterable[Bar]
I need to extract all Foo elements from the collection. The following is the code:
val fooes: Iterable[Foo] = bars
.filter(x => Try(x.isInstanceOf[Foo]).isSuccess))
.map(_.isInstanceOf[Foo])
Is there conciser approach?
val fooes: Iterable[Foo] = bars.collect{case foo:Foo => foo}
The .collect() method takes a partial-function as its parameter. In this case the function is defined only for Foo types. All others are ignored.
Couple of possible rewrites worth remembering in general
filter followed by map as collect
isInstanceOf followed by asInstanceOf as pattern match with typed pattern
Hence the following discouraged style
bars
.filter { _.isInstanceOf[Foo] }
.map { _.asInstanceOf[Foo] }
can be rewritten to idiomatic style
bars collect { case foo: Foo => foo }
...writing type tests and casts is rather verbose in Scala. That's
intentional, because it is not encouraged practice. You are usually
better off using a pattern match with a typed pattern. That's
particularly true if you need to do both a type test and a type cast,
because both operations are then rolled into a single pattern match.
Note the nature of typed pattern is still just runtime type check followed by runtime type cast, that is, it merely represent nicer stylistic clothing not an increase in type safety. For example
scala -print -e 'lazy val result: String = (42: Any) match { case v: String => v }'
expands to something like
<synthetic> val x1: Object = scala.Int.box(42);
if (x1.$isInstanceOf[String]()) {
<synthetic> val x2: String = (x1.$asInstanceOf[String]());
...
}
where we clearly see type check isInstanceOf followed by type cast asInstanceOf.
I have been trying to build a SQL parser with the scala-parser-combinator library, which I've simplified greatly into the code below.
class Expression
case class FalseExpr() extends Expression
case class TrueExpr() extends Expression
case class AndExpression(expr1: Expression, expr2: Expression) extends Expression
object SimpleSqlParser {
def parse(sql: String): Try[Expression] = new SimpleSqlParser().parse(sql)
}
class SimpleSqlParser extends RegexParsers {
def parse(sql: String): Try[_ <: Expression] = parseAll(expression, sql) match {
case Success(matched,_) => scala.util.Success(matched)
case Failure(msg,remaining) => scala.util.Failure(new Exception("Parser failed: "+msg + "remaining: "+ remaining.source.toString.drop(remaining.offset)))
case Error(msg,_) => scala.util.Failure(new Exception(msg))
}
private def expression: Parser[_ <: Expression] =
andExpr | falseExpr | trueExpr
private def falseExpr: Parser[FalseExpr] =
"false" ^^ (_ => FalseExpr())
private def trueExpr: Parser[TrueExpr] = "true" ^^ (_ => TrueExpr())
private def andExpr: Parser[Expression] =
expression ~ "and" ~ expression ^^ { case e1 ~ and ~ e2 => AndExpression(e1,e2)}
}
Without the 'and' parsing, it works fine. But I want to be able to parse things like 'true AND (false OR true)', for example. When I add the 'and' part to the definition of an expression, I get a StackOverflowError, the stack is alternating between the definitions of 'and' and 'expression'.
I understand why this is happening - the definition of expression begins with and, and vice-versa. But this seems like the most natural way to model this problem. In reality an expression could also be LIKE, EQUALS etc. Is there another way to model this kind of thing in general in order to get around the problem of recursive definitions.
scala.util.parsing.combinator.RegexParsers cannot handle left-recursive grammars. Your grammar can be summarized by the following production rules:
expression -> andExpr | falseExpr | trueExpr
...
andExpr -> expression "and" expression
expression is indirectly left-recursive via andExpr.
To avoid the infinite recursion, you need to reformulate the grammar so that it is not left-recursive anymore. One frequently-used way is to use repetition combinators, such as chainl1:
private def expression: Parser[_ <: Expression] =
chainl1(falseExpr | trueExpr, "and" ^^^ { AndExpression(_, _) })
Live on Scastie
The new expression matches one or more falseExpr/trueExpr, separated by "and", and combines the matched elements with AndExpression in a left-associative way. Conceptually, it corresponds to the following production rule:
expression -> (falseExpr | trueExpr) ("and" (falseExpr | trueExpr))*
If your grammar contains many tangled left-recursive production rules, you might want to consider other parser combinator libraries, such as GLL combinators, that directly support left recursion.
Consider the following function:
import java.util.concurrent.Callable;
def callable[T]( operation: =>T) : Callable[T] = {
new Callable[T] {
def call : T = operation
}
}
In the REPL, this code does what I want:
scala> val myCallable = callable {
| println("Side effect!");
| "Hi!"
| }
myCallable: java.util.concurrent.Callable[String] = $anon$1#11ba4552
scala> myCallable.call
Side effect!
res3: String = Hi!
scala> myCallable.call
Side effect!
res4: String = Hi!
The by-name parameter is not evaluated until the function 'call' is called, and is re-evaluated every time that function is called. That is the behavior I want.
But in the spec, it says the following about by-name parameters:
"the corresponding argument is not evaluated at the point of function application, but instead is evaluated at each use within the function."
From this description, it is unclear that I can rely on the behavior I want. What does a "use within the function mean"? How do I know that this refers to the point at which my Callable is called (sometime in the indefinite future), rather than the point at which it's defined (very much "within the function")?
The code is doing what I want. But I'd rest easier if I was sure this behavior is reliable, not a bug that might be "fixed" in some future version of scala.
This is not a bug - that behaviour is as intended. You can think of "evaluated at each use within the function" recursively as "evaluated at each use within an expression in the function when that expression is evaluated".
"The function" is the function you're passing your parameter to. What this passage tries to warn you about is this:
scala> def byName(arg: => String) = arg + arg
byName: (arg: => String)java.lang.String
scala> byName({println("hi") ; "foo" })
hi
hi
res0: java.lang.String = foofoo
i.e. your side effect will happen every time you reference the argument. Since you're only doing it once, that's not that relevant to your case (except for the point of evaluation, which is inside the function, not at the call site).
To expand on the previous answers and clarify the way to avoid this, you can capture the value in a val inside the function if you only want it to be evaluated once. By doing this you are causing evaluation of the "by name" parameter and are using the computed value more than once rather than causing 2 evaluations of the same expression.
scala> def byName(arg: => String) = {val computedArg = arg; computedArg + computedArg}
byName: (arg: => String)java.lang.String
scala> byName({"println("hi") ; "foo" })
hi
res0: java.lang.String = foofoo
In case you need to do that in the future...
Lastly, to get truly lazy evaluation of a method parameter (zero or one evaluations only), you can do this:
def m1(i: => Int) = {
lazy val li = i
...
// any number of static or dynamic references to li
...
}
In the file Parsers.scala (Scala 2.9.1) from the parser combinators library I seem to have come across a lesser known Scala feature called "lazy arguments". Here's an example:
def ~ [U](q: => Parser[U]): Parser[~[T, U]] = { lazy val p = q // lazy argument
(for(a <- this; b <- p) yield new ~(a,b)).named("~")
}
Apparently, there's something going on here with the assignment of the call-by-name argument q to the lazy val p.
So far I have not been able to work out what this does and why it's useful. Can anyone help?
Call-by-name arguments are called every time you ask for them. Lazy vals are called the first time and then the value is stored. If you ask for it again, you'll get the stored value.
Thus, a pattern like
def foo(x: => Expensive) = {
lazy val cache = x
/* do lots of stuff with cache */
}
is the ultimate put-off-work-as-long-as-possible-and-only-do-it-once pattern. If your code path never takes you to need x at all, then it will never get evaluated. If you need it multiple times, it'll only be evaluated once and stored for future use. So you do the expensive call either zero (if possible) or one (if not) times, guaranteed.
The wikipedia article for Scala even answers what the lazy keyword does:
Using the keyword lazy defers the initialization of a value until this value is used.
Additionally, what you have in this code sample with q : => Parser[U] is a call-by-name parameter. A parameter declared this way remains unevaluated, until you explicitly evaluate it somewhere in your method.
Here is an example from the scala REPL on how the call-by-name parameters work:
scala> def f(p: => Int, eval : Boolean) = if (eval) println(p)
f: (p: => Int, eval: Boolean)Unit
scala> f(3, true)
3
scala> f(3/0, false)
scala> f(3/0, true)
java.lang.ArithmeticException: / by zero
at $anonfun$1.apply$mcI$sp(<console>:9)
...
As you can see, the 3/0 does not get evaluated at all in the second call. Combining the lazy value with a call-by-name parameter like above results in the following meaning: the parameter q is not evaluated immediately when calling the method. Instead it is assigned to the lazy value p, which is also not evaluated immediately. Only lateron, when p is used this leads to the evaluation of q. But, as p is a val the parameter q will only be evaluated once and the result is stored in p for later reuse in the loop.
You can easily see in the repl, that the multiple evaluation can happen otherwise:
scala> def g(p: => Int) = println(p + p)
g: (p: => Int)Unit
scala> def calc = { println("evaluating") ; 10 }
calc: Int
scala> g(calc)
evaluating
evaluating
20