Scala: recursive value listHuman needs type - scala

Why is this function giving me the following error:
recursive value listHuman needs type
def setHumanResources(physicalResources: List[Physical], totalHumanResources: List[Human]): List[Human] = {
val listHuman = physicalResources.map{pr => totalHumanResources.find(_.handles.contains(pr.post)).filterNot(a=>listHuman.contains(a))}
return listHuman
}
I tried to do this, but it gives me another error:
val listHuman: List[Human] = physicalResources.map{pr => totalHumanResources.find(_.handles.contains(pr.post)).get}.filterNot(human=>listHuman.contains(human))
forward reference extends over definition of value listHuman

This error means that constant value or variable is used before its declaration. For example
val y = x + 2
val x = 5
What wrong with your code is you try to define constant value with itself. It's impossible by definition of constant. To build recursion use def.

It seems like you want to do a foldLeft, does this work?
def setHumanResources(physicalResources: List[Physical], totalHumanResources: List[Human]): List[Human] = {
physicalResources.foldLeft(Set.empty[Human]) { (l, pr) =>
val applicableHuman = totalHumanResources.find(_.handles.contains(pr.post))
l ++ applicableHuman
}.toList
}

The premises here is to have setHumanResourcesreturn a unique/distint list of Human objects. The code tries this by doing filterNot(a=>listHuman.contains(a)) in definition of listHuman and thus recursively referring to listHuman while defining listHuman in semantically illegal way. This de-duping can be achieved properly by the following ways.
convert the List to Set and convert it back to List to remove duplicates like listHuman.toSet.ToList. for this method to work the Human object have property identity defined by overriding equals method. so the code will now look like
def setHumanResources(physicalResources: List[Physical], totalHumanResources: List[Human]): List[Human] = {
val listHuman = physicalResources.map{pr => totalHumanResources.find(_.handles.contains(pr.post))
listHuman.toSet.toList
}
A Demo for a sample class of Human is shown below.
scala> class Human(val firstName: String, val lastName: String) {
| override def toString = this.firstName
| override def equals(that: Any): Boolean = that match {
| case that: Human if that.firstName == this.firstName => true
| case _ => false
| }
| }
defined class Human
scala> List(new Human("Peter", "Parker"), new Human("Peter", "Quill")).toSet.toList
res14: List[Human] = List(Peter)
If the class Human cannot have object equality defined in it by overriding equals method then follow this approach. considering each Human can be uniquely identified by say two properties property1 and property2. the listHuman can be deduped by the following expression. For our previously defined Human class if we want to de-dupe on both firstName and lastName properties, the code would be like below.
listHuman.groupBy(x => (x.firstName, x.lastName)).map(_._2.head)
so the new method definition becomes
def setHumanResources(physicalResources: List[Physical], totalHumanResources: List[Human]): List[Human] = {
val listHuman = physicalResources.map{pr =>
totalHumanResources.find(_.handles.contains(pr.post))
listHuman.groupBy(x => (x.property1, x.property2) ).map(_._2.head)
}

Related

Syntactic sugar explanation of Scala'a unapply method

I am getting an error in the extractor step (unapply method call).
The error message is: Wrong number of arguments for the extractors. found 2; expected 0
Can someone please help what is causing the error (where my misunderstanding is).
class ABC(val name:String, val age:Int) //class is defined.
object ABC{
def apply(age:Int, name:String) = new ABC(name, age)
def unapply(x:ABC) = (x.name, x.age)
}
val ins = ABC(25, "Joe") //here apply method is in action.
val ABC(x,y) = ins //unapply is indirectly called. As per my understanding , 25 and Joe suppose to be captured in x and y respectively. But this steps gives error.
The error I get is
an unapply result must have a member def isEmpty: Boolean
The easiest way to fix this is to make unapply return an Option:
def unapply(x: ABC) = Option((x.name, x.age))
The unapply method in an extractor which binds values must return an Option. This is because there's no intrinsic guarantee that an extractor will always succeed. For instance consider this massively oversimplified example of an extractor for an email address:
object Email {
def unapply(s: String): Option[(String, String)] =
s.indexOf('#') match {
case idx if idx >= 0 =>
val (user, maybeSite) = s.splitAt(idx)
if (maybeSite.length < 2 || maybeSite.lastIndexOf('#') > 0) None
else Some(user -> maybeSite.tail)
case _ => None
}
}
At the application site:
val Email(u, s) = "user3103957#stackoverflow.example.xyz"
Turns into code that's basically (from the description in Programming In Scala (Odersky, Spoon, Venners (3rd ed))):
val _tmpTuple2 =
"user3103957#stackoverflow.example.xyz" match {
case str: String =>
Email.unapply(str).getOrElse(throw ???)
case _ => throw ???
}
val u = _tmpTuple2._1
val s = _tmpTuple2._2
Technically, since the compiler already knows that the value is a String, the type check is elided, but I've included the type check for generality. The desugaring of extractors in a pattern match also need not throw except for the last extractor attempt.

Creating a modified `filter` function

Consider the filter function.
I am interested in the following modifications of the filter function, if possible:
We know for a collection we can do:
case class People(val age: Int)
val a: List[People] = ...
a.filter(i => i.age ==10 )
Or more simply:
a.filter(_.age==10 )
Any simple way I can define another modified filter that works just like the following (no underline)
a.myfilter1( age==10 )
the filter function does not work when its argument is no Boolean. Suppose I want to create a modified filter that when a non-Boolean is given, it translates to equality automatically. Here is an example:
val anotherPerson: People = ...
a.myFilter2(anotherPerson)
I want the above myFilter2 to get translated as following:
a.filter(_.equals(anotherPerson))
Using implicit def:
case class MyFilterable[T](seq: Seq[T]) {
def suchAFilter(v: Any): Seq[T] = {
seq.filter(v.equals)
}
}
implicit def strongFilter[T](seq: Seq[T]): MyFilterable[T] = {
MyFilterable(seq)
}
println(List(1,2,3).suchAFilter(2))

Restore a dependent type at runtime

I'm trying to restore a dependent type in Scala at runtime. I basically want to archive a type-save map, where every key has an associated type, but all type informations of the stored key value pairs aren't visible to the user of Map (unlike the awesome Shapeless Map).
class Key[V] {
type Value = V
def ->(value: V) = Pair(this, value)
}
trait Pair {
val key: Key[_]
val value: key.Value
}
trait Map {
val pairs: Seq[Pair]
def get[V](key: Key[V]): Option[V] =
pairs.find(pair => pair.key eq key).map(_.value).asInstanceOf[Option[V]]
// ^ ^
// the runtime prove that pair.key.Value equals V |
// |
// 'Convince' the compile that I know what I do
}
Usage:
val text = new Key[String]
val count = new Key[Int]
val map: Map = new Map { val pairs = text -> "Hello World!" :: Nil }
map.get(text) // Some(Hello World!), Type: Option[String]
map.get(count) // None, Type: Option[Int]
Is it possible to write a get method without using a cast explicit with asInstanceOf or implicit with a match with an unchecked branch?
I tried to write an unapply for pairs, but run into the same problem.
Note that I leave out the definition of the Pair-companion object. Here a running example in a Gist.
Remember the JVM erases generics at runtime. So anything that relies on generics, including dependent typing, can only happen at compile time - i.e. in the caller, because any given method will only compile to one runtime code path. The only alternative is checking the runtime class (either directly or by pattern matching) as you say. (Shapeless has a type-safe, typeclass-driven helper if you go down that route)
There might be a clever way to express your requirements without the type issues, but in general the type information has to be either visible to the caller or checked at runtime.
Many way to solve your type issue. First of all define source of issue:
trait Map {
val pairs: Seq[Pair] // (1)
def get[V](key: Key[V]): Option[V] = // (2)
pairs.find(_.key eq key).map{_.value } // (3)
}
pairs type is Seq of Pair (with some embedded undefined type key: Key[_])
key type is Key[V] and expected result type is Option[V]
try to return type from (1) Key[_] instead of expected Key[V] and extracted V
Solution: you should guaranty that pairs embedded type of key is the same what you return
One of possible solutions:
trait Key[V] {
def ->(value: V) = Pair(this, value)
}
trait Pair {
type Value
val key: Key[Value]
val value: Value
}
trait Map1[V] {
val pairs: Seq[Pair {type Value = V } ]
def get(key: Key[V]): Option[V] =
pairs.find(_.key eq key).map{ _.value }
}
trait Map2 {
type Value
val pairs: Seq[Pair {type Value = Map2.this.Value} ]
def get[V >: Map2.this.Value](key: Key[V]): Option[V] =
pairs.find(_.key eq key).map{ _.value }
}

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
}
}

