scala value toInt is not a member of Any - scala

The println in the following code works (with or without toInt)
println("retweets : ", e.getOrElse("retweets", 0).toInt)
top10Tweets(""+e.get("text").get, e.getOrElse("retweets", 0).toInt)
But when I pass it as an argument of a function (as above), it does not work. It says "value toInt is not a member of Any"
When I remove toInt, it says,
type mismatch;
[error] found : Any
[error] required: Int
e is a Map, as follows,
def tweetDetails(obj: twitter4j.Status) = {
Map(
"id" -> obj.getUser().getId(),
"screenName" -> obj.getUser().getScreenName(),
"text" -> obj.getText(),
"retweets" -> obj.getRetweetCount(),
"mentions" -> obj.getUserMentionEntities().length)
}
signature of top10Tweets,
def top10Tweets(tweets: String, retweet_c: Int, mention_c: Int) = {
}

edit:
Ok, with the new information I would suggest you to create a case class that holds the data instead of using a Map, this way you will preserve type information. I know it is common to use hashes/maps for that in dynamically typed languages, but in statically typed languages as scala data types are the preferred way.
orig:
As I neither know what e is, nor what signature top10Tweets has, I can only assume. But from your code and the error I assume that e is a Map[String, String] and you are trying to get the string representation of an integer for the key "retweets" and convert it to an Int. As a default value you pass in an Int, so the type inferencer infers type Any, because that is the most common super type of String and Int. However Any does not have a toInt method and thus you get the error.
Map("x" -> "2").getOrElse("x", 4).toInt
<console>:8: error: value toInt is not a member of Any
Map("x" -> "2").getOrElse("x", 4).toInt
Either pass in the default value as String, or convert the value of "retweets" to an Int before, if it exists:
e.get("retweets").map(_.toInt).getOrElse(0)
Anyway a little more information would help to give an accurate answer.

Yes because in Map is "string" -> "string" and You did when getOrElse ( else ) string -> int, thats why its Any.
Map("x" -> 2).getOrElse("x", 4).toInt
works fine or You can:
Map("x" -> "2").getOrElse("x", "4").toInt

The same problem bothers me before you could check below
Map("x" -> 2).getOrElse[Int](x, 4)

Related

How to call Scala method with Map Mutable signature?

I have a Scala code:
import collection.mutable._
def myMethod(mycollection: Map[A, B]) = {
...
}
How do I call this method?
Tried this:
myMethod(["test1", "test2"])
Got error:
Identifier expected but 'def' found
Thanks.
A Map is a data structure that maps a key (of some type K) to a value (of some type V). In Scala, such a pair can be denoted by the syntax key -> value. If your intent is to have a single String key "test1" that maps to a String value of "test2", then you can do that as follows:
Map("test1" -> "test2")
Your declaration of myMethod is invalid: you need to either define actual types for A and B or make them generic parameters for your method (so that the method is generic):
// With specific types (assuming both keys and values have String types):
def myMethod(mycollection: Map[String, String]) = //...
// In generic form (allows any key type A, or value type B):
def myMethod[A, B](mycollection: Map[A, B]) = //...
Either way, you can then use the result as the argument in a call to your method as follows:
myMethod(Map("test1" -> "test2"))
Some points to note:
Square brackets are used when defining generic type parameters, or specifying the types used as type parameters.
Type parameters can be inferred from the values supplied. For example Map("test1" -> "test2") uses String as the type for both the key and the value, and is equivalent to Map[String, String]("test1" -> "test2").
If you need more than one key/value pair, list them with a comma separator, for example: Map("key1" -> "value1", "key2" -> "value2", "key3" -> "value3")
I strongly recommend that you read a good book on Scala, such as the excellent Programming in Scala, 3rd Edition by Odersky, Spoon & Venners, in order to become familiar with its syntax and standard library.
As a final point, I would strongly recommend that you use the immutable version of Map whenever possible. If you're not familiar with functional programming principles, this will seem unusual at first, but the benefits are huge.

Strange type inference behavior

I'm trying to understand why purescript is unable to properly infer type for map parameter in this simple code:
maybeInc :: String -> StateT (Maybe Int) Identity Unit
maybeInc "a" = modify $ map (1 +)
maybeInc _ = return unit
Here is my error message:
No type class instance was found for
Control.Monad.State.Class.MonadState (_0 Int)
(StateT (Maybe Int) Identity)
The instance head contains unknown type variables. Consider adding a type annotation.
However, it works if I specify the type manually:
maybeInc "a" = modify $ \(m :: Maybe Int) -> map (1 +) m
Why it doesn't want to infer this type automatically even it's already provided in function signature?
The current compiler has no way of modeling functional dependencies, which are used in Haskell and the mtl library to capture the relationship between the two type arguments in MonadState.
This means that the compiler can't figure out that the two state types have to be the same (that is, if we find an instance of MonadState for StateT (Maybe Int) Identity, the state type is forced to be Maybe Int).
For now, one solution is to add a type annotation:
maybeInc :: String -> StateT (Maybe Int) Identity Unit
maybeInc "a" = modify modifier
where
modifier :: Maybe Int -> Maybe Int
modifier = map (1 +)
maybeInc _ = return unit

