How do I invoke the '!=' method on an object? - scala

I just started playing with scala and have been using the "Scala By Example" by Michel Schinz ( http://www.scala-lang.org/node/198 ) as a starting point. In the segment on traits, I've attempted to use reflection/method invocation to test traits and wanted to test all the comparison operator. I hit the issue with name mangling and found the solution in NameTransformer for the operators. However, the != operator, appears to me that it does not translate into an equivalent function like <, <=, >, >=, equals. I wonder if there is a way to invoke != much like the other operators that I have not found out?
From the pdf:
trait ord {
def < (that:Any):Boolean
def <= (that:Any):Boolean = (this < that) || (this == that)
def > (that:Any):Boolean = !(this <= that)
def >= (that:Any):Boolean = !(this < that)
}
class Date(y:Int, m:Int, d:Int) extends ord{
def year = y
def month = m
def day = d
override def toString():String = year + "-" + month + "-" + day
override def equals(that:Any): Boolean =
that.isInstanceOf[Date] && {
val o = that.asInstanceOf[Date]
o.day == this.day && o.month == this.month && o.year == this.year
}
override def <(that:Any):Boolean = {
if (!that.isInstanceOf[Date])
error("Cannot compare " + that + " and date")
val o = that.asInstanceOf[Date]
(year < o.year) ||
(year == o.year && (month < o.month ||
(month == o.month && day < o.day )))
}
}
My code:
def Classes_Traits(){
val (d1, d2, d3) = (new Date(2001, 10, 1), new Date(2001, 10, 1), new Date(2000, 1, 10))
println("d1 : " + d1)
println("d2 : " + d2)
println("d3 : " + d3)
Array((d1,d2), (d2,d3), (d3,d1)).foreach {
(comp:(Date, Date)) =>
println("comparing " + comp._1 + " and " + comp._2)
val d = comp._1.getClass()
Map(
"equals " -> "equals",
"not equals " -> "!=",
"less than " -> "<",
"less than or equal" -> "<=",
"more than " -> ">",
"more than or equal" -> ">=").foreach {
(a) =>
println(a._1 + " : " +
d.getMethod(scala.reflect.NameTransformer.encode(a._2),
classOf[Object]).invoke(comp._1, comp._2))
}
/*println("equals : " + m.invoke(comp._1, comp._2) )
// Same as above
println(comp._1 + " == " + comp._2 + " is " + (comp._1 == comp._2))
println(comp._1 + " != " + comp._2 + " is " + (comp._1 != comp._2))
println(comp._1 + " > " + comp._2 + " is " + (comp._1 > comp._2))
println(comp._1 + " >= " + comp._2 + " is " + (comp._1 >= comp._2))
println(comp._1 + " < " + comp._2 + " is " + (comp._1 < comp._2))
println(comp._1 + " <= " + comp._2 + " is " + (comp._1 <= comp._2))
*/
}
}
exception:
comparing 2001-10-1 and 2001-10-1
more than or equal : true
more than : false
Exception in thread "main" java.lang.NoSuchMethodException: proj2.Main$Date.$bang$eq(java.lang.Object)
at java.lang.Class.getMethod(Class.java:1605)
at proj2.Main$$anonfun$Classes_Traits$1$$anonfun$apply$1.apply(Main.scala:180)
at proj2.Main$$anonfun$Classes_Traits$1$$anonfun$apply$1.apply(Main.scala:178)
at scala.collection.immutable.HashMap$HashMap1.foreach(HashMap.scala:125)
at scala.collection.immutable.HashMap$HashTrieMap.foreach(HashMap.scala:344)
at proj2.Main$$anonfun$Classes_Traits$1.apply(Main.scala:177)
at proj2.Main$$anonfun$Classes_Traits$1.apply(Main.scala:168)
at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:34)
at scala.collection.mutable.ArrayOps.foreach(ArrayOps.scala:35)
at proj2.Main$.Classes_Traits(Main.scala:167)
at proj2.Main$.main(Main.scala:26)
at proj2.Main.main(Main.scala)

Try calling equals and negating the result. == and != benefit from a little compiler magic in Scala (e.g., you can call null.==(4) without getting a NullPointerException).

Related

Scala – Reduce, fold or scan (Left/Right) error cannot resolve symbol x