Scala Macros: How to create setter function for case classes

I would like to use macro to generate a setter for case classes. e.g:
case class Person(name: String, age: Int)
Macro.mkSetter[Person, String]("name") : Person => String => Person
I tried the following implementation but I keep getting the following
error: scala: Error: Unknown source file: embeddedFile--QuasiquoteCompat.scala#6....
(I am using scala 2.10.3 with macro-paradise 2.0.0-SNAPSHOT)
object Macro {
def mkSetter[A, B](fieldName: String): (A,B) => A = macro mkSetter_impl[A,B]
def mkSetter_impl[A: c.WeakTypeTag, B: c.WeakTypeTag](c : Context)(fieldName: c.Expr[String]): c.Expr[(A,B) => A] = {
import c.universe._
val (aTpe, bTpe) = (weakTypeOf[A], weakTypeOf[B])
val constructor = aTpe.declarations.collectFirst {
case m: MethodSymbol if m.isPrimaryConstructor => m
}.getOrElse(c.abort(c.enclosingPosition, s"Cannot find constructor in ${weakTypeOf[A]}"))
val field = constructor.paramss.head.find(
_.name.decoded == fieldName.toString()
).getOrElse(c.abort(c.enclosingPosition, s"Cannot find constructor field named in $fieldName"))
c.Expr[(A,B) => A](q"{(a: $aTpe, b: $bTpe) => a.copy(${field.name} = b)}")
}
}
I do realise that _.name.decoded == fieldName.toString() is not correct way to check method name (even if _.name.decoded == "name" seems to be ok)
Bonus point: generalise macro with varags parameters for parameters with same type, e.g.
def mkSetter[A, B](fieldNames: String*): A => B => B ... => A = macro mkSetter_impl[A,B]
Thank you!
Seems to be caused by https://github.com/scalamacros/paradise/issues/11. This week I planned to fix that issue, so it should be fine soon. You could subscribe to updates at scalamacros.org (http://scalamacros.org/news/rss.xml) or follow me on Twitter to get notified when the fix is deployed.