How to return Double with map - scala

I try to making token lexical analyzer
and I want return Double type using map in scala
var m = Map[String,Double]()
def parseItem(tok: Tokenizer): Double = {
val startPos = tok.tokenPos
val t = tok.token
tok.next()
//(other codes)
else if (t.isIdentifier) {
var t1 = tok.token
if(t1.text == "=") {
tok.next()
var t2 = tok.token
if(t2.isNumber) {
m += (t.text -> t2.number)
println("Idenrifier sorted :" + t.text)
0
}else if(t2.isIdentifier && m.get(t2.text) == None){
println("Error!!! RHS is Wrong identifier!!!")
throw new SyntaxError(startPos, "expected number, identifier, or '('")
}else{
m += (t.text -> m.get(t2.text))
println("Idenrifier sorted :" + t.text)
0
}
}else{
m.get(t.text)
}
the error code is :Option[Double]
I think return type is Double But I can't understanding this error

m.get(t.text) is of type Option[Double]
You can use the apply method of the Map but keep in mind that the apply method returns the value associated with a given key directly, without wrapping it in an Option. If the key is not defined in the map, an exception is raised.
You can use m(t.text) or m.apply(t.text)
Or you can use m getOrElse (t.text, defaultValue) ,which returns the value associated with key t.text in the m map , or the defaultValue if not found.

Related

How to remove' identifier expected but integer literal found error' in Scala?

I am trying to build a function to identify if a an expresson has balanced parenthesis or not.
My problem is that I am getting this error on my functions for the variables opening_index and closing_index :
Error:(3, 30) identifier expected but integer literal found.
var opening_index: Int =-1
Error:(6, 30) identifier expected but integer literal found.
var closing_index: Int =-1
Error:(34, 30) identifier expected but integer literal found.
var opening_index: Int =-1
Error:(37, 30) identifier expected but integer literal found.
var closing_index: Int =-1
I have been googling my error for the last hour without finding any valuable cluses.
Here is my code:
object Test
{
def balance(chars: List[Char]): Boolean=
{
var opening_index: Int =-1
var closing_index: Int =-1
opening_index=chars.indexOf('(')
closing_index=chars.indexOf(')')
if (opening_index ==-1 && closing_index==-1)
{
true
}
if (closing_index>-1 && opening_index>-1)
{
if (closing_index<=opening_index) return(false)
else
{
balance(chars.drop(closing_index).drop(opening_index))
}
}
else
return (false)
}
}
The tokenizer doesn't know, where a token ends or starts. Use some delimiters, which makes the code more readable for humans too:
object Test {
def balance(chars: List[Char]): Boolean =
{
var opening_index: Int = -1
var closing_index: Int = -1
opening_index=chars.indexOf ('(')
closing_index=chars.indexOf (')')
if (opening_index == -1 && closing_index == -1)
{
true
}
if (closing_index > -1 && opening_index > -1)
{
if (closing_index <= opening_index)
return false
else
balance (chars.drop (closing_index).drop (opening_index))
}
else
return false
}
}
Since you only initialize your vars to reinitialize them directly again, you can easily earn some functional points by declaring them as vals:
def balance (chars: List[Char]): Boolean =
{
val opening_index: Int = chars.indexOf ('(')
val closing_index: Int = chars.indexOf (')')
For recursive calls, you don't have to bother - those generate a new pair of values which don't interfere with those of the calling context.
You might also note, that return statements dont need a function-call-look with parens return (false) but can be written as return false, and even the return keyword is most of the time superflous.
object Test {
def balance (chars: List[Char]): Boolean =
{
val opening_index: Int = chars.indexOf ('(')
val closing_index: Int = chars.indexOf (')')
if (opening_index == -1 && closing_index == -1)
{
true // but note the else in the 2nd next line
}
else if (closing_index > -1 && opening_index > -1)
{
if (closing_index <= opening_index)
false
else
balance (chars.drop (closing_index).drop (opening_index))
}
else
false
}
}
When Scala sees =-1, it gets tokenized (split) not as = -1 (as in other languages you may be familiar with), but as =- 1, since =- is a perfectly fine identifier in Scala.
Since = hasn't been seen, the entire Int =- 1 must be a type. By infix notation for types, it's equivalent to =-[Int, 1]. Except 1 here must be a type. To be a type it should start with an identifier, and that's what the error message is saying. If you fixed that, it would complain about unknown =- type next.
This can be simplified by just counting how many of each there are and seeing if the numbers match up:
def balance (chars: List[Char]): Boolean = {
val opening = chars.count(_ == '(')
val closing = chars.count(_ == ')')
opening == closing
}
balance(List('(', ')', '(', ')', '(')) //false
balance(List('(', ')', '(', ')')) //true
If you want the balanced parentheses to be in order, you can do it recursively:
def balance(chars: List[Char], open: Int = 0): Boolean = {
if (chars.isEmpty)
open == 0
else if (chars.head == '(')
balance(chars.tail, open + 1)
else if (chars.head == ')' && open > 0)
balance(chars.tail, open - 1)
else
balance(chars.tail, open)
}
val x = "(apple + pear + (banana)))".toList
balance(x) //true
val y = "(()(".toList
balance(y) //false
This goes through every element of the list and adds/subtracts to/from a variable called open until the list is empty, at which point if open is 0 it returns true otherwise it returns false.

Why Scala return in for-loop give Unit value type?

I have written a for loop to traverse Map, I want this function return key immediately when found some value (both of key and value is Int type)
var hs:Map[Int,Int] = Map(1 -> 1, 2 -> 2)
for ((k,v) <- hs) {
if (v == 1)
return k
}
but, scala give me the error message:
error: type mismatch;
found : Unit
required: Int
for ((k,v) <- hst)
^
one error found
then I change to
var result = 0
for ((k, v) <- hst){
if (v == 1)
result = k
}
result
then, it works well. Why the first version has type issues?
The compile error is explained by #D.Peter, It's lack of a return for this clause.
In Scala, you can use find to do that, like:
hs.find(_._2 == 1).map(_._1).getOrElse(0) // get or return default value.
You forgot to return something if you function never enters in the if statement
def a() : Int = {
var hs:Map[Int,Int] = Map(1 -> 1, 2 -> 2)
for ((k,v) <- hs) {
if (v == 1){
return k
}
}
return -1
}
The accepted answer is not very accurate because it's not about entering if statement, even if you remove if condition it will still not compile.
The problem is the for loop itself. Without yield it simply acts as a construct for side effects. Meaning it returns Unit. Pretty much like foreach semantics.
Read more here.

Scala Cannot Resolve Symbol

Currently my system has the ability for a user to enter 2 numbers, the last number on the tail is found and returned, how can I get the data and data2 to only show there numbers, not the SK1/SK3 before. Currently I am getting the error ;
Error:(177, 28) value >= is not a member of (String, Int)
val highest = if (data >= data2){
//Compare 2 values
def mnuCompareTwoStocks(f: (String) => (String, Int)) = {
print("Stock > ")
val data = f(readLine)
print("Stock 2 > ")
val data2 = f(readLine)
val highest = if (data >= data2){
println(data)
}
else
{
println(data2)
}
println(s"${data._1}: ${data._2} ${data2._1}: ${data2._2}")
}
EDIT:
The working outcome
//Compare 2 values
def mnuCompareTwoStocks(f: (String) => (String, Int)) = {
print("Stock > ")
val data = f(readLine)
print("Stock 2 > ")
val data2 = f(readLine)
if (data._2 >= data2._2){
println("The higher stock is " + data)
}
else
{
println("The higher stock is " + data2)
}
println(s"${data._1}: ${data._2} ${data2._1}: ${data2._2}")
}
You are trying to compare 2 tuples of type (String,Int). There is no simple comparison operator for such.
scala> ("a",3) > ("b",0)
<console>:12: error: value > is not a member of (String, Int)
("a",3) > ("b",0)
^
Do you want the String to take precedence or the Int?
scala> ("a",3)._1 > ("b",0)._1
res0: Boolean = false
scala> ("a",3)._2 > ("b",0)._2
res1: Boolean = true
There are several problems in your code which are causing the errors you're seeing.
First, you have a syntax error: to print out the variable highest the way you want to, you need to use + for string concatenation: println("The higher stock is " + highest)
Secondly, highest is only declared inside your if statements so it's out of scope for the println statement. You can solve this issue by declaring it in scope:
...
var highest = 0.0
if(...){
highest = ...
}
else {
highest = ...
}
println("The higher stock is " + highest)
Lastly, and most importantly, the overall design of your method doesn't really make sense to me. f is your parameter to mnuCompareTwoStocks, and it's a function that converts from String to (String, Int). So why are you calling apply (via f(readLine)) on this function and seemingly expecting a numeric datatype back? What is even the purpose of this parameter? If, indeed, you do want the tuple to be returned, you'll need to unpack the numeric component before comparing the values:
val data = f(readLine)
val data2 = f(readLine)
if (data._2 >= data2._2)
...
I see you edited your question to solve the first two issues. However, now you're pointlessly setting val highest = Unit with your if statement...
Regardless, you should unpack the Int component of your tuple if you want to do numeric comparison between them, as shown above.

Passing function arguments by Name Scala

I have the following scala code. In this code, I am passing a (global) string name to a function and want to change the string depending on the first argument as shown below:
def retVal(x: (String,String), y: => String) = {if (x._1 != "") {y = x._1;x} else (y,x._2)}
But when I run this code, I get the following error:
y = x._1
^
reassignment to a val
How can I modify the code, so that I get the global string variable get updated when I call this function?
Function arguments are by default immutable in Scala. You cannot assign the a value to the function parameter.
In your case you are trying to assign to a call by name param which is not at all possible.
Also mutating is bad instead return the value and assign it to a new variable.
But still if you want to mutate do something like this
object MutationBox {
var globalString = ""
def retVal(x: (String,String)) = {
if (x._1.nonEmpty) {
globalString = x._1
x
} else (globalString, x._2)
}
}

Type mismatch from partition in Scala (expected (Set[String]...), actual (Set[String]...) )

I have a partition method that creates tuple of two sets of string.
def partition(i:Int) = {
dictionary.keySet.partition(dictionary(_)(i) == true)
}
I also have a map that maps integer to the return value from the partition method.
val m = Map[Int, (Set[String], Set[String])]()
for (i <- Range(0, getMaxIndex())) {
m(i) = partition(i)
}
The issue is that I have type mismatch error, but the error message does not make sense to me.
What might be wrong?
This is the code:
import scala.collection.mutable.Map
import scala.collection.{BitSet}
case class Partition(dictionary:Map[String, BitSet]) {
def max(x:Int, y:Int) = if (x > y) x else y
def partition(i:Int) = {
dictionary.keySet.partition(dictionary(_)(i) == true)
}
def getMaxIndex() = {
val values = dictionary.values
(0 /: values) ((m, bs) => max(m, bs.last))
}
def get() = {
val m = Map[Int, (Set[String], Set[String])]()
for (i <- Range(0, getMaxIndex())) {
m(i) = partition(i)
}
m
}
}
When I compile your example, the error is clear:
<console>:64: error: type mismatch;
found : (scala.collection.Set[String], scala.collection.Set[String])
required: (scala.collection.immutable.Set[String], scala.collection.immutable.Set[String])
m(i) = partition(i)
^
Looking into the API, the keySet method of a mutable map does not guarantee that the returned set is immutable. Compare this with keySet on an immutable Map—it does indeed return an immutable set.
Therefore, you could either
use an immutable Map and a var
force the result of your partition method to return an immutable set (e.g. toSet)
define the value type of your map to be collection.Set instead of Predef.Set which is an alias for collection.immtuable.Set.
To clarify these types, it helps to specify an explicit return type for your public methods (get and partition)