while performing a hands on code practice i am facing cannot resolve symbol x from intellj
error code line
println(lst.reduceLeft((x,y) => {println(x + " , "+ y) x +y}))
println(lst.reduceRight((x,y) => {println(x + " , "+ y) x -y}))
i have tried to debugg from the suggestions from intellj but not working
Intellj
Build #IC-221.5591.52, built on May 10, 2022
scala version
scala-sdk-2.11.12
reference
http://www.codebind.com/scala/scala-reduce-fold-scan-leftright/?unapproved=192475&moderation-hash=8cdabb0f7834cbe19792b863eb952538#comment-192475
//In Scala Reduce, fold or scan are most commonly used with collections in the form of reduceLeft, reduceRight, foldLeft, foldRight, scanLeft or scanRight.
// In general, all functions apply a binary operator to each element of a collection.
// The result of each step is passed on to the next step.
package pack {
}
object obj2 {
println
println("=====started=======")
println
//val is a constant (which is an un changeable variable),A variable holds a value / address to a value in memory
val lst = List(1, 2, 3, 5, 7, 10, 13)
val lst2 = List("A", "B", "C")
def main(args: Array[String]) {
println(lst.reduceLeft(_ + _))
println(lst2.reduceLeft(_ + _))
println(lst.reduceLeft((x,y) => {println(x + " , "+ y) x +y}))
println(lst.reduceLeft(_ - _))
println(lst.reduceRight(_ - _))
println(lst.reduceRight((x,y) => {println(x + " , "+ y) x -y}))
println(lst.foldLeft(100)(_ + _))
println(lst2.foldLeft("z")(_ + _))
println(lst.scanLeft(100)(_ + _))
println(lst2.scanLeft("z")(_ + _))
}
}
println(lst.reduceLeft((x,y) => { println(x + " , " + y) x + y }))
The code inside the { } is not a valid expression. It looks like you are expecting Scala to work out that there are two expressions here, but it can't. You need to put in an explicit ; to fix it:
println(lst.reduceLeft((x,y) => { println(x + " , " + y); x + y }))
println(lst.reduceLeft((x,y) => {println(x + " , "+ y) x +y})) is not valid. If you want several instructions in a anonymous function you need either to separate them with ; or make it multiline:
println(lst.reduceLeft((x, y) => { println(x + " , " + y); x + y }))
or
println(lst.reduceLeft((x, y) => {
println(x + " , " + y)
x + y
}))
Also better use string interpolation instead of concatenation:
println(lst.reduceLeft((x, y) => {
println(s"$x , $y")
x + y
}))

how to implement variable length argument function in scala

I have to concatenate k different lengths of strings into one string res and save res string into ArrayBuffer[String]().
But the k is variable.
For example,
val result = new ArrayBuffer[String]()
result.+=("1\t" + A.toString() + "\t" + ls.pid + "\t" + ls.did + "\t" + ls.sid + "\t" + ls.request_time.substring(0,10))
result.+=("2\t" + B.toString() + "\t" + ls.pid + "\t" + ls.did + "\t" + ls.sid + "\t")
result.+=("2\t" + B.toString() + "\t" + ls.pid + "\t" + ls.did + "\t")
result.+=("2\t" + B.toString() + "\t")
How to use a function with a variable-length argument to implement it?
Thanks in advance.
You can use the following syntax:
def f(args: String*) = {
args.map{s =>
//todo: process single item
s
}
}

Running different objects in IDEA - Scala

I have 3 different objects that I've written in IDEA, labelled PartA, PartB, and PartC. However, when I attempt to run any of these objects, the only one that gives me the option to run is PartB. When I right click on the code for PartA and PartC, I have no option to run them. Only PartB has the option to run. What's going on here, and how can I fix it so I can run the different objects I have written?
Edit: Sorry, first time posting a question here. Here's the code I have written.
object PartB extends App {
def easter(Y:Int): Int = {
val N = Y - 1900
val A = N - (N/19) * 19
val B = (7 * A + 1) / 19
val C = 11 * A + 4 - B
val M = C - (C / 29) * 29
val Q = N / 4
val S = N + Q + 31 - M
val W = S - (S / 7) * 7
val DATE = 25 - M - W
return DATE
}
println("Enter a year: ")
val year = scala.io.StdIn.readInt()
val date = easter(year)
var easter_day : String = ""
if (date == 0) {
easter_day = "March, 31"
} else if (date < 0) {
easter_day = "March, " + (31 + year)
} else {
easter_day = "April, " + date
}
println("In " + year + ", Easter is on " + easter_day + ".")
}
////////////////////////////////////////////////////////////////////////////////
object PartC {
def ack(m:Int, n:Int) : Int = {
if (m == 0) {
return n + 1
} else if (n == 0) {
return ack(m - 1, 1)
} else {
return ack(m - 1, ack(m, n - 1))
}
}
println("Enter a value for m: ")
val m = scala.io.StdIn.readInt()
println("Enter a value for n: ")
val n = scala.io.StdIn.readInt()
println(ack(m, n))
}
PartB extends App, but PartC doesn't. Presumably PartA doesn't either.
The App trait can be used to quickly turn objects into executable programs... the whole class body becomes the “main method”.
So PartB defines a main method.

Making a nested if statement more functional in scala

