Behavior of map() on Options - scala

Im trying to map a JSONObject instance into an actual instance through Play Combinators. I am able to get the desrialization work correctly. The question is on the behavior of how map() works on an Option[JSONObject].
Option1:
jsonVal: Option[JSONObject] = getAsJson(input)
jsonVal.map(JSONUtil.fromJsonString(_.toString(), Blah.jsonReads))
Doesnt work, fails to compile as the _ is not resolved correctly. Compiler couldnt find the toString() on the object.
Option2:
jsonVal: Option[JSONObject] = getAsJson(input)
jsonVal.map(_.toString()).map(JSONUtil.fromJsonString(_, Blah.jsonReads))
Works !!. Can some one tell me why the Type of the default variable is not propagated when transformation is done as part of function argument?

It isn't behavior of map, it's behavior of _. It's just a shortcut for the normal function expression (in this case). In the first case you have
jsonVal.map(JSONUtil.fromJsonString(x => x.toString(), Blah.jsonReads))
which obviously doesn't work, and need to write the full version
jsonVal.map(x => JSONUtil.fromJsonString(x.toString(), Blah.jsonReads))

Related

Correct class names in IntelliJ debugger (scala)

I am new to scala & IntelliJ, so this might sound like a stupid question. However, I see that when debugging, IntelliJ will infer parameter types to some kind of "weird" type, in my case MapLike$MappedValues. The expected type would be Map[String, Iterable[Person]].
Why can IntelliJ not display the correct type? Right now this would be kind of important to me, because by debugging I am trying to find out the correct parameter type, because the API documentation on this part is not very clear (working with Apache Flink CEP)
Code example:
val result:DataStream[String] = patternStream.select(patterns => {
val person:Person = patterns.head._2.head
s"Person ${person.name} of age ${person.age} can drink!"
})
This is what I can see in the debugger:
According to the documentation:
"The select() method takes a selection function as argument, which is called for each matching event sequence. It receives a match in the form of Map[String, Iterable[IN]]"
Why does IntelliJ display MapLike$MappedValues and not something like Map[String,Iterable[Person]]?
The debugger is showing you the runtime class.
On the JVM, generic type parameters are "erased" at runtime, so they will not be visible in the debugger. Map is just an interface, but MapLike$MappedValues implements it as inheritor of AbstractMap.
Thus, the displayed class is compatible with the type of the value.
To find the compile time type of an expression, IntelliJ can help you:
select the expression
press the "type info" hotkey (usually shift+ctrl+p)

(Scala) Am I using Options correctly?

I'm currently working on my functional programming - I am fairly new to it. Am i using Options correctly here? I feel pretty insecure on my skills currently. I want my code to be as safe as possible - Can any one point out what am I doing wrong here or is it not that bad? My code is pretty straight forward here:
def main(args: Array[String]): Unit =
{
val file = "myFile.txt"
val myGame = Game(file) //I have my game that returns an Option here
if(myGame.isDefined) //Check if I indeed past a .txt file
{
val solutions = myGame.get.getAllSolutions() //This returns options as well
if(solutions.isDefined) //Is it possible to solve the puzzle(crossword)
{
for(i <- solutions.get){ //print all solutions to the crossword
i.solvedCrossword foreach println
}
}
}
}
-Thanks!! ^^
When using Option, it is recommended to use match case instead of calling 'isDefined' and 'get'
Instead of the java style for loop, use higher-order function:
myGame match {
case Some(allSolutions) =>
val solutions = allSolutions.getAllSolutions
solutions.foreach(_.solvedCrossword.foreach(println))
case None =>
}
As a rule of thumb, you can think of Option as a replacement for Java's null pointer. That is, in cases where you might want to use null in Java, it often makes sense to use Option in Scala.
Your Game() function uses None to represent errors. So you're not really using it as a replacement for null (at least I'd consider it poor practice for an equivalent Java method to return null there instead of throwing an exception), but as a replacement for exceptions. That's not a good use of Option because it loses error information: you can no longer differentiate between the file not existing, the file being in the wrong format or other types of errors.
Instead you should use Either. Either consists of the cases Left and Right where Right is like Option's Some, but Left differs from None in that it also takes an argument. Here that argument can be used to store information about the error. So you can create a case class containing the possible types of errors and use that as an argument to Left. Or, if you never need to handle the errors differently, but just present them to the user, you can use a string with the error message as the argument to Left instead of case classes.
In getAllSolutions you're just using None as a replacement for the empty list. That's unnecessary because the empty list needs no replacement. It's perfectly fine to just return an empty list when there are no solutions.
When it comes to interacting with the Options, you're using isDefined + get, which is a bit of an anti pattern. get can be used as a shortcut if you know that the option you have is never None, but should generally be avoided. isDefined should generally only be used in situations where you need to know whether an option contains a value, but don't need to know the value.
In cases where you need to know both whether there is a value and what that value is, you should either use pattern matching or one of Option's higher-order functions, such as map, flatMap, getOrElse (which is kind of a higher-order function if you squint a bit and consider by-name arguments as kind-of like functions). For cases where you want to do something with the value if there is one and do nothing otherwise, you can use foreach (or equivalently a for loop), but note that you really shouldn't do nothing in the error case here. You should tell the user about the error instead.
If all you need here is to print it in case all is good, you can use for-comprehension which is considered quite idiomatic Scala way
for {
myGame <- Game("mFile.txt")
solutions <- myGame.getAllSolutions()
solution <- solutions
crossword <- solution.solvedCrossword
} println(crossword)

