Scala 2.12: Unable to use unapply in extractor object - scala

I am following through Scala Tour provided on docs.scala-lang.org. I am stuck at the extractor objects tutorial: https://docs.scala-lang.org/tour/extractor-objects.html
Here is the code I am trying to compile:
object IdGenerator {
private val id: AtomicInteger = new AtomicInteger
def apply(name: String): String = id.incrementAndGet + "--" + name
def unapply(genID: String): Option[String] = {
val idParts = genID.split("--")
if (idParts.head.nonEmpty && idParts.tail.nonEmpty)
Some(idParts(0))
else
None
}
}
println(IdGenerator("ABC"))
println(IdGenerator("DEF"))
println(IdGenerator("XYZ"))
IdGenerator(idName) = IdGenerator("ABC")
println(idName)
println(IdGenerator.unapply(IdGenerator("ABC")))
Here is the error:
D:\MyApps\ScalaPrac\helloworld\hello\src\main\scala\example\Hello.scala:68:5: value update is not a member of object example.IdGenerator
IdGenerator(idName) = IdGenerator("ABC")
It says that value update is not a member of object. Sure, it isn't. But I am not asking it to look for update method, I want it to look for unapply instead.

IdGenerator(idName) = x looks like an assignment, but it actually is syntax sugar for IdGenerator.update(idName, x). That explains the error message you get.
You need to use the val keyword to extract idName:
val IdGenerator(idName) = IdGenerator("ABC")

Related

Error while Passing arguments to methods using scala reflection

Error while passing arguments to methods. I have an object builddeequ_rules and calling methods using Scala reflection.
def build(rules: List[Map[String, Any]]): Check = {
for (constraint <- rules) {
val name = constraint("name")
val args = constraint("args")
val hiObj = builddeequ_rules
val mtd = hiObj.getClass.getMethod(name.toString,args.getClass)
mtd.invoke(hiObj,args)
}
import com.amazon.deequ.checks.{Check, CheckLevel}
object builddeequ_rules {
var checks = Check(CheckLevel.Warning, "Data unit test")
def isComplete(args: Any) {
val arg = args.asInstanceOf[Map[String,Any]]
val columnName = arg("column").toString
checks = checks.isComplete(columnName)
}
def isUnique(args: Any) {
val arg = args.asInstanceOf[Map[String,Any]]
val columnName = arg("column").toString
checks = checks.isUnique(columnName)
}
def isPositive(args: Any) {
val arg = args.asInstanceOf[Map[String,Any]]
val columnName = arg("column").toString
checks = checks.isPositive(columnName)
}
I am getting below error. Need help!
Error: type mismatch;
found : Any
required: Object
mtd.invoke(hiObj,args)
java.lang.Object is more or less scala.AnyRef. scala.Any is (simplyfying) a superset of objects and primitives. So the compiler is warning you, that you are trying to pass something that could potentially be primitive (Any) as java.lang.Object.
On bytecode level Any will quite often be just Object, sure, but Scala's type system make the distinction between things that are "natively" Objects and things that could involve autoboxing to make them Objects, and that's the error you see.
So the solution here would be to have this object annotated as AnyRef or even better, as java.lang.Object to clearly show that you want to use it for something Java/JVM-specific.

Shapeless lenses usage with a string definition

I would like use shapeless lenses to access value of the case class field by a String definition.
I know this code works.
case class Test(id: String, calc: Long)
val instance = Test("123232", 3434L)
val lens = lens[Test] >> 'id
val valueOfFieldId = lens.get(instance)
But what I am trying to do is:
val fieldName = "id"
val lens = lens[Test] >> fieldName.witness
//I typed .witness because it was expecting a witness (if I am not wrong)
val valueOfFieldId = lens.get(instance)
But with this code, I am getting this error.
Could not find implicit value for parameter mkLens: shapeless.MkFieldLens[A$A148.this.Test,A$A148.this.str.type]
def get$$instance$$lll = lll;/* ###worksheet### generated $$end$$ */ lazy val lens = lens[Test] >> str.witness
Is it possible to get the value of case class field with a String definition?
Thanks.
You are supposed to use Symbol ('id) here rather than String ("id").
Creating Symbol from String
Symbol(fieldName)
is runtime operation and Shapeless operates in compile time.
Why can't you use symbols?

What is mean method Apply on Scala

according to this link example
and then im create code like this :
object objPersamaan{
def main(args : Array[String]){
val x = objPersamaan("Budi ")
println(x)
}
def apply(pX:String) = pX + "Belajar"
def unapply(pZ:Int) : Option[Int] = if(pZ%2==0) Some(pZ/2) else None
}
i can't still dont understand, how can objPersamaan("Budi ") would had value Budi Belajar? is that method apply like constructor with parameter? or what? can anyone, explain more detail why the process from method apply? thanks!
In Scala, you can omit the method name apply. So calling objPersamaan("Budi ") is the same as objPersamaan.apply("Budi "), which then concatenates the String Belajar to the given parameter.
When you have an object and call it without a method name, just your arguments, the copmiler expands this call with MyObject.apply(...). This comes from the fact, that you often use objects where you want to apply something to (e.g. in factories), so Scala built this feature directly into the language.
case class MyObj(foo: String, bar: String)
object MyObj {
def apply(x: Int): MyObj = MyObj(x.toBinaryString, x.toHexString)
}
// ...
MyObj(42)
// same as
MyObj.apply(42)

Runtime instantiation in scala without type parameters

So here's what I have:
type CompType = Manifest[_ <: Component]
type EntityType = HashSet[CompType]
type CompSet = HashSet[Component]
val type_map = new HashMap[String, EntityType]
val entity_map = new HashMap[EntityID, CompSet]
def createEntityType(type_name: String) = {
val ent_id = new EntityID
val ent_type: CompSet =
type_map(type_name) map (c_type => c_type.erasure.newInstance())
entity_map += (ent_id -> ent_type)
ent_id
}
But as you can see, the map function doesn't create a CompSet, it creates a HashSet[Any].
Is there any way of solving this problem?
The whole point is to save object types for instantiation at a later time within the program, but I can't get this to work, and all the examples of reflection expect some kind of type parameter to cast to via _.asInstanceOf[SomeClassType].
type_map(type_name) map (c_type => c_type.erasure.newInstance().asInstanceOf[Component])
?
BTW, Manifest is deprecated in 2.10, you should use ClassTags and TypeTags instead.

Scala Getting class type from string representation

I have a class name string representation
val cls = Class.forName("clsName")
def fromJson[T: Manifest](me: String): T = {
Extraction.extract[T](net.liftweb.json.parse(me))
}
I would like to use it as T:manifest i.e
JsonConverter.fromJson[cls.type](stringData)
this returns an error
tried also
val t = Manifest.classType(cls)
JsonConverter.fromJson[t](stringData) // compile error
what is the best way to it ? is there a way to avoid using reflection ?
You could try something like this:
val cls = Class.forName(myClassName)
val m = Manifest.classType(cls)
val myObj:Any = JsonConverter.fromJson(stringData)(m)
One nuance to this approach is that you have to explicitly type the object as an Any. This is because you don't have the class as compile time and the call to classType is not supplied its type param so the Manifest returned is Manifest[Nothing]. Not ideal, but it works.