Just wondering if anyone would know how to make the following if statement more functional:
val value1 = 8
val value2 = 10
if(val1 > val2){
println("\n" + stock1 + " has the highest current value")
}else if(val1 < val2){
println("\n" + stock2 + " has the highest current value")
}else if(val1 == val2)){
println("\nThe current value for " + stock1 + " is equal the current value for " + stock2)
}
I would be very grateful if someone could make a suggestion.
Thanks
Using cats-kernel you could use Order[Int].comparison :
import cats.kernel.Order
import cats.kernel.instances.int._
import cats.kernel.Comparison._
val message =
Order[Int].comparison(val1, val2) match {
case GreaterThan => s"$stock1 has the highest current value"
case LessThan => s"$stock2 has the highest current value"
case EqualTo =>
s"The current value for $stock1 is equal the current value for $stock2"
}
println(s"\n$message")
match, if you like it
val1 match{
case v if v > val2 => println("\n" + stock1 + " has the highest current value")
case v if v < val2 => println("\n" + stock2 + " has the highest current value")
case _ => println("\nThe current value for " + stock1 + " is equal the current value for " + stock2)
}
I think the key thing about being functional here is to separate calculation from effects.
Your snippet is both calculating the message to print and doing IO. There's nothing wrong with using if statements -- in this case I'd say it's the clearest way to write it.
val value1 = 8
val value2 = 10
def valueMessage =
if (val1 > val2) stock1 + " has the highest current value"
else if (val1 < val2) stock2 + " has the highest current value"
else "The current value for " + stock1 + " is equal the current value for " + stock2
def printValueMessage() = println("\n" + valueMessage)
printValueMessage() // unsafe
Or this:
math.signum(value1 - value2) match {
case -1 => println("v1 <= v2")
case 1 => println("v1 >= v2")
case _ => println("v1 == v2")
}
Like this? What do you think is not functional enough about your solution?
println(
if (val1 > val2)
s"\n$stock1 has the highest current value"
else if (val1 < val2)
s"\n$stock2 has the highest current value"
else
s"\nThe current value for $stock1 is equal the current value for $stock2"
)

Caching function results using a hashmap scala

Here is some code I wrote to solve project Euler #14 in scala
The output is shown below as well. My issue is, I expect better performance from the cached version, but the opposite is true. I think I did something wrong, since I don't think HashMap's overhead is enough to make this this slow.
Any suggestions?
object Problem14 {
def main(args: Array[String]) {
val collatzCacheMap = collection.mutable.HashMap[Long,Long]()
def collatzLengthWithCache(num: Long): Long = {
def collatzR(currNum: Long, solution: Long): Long = {
val cacheVal = collatzCacheMap.get(currNum)
if(cacheVal != None) {
val answer = solution + cacheVal.get
collatzCacheMap.put(num, answer);
answer;
}
else if(currNum == 1) { collatzCacheMap.put(num, solution + 1); solution + 1; }
else if(currNum % 2 == 0) collatzR(currNum/2, solution + 1)
else collatzR(3*currNum + 1, solution + 1)
}
collatzR(num, 0)
}
def collatzLength(num: Long): Long = {
def collatzR(currNum: Long, solution: Long): Long = {
if(currNum == 1) solution + 1
else if(currNum % 2 == 0) collatzR(currNum/2, solution + 1)
else collatzR(currNum*3 + 1, solution + 1)
}
collatzR(num, 0)
}
var startTime = System.currentTimeMillis()
//val answer = (1L to 1000000).reduceLeft((x,y) => if(collatzLengthWithCache(x) > collatzLengthWithCache(y)) x else y)
val answer = (1L to 1000000).zip((1L to 1000000).map(collatzLengthWithCache)).reduceLeft((x,y) => if(x._2 > y._2) x else y)
println(answer)
println("Cached time: " + (System.currentTimeMillis() - startTime))
collatzCacheMap.clear()
startTime = System.currentTimeMillis()
//val answer2 = (1L to 1000000).par.reduceLeft((x,y) => if(collatzLengthWithCache(x) > collatzLengthWithCache(y)) x else y)
val answer2 = (1L to 1000000).par.zip((1L to 1000000).par.map(collatzLengthWithCache)).reduceLeft((x,y) => if(x._2 > y._2) x else y)
println(answer2)
println("Cached time parallel: " + (System.currentTimeMillis() - startTime))
startTime = System.currentTimeMillis()
//val answer3 = (1L to 1000000).reduceLeft((x,y) => if(collatzLength(x) > collatzLength(y)) x else y)
val answer3 = (1L to 1000000).zip((1L to 1000000).map(collatzLength)).reduceLeft((x,y) => if(x._2 > y._2) x else y)
println(answer3)
println("No Cached time: " + (System.currentTimeMillis() - startTime))
startTime = System.currentTimeMillis()
//val answer4 = (1L to 1000000).par.reduceLeft((x,y) => if(collatzLength(x) > collatzLength(y)) x else y)
val answer4 = (1L to 1000000).par.zip((1L to 1000000).par.map(collatzLength)).reduceLeft((x,y) => if(x._2 > y._2) x else y)
println(answer4)
println("No Cached time parallel: " + (System.currentTimeMillis() - startTime))
}
}
Output:
(837799,525)
Cached time: 1070
(837799,525)
Cached time parallel: 954
(837799,525)
No Cached time: 450
(837799,525)
No Cached time parallel: 241