Groovy: getClass method on map literal returns null

In Groovy I use the map literal notation quite frequently in my code, and was curious as to what concrete implementation of Map it was.
After trying a few things, this script best illustrates my confusion:
def map = ["A":"B"]
println map // I assume this avoids any lazy evaluation of the map
println map instanceof HashMap // I tried some other impls too
println map.class
and receive this output:
[A:B]
true
null
This tells me that the map is apparently a HashMap, but the getClass method doesn't want to tell me that.
So my question is: why is getClass returning null, and is there a more appropriate way to get runtime class info from Groovy?
You need to use
map.getClass()
As otherwise it's looking for a key called class
Nearly a duplicate of Why does groovy .class return a different value than .getClass()

dsl for capturing field name

I'm working on a mapper and wanted a typesafe way to capture class fieldnames for mapping and went with a syntax I'd used in C#:
case class Person(name: String, age: Int)
new Mapping[Person]() {
field(_.age).name("person_age").colType[java.lang.Integer]
field(_.name).name("person_name")
}
where def field(m: T => Unit): FieldMap
This triggers the following warnings:
Warning:(97, 13) a pure expression does nothing in statement position; you may be omitting necessary parentheses
field(_.age).name("person_age").colType[java.lang.Integer]
^
Warning:(98, 13) a pure expression does nothing in statement position; you may be omitting necessary parentheses
field(_.name).name("person_name")
^
So clearly that's not a desirable syntax. Any way I can tweak the signature of field to avoid the warning or is there a more idiomatic scala way of mapping fields in a typesafe manner?
Note: #sjrd's answer indeed gets rid of the warning, but the attempted feature doesn't seem feasible with scala reflection after all. My end goal is a Mapper that allows the specifying of T members in a compile time checked mannner, rather than strings, so it's less vulnerable to typo's and refactoring issues.
The field method takes a T => Unit function as parameter. Hence, the lambda _.age, which is equivalent to x => x.age, is typechecked as returning Unit. The compiler warns that you are using a pure expression (x.age) in statement position (expected type Unit), which basically means that the expression is useless, and might as well be removed.
There is a very simple symptomatic solution to your problem: replace m: T => Unit by m: T => Any. Now your expression x.age is not in statement position anymore, and the compiler is happy.
But your code suggests that there is something wrong a little bit deeper, since you obviously don't use the result of m anywhere. Why is m for anyway?

Scala Option vs Java null [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why Option[T] ?
I am a newbie on Scala and I can't really feel that sensation of that difference between null on java and Option on Scala .
I know that none is an object and if I write smth like that on Scala , it will go safe :
val map = Map("koko" -> "is a cat")
val string:Option[String] =map.get("other")
println(string.map(a=>println(a.toString)) )
I well get None as a result instead of throwing an exception .
It's interesting .
However if I need the returning value not to be wrapped by Some . I will use .get to return the value .
In our example , it will throw an exceoption:
map.get("other").get.map(a=>println(a.toString))
I know I can handle this issue by using "match" .
I am taking here that I need to learn what's that booming on option on Scala vs null on java !
What I still couldn't get is that how could I use the advantages of Option but in case there are values existed into my variable , return the value not Some(value)
def testOption(): String = {
val map = Map("koko" -> "is a cat")
val string: Option[String] = map.get("koko")
string
}
I mean is there any way to make this code works instead of updating the return value to be Option[String] !
Imagine that I have to return a String in order to be set into my bean variable that is of type String not Option[String]
How could I make that works without any kind of match !!
I guess if there smth that makes it works , that will make me understand well the power of Option.
Options are actually quite useful. In Java, it's tough to document whether or not something can be null. In Scala, you can often assume all variables are not null.
This gets really useful when you have some computation that can fail or may not be defined. A good instance would be if you have a webapp and there's some user data that isn't filled out, so the computation can't run. If you had the user data in a map, you could do something like
val myData = map.get(userId).map(doFunction).map(toHtml)
println(myData.getOrElse(noDataHtml))
So clearly here we never have to worry about null. If the user data is in the map, we proceed with the computation and then turn that into html. Otherwise, we'll just print out a default html. In Java, at each stage we'd have to do a null check, but in Scala we can just chain functions.