scala variable number by name parameters [duplicate] - scala

This question already has answers here:
Scala variable argument list with call-by-name possible?
(2 answers)
Closed 6 years ago.
I am trying to implement a control flow structure which can accept a variable number of by-name parameters.
See CalculateGroup method and its use.
I was trying to follow this post, but still have some issues
As I can see from the error, I suspect I need to define a type annotation predicate in CalculateGroup function?
Here is current code:
def compare[T : Numeric](x: T)(y: T) : Boolean = implicitly[Numeric[T]].gt( x, y )
val items = compare[Double](10) _
val assertionsEnabled = true
def Calculate( predicate: => Boolean ) =
if (assertionsEnabled && !predicate)
throw new AssertionError
Calculate{
items(5)
}
def CalculateGroup( list: (predicate: => Boolean) *) =
{
list.foreach( (p : (predicate: => Boolean) ) => {
if (assertionsEnabled && !predicate)
throw new AssertionError
})
}
CalculateGroup{
items(5),
items(3),
items(8)
}
Error details:
scala ControlFlow.scala
/Users/pavel/Documents/ControlFlow/ControlFlow.scala:36: error: ')' expected but ':' found.
def CalculateGroup( list: (predicate: => Boolean) *) =
^
/Users/pavel/Documents/ControlFlow/ControlFlow.scala:68: error: ')' expected but '}' found.
}
^
two errors found

You cannot use by-name var args, you could use a lazy collection like Iterator or maybe Stream:
def compare[T : Numeric](x: T)(y: T) : Boolean = implicitly[Numeric[T]].gt( x, y )
val items = compare[Double](10) _
val assertionsEnabled = true
def Calculate(predicate: => Boolean) =
if (assertionsEnabled && !predicate)
throw new AssertionError
Calculate{
items(5)
}
def CalculateGroup(list: Iterator[Boolean]) =
{
list.foreach { (p : Boolean ) =>
if (assertionsEnabled && !p) {
throw new AssertionError
}
}
}
CalculateGroup{Iterator(
items(5),
items(3),
items(8)
)}

You have a syntax problem... you are placing a colon in front of the word predicate in the signature of the method CalculateGroup and in the foreach. Just remove them and it should compile.
just remove it and know that the word predicate is not alias for a variable, but it should be the name of a class. So it's better if you capitalize it. Contrary to the case of your methods, which shouldn't be capitalized.
Update
To have multiple by-name parameters just do this:
def CalculateGroup( list: (=> Boolean) *) =
{
list.foreach( (p : (=> Boolean) ) => {
if (assertionsEnabled && !p)
throw new AssertionError
})
}

Related

getting error while trying to use scala extractors without case classes

I'm new to scala and just learning to code . can someone tell me what am i doing wrong here
class ForExtractor(val i : Int , j:Int){
//def unapply(i:Int) = true
}
object ForExtractor{
def unapply(i:Int ):Option[(Int , Int)] = if(i>2)Some(1,2) else None
}
def extractorTest(obj : ForExtractor) = {
obj match {
case ForExtractor(4,2)=> true ;
case e => false
}
}
The error that i see on case line is
pattern type is incompatible with expected type ; found:Int ,
ForExtractor
What i can guess is that you want to test whether the val i
in your ForExtractor is bigger that 2 or not, and in this case return Some((1,2)) (notice your error here you're returning Some(1,2)).
your unapply method should take as argument a ForExtractor, so in the end the unapply method would look like this:
def unapply(forex: ForExtractor):Option[(Int , Int)] =
if(forex.i > 2)Some((1,2)) else None
then we get:
scala> extractorTest(new ForExtractor(1, 2))
res1: Boolean = false

Scala error : unbound placeholder parameter and pattern matching condition

I'm trying to combine pattern matching and condition, but this code (that's a Samza task):
override def process(incomingMessageEnvelope: IncomingMessageEnvelope, messageCollector: MessageCollector, taskCoordinator: TaskCoordinator): Unit = {
val event = (incomingMessageEnvelope getMessage).asInstanceOf[Map[String, Date]]
val symbol = (event get "symbol").asInstanceOf[String]
val eventDate = (event get "date").asInstanceOf[Date]
(store get symbol) match {
case x: java.util.Date if x.equals(eventDate) || x.after(eventDate) => _
case _ => {
this.store.put(symbol, eventDate)
}
}
}
returns this error:
Error:(30, 38) unbound placeholder parameter
case x if isGreaterOf(x, x) => _
^
Have you any idea of the error?
Thank you
Regards
Gianluca
The Exception does not match your code, but there is one line, that would throw the same error:
case x: java.util.Date if x.equals(eventDate) || x.after(eventDate) => _
because _ is a placeholder that can be used in patterns for matching and return types. It cannot not be used to indicate a Unit return value. To return a Unit value without executing code, you could just do
case x: java.util.Date if x.equals(eventDate) || x.after(eventDate) => ()
instead.