Scala type mismatch while using Map

I was trying to create a map that goes from integers to Nd4j arrays (as in INDArrays) using the nd4s library. I'm struggling with this issue:
import org.nd4j.linalg.factory._
scala> Map(0 -> Nd4j.create(2))
<console>:17: error: type mismatch;
found : org.nd4j.linalg.api.ndarray.INDArray
required: Int
Map(0 -> Nd4j.create(2))
^
If I set the key type as string, it works:
scala> Map("0" -> Nd4j.create(2))
res28: scala.collection.immutable.Map[String,org.nd4j.linalg.api.ndarray.INDArray] = Map(0 -> [ 0.00, 0.00])
It works also by inverting key and value type.
I can't understand what is happening.
I found the answer by asking help on the Scala channel on gitter.
The problem is that nd4s does an implicit conversion for the -> operator, leading to this issue.
https://github.com/deeplearning4j/nd4s/blob/master/src/main/scala/org/nd4s/Implicits.scala#L143-L176

Strange behavior of Void and intersection types

Is this the expected behavior?
scala> val l: List[Void] = "I'm void".asInstanceOf[String with Void] :: Nil
l: List[Void] = List(I'm void)
Is valid to recognize l as List[Void] and show a String as the first element?
This is completely valid, in a sense, and is not specific to Void. By itself, "I'm void".asInstanceOf[String with Void] will not throw a ClassCastException until you actually try to use it in an way that would require treating it as an invalid type.
val l: List[Void] = "I'm void".asInstanceOf[String with Void] :: Nil
This is valid, because we're lying to the compiler to say "I'm void" is an instance of String with Void, and String with Void is a sub-type of Void, which means we can, for a moment have a List[Void], since List[String with Void] <: List[Void]. However, if we try to access to the head of the List[Void], we expect a Void, which the original String is not.
scala> l.head
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Void
It appears to work at first, because everything has a toString method, so it doesn't need to be treated as anything other than Any.
The same thing happens if we try it with String with Int.
scala> val int = "I'm an Int".asInstanceOf[String with Int]
int: String with Int = I'm an Int
scala> int % 2
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
The String with Int will happily exist until reality sets in, and we realize it isn't actually an Int, and doesn't have a % method.
A slight extension to #m-z's answer to explain why .asInstanceOf[String with Void] doesn't throw. We need to distinguish what exists in Scala and what exists in JVM bytecode. In particular, bytecode doesn't support intersection types like String with Void and therefore can't cast to it. So the bytecode emitted for .asInstanceOf[String with Void] is actually the same as for .asInstanceOf[String]; but when the compiler sees values of this type used as Void, it'll insert additional casts.
This is the same reason why you can't distinguish generic types with different parameters (like List[Int] and List[String]) using isInstanceOf: so far as bytecode is concerned, the types are the same.

Is '->' a operator? What does it return?

In Scala I can build a Map this way:
val map = Map(1 -> "one", 2 -> "two", 3 -> "three")
But what does it do? The arguments should be evaluated, so 1 -> "one" has a value. What's it?
I also noticed this expression returns true:
scala> 1 -> "one" == (1, "one")
res1: Boolean = true
So what's the difference?
It comes from the class ArrowAssoc (http://www.scala-lang.org/api/current/scala/Predef$$ArrowAssoc.html). Look in the object Predef (http://www.scala-lang.org/api/current/scala/Predef$.html) which contains all the pre-imported methods. There you should find the method any2ArrowAssoc[A](x: A): ArrowAssoc[A] which is the implicit conversion allowing the method -> to be called on anything.
To elaborate on this answer, this means that the following code is implicit in your examples:
scala> 'a' -> 1 == (any2ArrowAssoc('a').->(1))
res0: Boolean = true
In short it's just an extension method on Pair (or Tuple2) type. If you take a look at Map type in scala, you'' see that it consist of pairs or tuples of arity of 2. As i know it was defined specially for Map construction to denote key value association key -> value, but you can easily write Map(("a", 1), ("b", 2)) which is equivalent to Map("a" -> 1, "b"-> 2), just looks better. So 1 -> "one" == (1, "one") is equals cause it's the same. In scala, -> is defined as an implicit class in Predef object
From book "Programming in Scala" (http://booksites.artima.com/programming_in_scala_2ed):
The Scala compiler transforms a binary operation expression like 1 -> "Go to island." into (1).->("Go to island.").
Thus, when you say 1 -> "Go to island.", you are actually calling a method named -> on an integer with the value 1, passing in a string with the value "Go to island."
This -> method, which you can invoke on any object in a Scala program, returns a two-element tuple containing the key and value.
The Scala mechanism that allows you to invoke -> on any object, implicit conversion.