How to determine if an expression passed to a macro will always result in the same value?

Let's suppose I've defined a macro as below. It essentially types an expression of type T and returns an object of type MyType[T] (the actual types involved don't really matter).
object MyMacro {
def macroImpl[T : context.WeakTypeTag, U : context.WeakTypeTag](context : scala.reflect.macros.blackbox.Context) (expression : context.Expr[T]) : context.Expr[U] =
}
object MyObj {
def callMacro[T](expression : T) : MyType[T] = macro MyMacro.macroImpl[T, MyType[T]]
}
In my macro, I'd like to determine if the expression passed is constant or not. By that I mean, I want to know if the expression, once evaluated at runtime, could ever subsequently evaluate to a different value. If it is constant, I can apply certain optimizations that are very useful.
I know an expression is constant if it is:
a literal expression.
a 'this' expression.
a reference to a val or parameter.
a member invocation where the object expression is constant, and the member being invoked is a val or lazy val.
For example, the expressions passed in the first five calls to callMacro below should be considered a constant:
class MyClass {
val i = 0
val myLiteral = callMacro("Hi!") //constant - literal expression
val myThis = callMacro(this) //constant - this expression
val myInt = callMacro(i) //constant - reference to a val
def myMethod(p : MyOtherClass) {
val myParameter = callMacro(p) //constant - reference to a parameter
val myValMember = callMacro(p.x) //constant - invocation of val member
val myVarMember = vallMacro(p.y) //NOT constant - invocation of var member
val myVarMember = vallMacro(p.z) //NOT constant - invocation of def member
}
}
class MyOtherClass(val x : Int, var y : Int) {
def z = x + y
}
I've already implemented code for the first two cases (which is rather trivial).
def isConstant[T](context : scala.reflect.macros.blackbox.Context) (expression : context.Expr[T]) = {
import context.universe._
expression.tree match {
case This(_) =>
true
case Literal(_) =>
true
/*...put additional cases here...*/
case _ =>
false
}
}
However, I'm not sure whether something like this already exists, or if its even possible to detect whether the member being called on an object is a val or not.
Is it possible to implement the fourth criteria? Or, does anything like this already exist in the API?
I figured out a solution. It basically boiled down to me not knowing about Symbols in scale's reflection system.
I ended up adding a fifth criteria to handle the case in which an implicit parameter or object is referenced.
implicit class extendSymbol(symbol : scala.reflect.macros.blackbox.Context#Symbol) {
def isStable =
(symbol.isTerm && symbol.asTerm.isStable) || (symbol.isMethod && symbol.asMethod.isStable)
}
def isConstant[T](context : scala.reflect.macros.blackbox.Context) (tree : context.Tree) : Boolean = {
import context.universe._
tree match {
case This(_) =>
true
case Literal(_) =>
true
case ident # Ident(_) =>
ident.symbol.isStable
case select # Select(objExpr, term) =>
isConstant(context) (objExpr) && select.symbol.isStable
//for implicit values
case Apply(TypeApply(Select(Select(This(TypeName("scala")), TermName("Predef")), TermName("implicitly")), _), _) =>
true
case _ =>
false
}
}

delay implementation in scala

I have implemented the following cons_stream function in scala that does not work and I am not sure why.
def cons_stream[T, U](x : T, y : U) =
{
def delay = () => y
/// Delay takes no parameters but returns y
(f : String ) =>
{
if ( f == "x") x
else if( f == "y") delay
else throw new Error("Invalid string use x or y")
}
}
The corresponding car and cdr functions are:
def stream_car[T](f : String => T) : T = f("x")
def stream_cdr[T](f : String => Any) : T = force(f("y").asInstanceOf[() => T])
Now I have the definition of a stream integers starting with 1
def integers_starting_from_n[T, U](n : Int) : String => Any =
{
cons_stream(n, integers_starting_from_n(n+1))
}
Unfortunately when I try to access the stream using either stream_car or stream_cdr I get a stack overflow:
def integers = integers_starting_from_n(1)
stream_car(integers)
I have no idea why. Any help is appreciated.
I assume that the stack is full of integers_starting_from_n. Correct? That function is recursive and is called before cons_stream can be executed, because it takes value of integers_starting_from_n(n+1) as a paremeter.
In order to define a stream, you can use a call-by-name parameter by prepending => to the type. For your example, use call-by-name with y.
def cons_stream[T, U](x:T, y: => U)

Scala: if statement returning Any instead of Unit in a closure [duplicate]

This question already has answers here:
What is return type of `if` statement
(3 answers)
Closed 8 years ago.
I have the following code in a method:
aSides.foreach(as => as.side.terr match
{
case r: TerrSRiver => paintSeq :+= ((g: Graphics2D) =>
{
g.setPaintColour(ColourInt.blue)
g.fill(Polygon(as.paintStd(0.2)))
}
case _: TerrSCoast => paintSeq :+= ((g: Graphics2D) =>
{
g.setPaintColour(TerrSea.colour)
g.fill(Polygon(as.paintStd(0.2)))
}) //one case excluded for simplicity
paintSeq is declared outside the method
var paintSeq: Seq[Graphics2D => Unit] = Nil
This compiles and runs as expected. However if I add an if Statement to the first case:
case r: TerrSRiver => paintSeq :+= ((g: Graphics2D) =>
{
g.setPaintColour(ColourInt.blue)
g.fill(Polygon(as.paintStd(0.2)))
if (zoom > 50) g.setPaintColour(ColourInt.white)
}
I get an error:
type mismatch; found : Seq[swing.Graphics2D => Any] required: Seq[swing.Graphics2D => Unit] AreaESw.scala /prStratSw/src/pGrid/pUISw line 49 Scala Problem
The error refers to the paintSeq :+= method. Why is the if statement returning Any rather than Unit? I can get rid of the error by adding a line after the if statement:
val dummy = 0
However if I add in return Unit at the end:
case r: TerrSRiver => paintSeq :+= ((g: Graphics2D) =>
{
g.setPaintColour(ColourInt.blue)
g.fill(Polygon(as.paintStd(0.2)))
if (zoom > 50) g.setPaintColour(ColourInt.white)
return Unit
}
It Compiles with the following warning:
enclosing method setVisObjs has result type Unit: return value discarded
But when it runs I get the following error
Exception in thread "AWT-EventQueue-0" scala.runtime.NonLocalReturnControl$mcV$sp
Using "return ()" still gives the run time exception.
This is Scala Swing code, but I'm using Scala 2.10.3 in the JavaFx Eclipse download: 4.2.2 on Linux.
Type of if
The result type of if (cond) expr is the common base type of expr and Unit, just like if (cond) { expr } else { () }
See What is return type of if statement? for details.
How to get Unit
To get an instance of type Unit you should use () literal:
if (zoom > 50) g.setPaintColour(ColourInt.white)
()
Unit value is the companion object of type Unit. It's not an instance of type Unit. Type of object Unit is Unit.type.
Do not use return in lambda
The result of lambda is the result of the last statement in lambda body, so you could just add result value (in this case literal ()) as the last line.
return in lambda will return from the surrounding method rather than from the lambda itself using exception (NonLocalReturnControl).
It's useful for java-style methods like this:
def firstNegative(seq: Seq[Int]): Option[Int] = {
for {
i <- seq
} if (i < 0) return Some(i)
return None
}
if (i < 0) return Some(i) here is lambda body. Equivalent code for this method:
def firstNegative(seq: Seq[Int]): Option[Int] = {
seq.foreach{ i =>
if (i < 0) return Some(i)
}
return None
}
You should have a else clause :
if (zoom > 50) g.setPaintColour(ColourInt.white) else ...
Benoit