How to access member variables in nested case classes - scala

I have this code:
case class L2JsonMapping(myTarget: Option[Int])
case class L1JsonMapping(l1: Option[L2JsonMapping])
case class JsonMapping(l0: Option[L1JsonMapping])
Assume that they have been initialized. Now how should I get "myTarget" assigned to "result" in the following function:
def function(in: JsonMapping): Int = {
val result = ?
...
}
Note that I also need to handle Option situation. Thanks.

You'll have to supply a default value to return in case one of the Options is None. Let's assume that default is 0 - if so, you can use:
def function(in: JsonMapping): Int = in.l0 // get Option[L1JsonMapping]
.flatMap(_.l1) // flatMap to get an Option[L2JsonMapping]
.flatMap(_.myTarget) // flatMap to get an Option[Int]
.getOrElse(0) // get value value or default
This uses Option.flatMap which you can read about in the ScalaDocs:
Returns the result of applying [the given function] f to this scala.Option's value if this scala.Option is nonempty. Returns None if this scala.Option is empty.
NOTE that this simply returns the value of myTarget - I'm assuming you're assigning it to result just to return result immediately - if so, that's redundant.

Related

Understanding Scala Syntax

I have code below and I wanted to know what does Seq[String] = List() mean?
Does it mean it takes sequence of strings and converts it into List()?
def somefuncname(input: Seq[String] = List()): Unit = {
//Some Code
}
First try to understand the below function signature.
def somefuncname(input: Seq[String]): Unit = {
//Some Code
}
The above code is a function declaration. Its a function which takes 1 argument called input which is of type Seq[String]. That means it takes sequence or list of strings as input and returns nothing Unit
Now, what does = mean?
= after the input argument of the function means default value for the function argument. If you are not interested in passing a custom "sequence of strings" then you can rely on the default argument of already passed.
Now, what does List() mean?
List() returns sequence of 0 elements or empty sequence. That means function is taking empty elements as default argument
alternatively you can also pass Seq() as default argument. It also means empty sequence
def somefuncname(input: Seq[String] = Seq()): Unit = {
//Some Code
}
Now to use the function in any of the following ways
somefuncname() // Now input is empty sequence of strings
somefuncname(Seq("apple", "cat"))
somefuncname(List("apple", "cat"))
input is of type Seq[String] and it has a default value of empty list (List()).
Having a default value means so that if you call the function without passing an argument it would get the default value

Difference between underscore (_) and triple question marks (???) in scala

I am in the middle of writing some code so I wanted to leave a method unimplemented which I am calling but that pathflow is not hitting based on input I am providing. The method looks like this
object HbaseStore {
def get() = _
}
But the above code threw an exception
HbaseStore.scala:24: error: unbound placeholder parameter
[INFO] def get() = _
But when I replaced _ with ??? code executed successfully. I am just curious to know what is the difference between these two. As far as I know, _ provides default values so I assumed it would define an empty function here and return Nothing.
_ is a placeholder syntax, which is used to bind values. Placeholder syntax is used in many scenarios, for example:
In case of list:
val x = List(1,2,3,4,5)
//To print each value we can do:
x.map(res => println(res))
//Now, we can use placeholder syntax to bind res value.
x.map(println(_))
Pattern matching:
val x = "some value"
x match {
case x:String => //convert to lowercase and print.
case res#_ => //here, type doesnot matter I just want to get that value and print as it is. println(res)
So, basically, you use placeholder syntax if you want to have the value without knowing its type.
On the other hand, ??? is assigned to method or variables as value in case you don't want to provide implementation.
e.g. def doSomething() => ???
here, doSomething() method is not implemented, and you need to provide or override implementation later. Note, that you cannot use variables/methods without implementations and you will get exception in case you try to invoke it. e.g. doSomething() will fail in above case.
If you want to use _ as a default value you need to provide a type of this value. For example var x: Any = _ will be initialized with null but var x: Int = _ will be initialized with 0.
Regarding ??? :
You can click on the definition of ??? in IDE:
def ??? : Nothing = throw new NotImplementedError
Since Nothing is a subtype of any given type, it works.

Do I have to initialize Option type in Scala

What is the different between Option[String] and Option[String] = None? I think Option type is default to None if not set, but not 100% sure. Wondering if there will be any potential impact.
For example:
case class User(name:Option[String])
Will it be different from
case class User(name:Option[String]=None)
I think you confuse two different concepts: Default arguments and Default initial values.
Default arguments
In Scala you can provide default arguments for parameters of methods and constructors. And it allows you to skip those arguments:
case class User(name:Option[String]=Some("Sam")) {
def say(greeting: String = "Hello"): String = greeting + " " + name
}
val u = new User
println(u.say())
As you can see, it has nothing to do with Option and None. It works for any type (see the method) and yes, you have to specify that default yourself, otherwise it will not compile:
case class User(name:Option[String])
val u = new User
// Doesn't compile.
And no, None is not the default value for Option[A] when we talk about default arguments. You can provide None as well as any other value of type Option[A] as a parameter of type Option[A], but you have to do it explicitly:
case class User(name:Option[String]=Some("Sam"))
case class User(name:Option[String]=None)
So, talking about parameters to methods and constructors, there's no default value for values of type Option[A]. You must specify that default yourself, otherwise it will not compile.
So, these two lines from your question are indeed different:
case class User(name:Option[String])
case class User(name:Option[String]=None)
Default initial values
Consider this code:
var name: Option[String] = _
println(name)
null is printed. Because the default value is null, not None. And this is the case not only for Option[A], but for all AnyRef types in Scala. The following prints null either:
var name: String = _
println(name)
Please, refer also to Scala Language Specification. E.g. https://www.scala-lang.org/files/archive/spec/2.11/04-basic-declarations-and-definitions.html#variable-declarations-and-definitions
Your assumption is incorrect. There is no standard default for parameters; usually, parameters that are declared must also be provided explicitly when the method or constructor is called.
But a parameter can be declared as optional, and supplied with a default value at its declaration point: When you declare a parameter with its name and type, and then you add the equals sign followed by a static value, then this parameter becomes optional. If left out, the given static value will be inserted automatically.
This does not only work with case classes, but also with other kinds of constructors and methods.
In the first example that you have given, a statement like val user = User() would not compile, because the name parameter must be given.
In the second example, val user = User() would very well compile. At runtime, user.name would have the value of None.

Declare a null var in Scala

I have read that null should not be used in scala.
How can I leave myVar uninitialized without the use of null?
class TestClass {
private var myVar: MyClass = null
}
I understand I can just make a dummy MyClass, that is never used in place of the null. But this can and does reduce the code's understandability.
As Rado has explained I can change null as shown below. I understand that I can now check to see if the variable is set during run-time, however, if I don't program that check then there is no benefit of using Option in this case.
Coming from Java, I feel there should be a way to simply leave the var uninitialized at compile-time and let it set during run-time without using the Option class, because as I mentioned above, if I don't code for the unset case then why use Option?
class TestClass {
private var myVar: Option[MyClass] = None
private def createVar() {
myVar = Some(new MyClass)
x: MyClass = myVar.get
}
}
I am thinking the only other way of doing what I am asking is:
class TestClass {
// Using dummy MyClass that will never be used.
private var myVar: MyClass = new MyClass
private def process(myVar: MyClass) {
this.myVar = myVar
myVar.useVarMethod()
}
}
The Scala way is to declare the variable as Option[MyClass]:
class TestClass {
private var myVar: Option[MyClass] = None
private def createVar() {
myVar = Some(new MyClass)
}
// Usage example:
def useMyVar(): Unit = {
myVar match {
case Some(myClass) => {
// Use myClass here ...
println(myClass.toString)
}
case None => // What to do if myVar is undefined?
}
}
}
That way you avoid NullPointerException. You make it explicit that the variable can be in undefined state. Everytime you use the myVar you have to define what to do if it is undefined.
http://www.scala-lang.org/api/current/index.html#scala.Option
I need myVar to be of type MyClass not Option[MyClass]. I see that I
could use Rado's updated answer and then use the get method, but is
there any other way?
When you use Option you can telling the compiler and everyone else who will read/use your code that it's okay not to define this value and the code will handle that condition and not fail at runtime.
The other way of dealing with is to do null checks every time before you access the variable because it could be null and therefore throw an exception at runtime.
When you use Option, the compiler will tell you if at compile time that you have not handled a condition where the value of a variable maybe undefined.
If you think about it, it's really a big deal. you have converted a runtime exception (which is deterministic) to a compile-time error.
If you want to extract the value out of something like an Option (which supports map and also flatMap), then you don't necessarily have to keep doing pattern matching on whether or not the Option contains a value (i.e. is a "Some") or not (i.e. is a "None").
Two methods are very useful - if you want just alter (or "map") the value within the Option then you can use the map method, which takes a function with a general type of:
f: A => B
so in your case at compile time would end up being:
f: MyClass => B
When you map an option, if the option is a "Some" then the contained value is passed through to the mapping function, and the function is applied (to change the MyClass to a B if you like...) and the result is passed back wrapped in an Option. If your Option is a None, then you just get a None back.
Here's a simple example:
scala> case class MyClass(value : String)
defined class MyClass
scala> val emptyOption : Option[MyClass] = None
emptyOption: Option[MyClass] = None
scala> val nonEmptyOption = Some(new MyClass("Some value"))
nonEmptyOption: Option[MyClass] = Some(MyClass(Some value)
Try and extract the value from both option instances using map:
scala> nonEmptyOption map { s => s.value + " mapped" }
res10: Option[String] = Some(Some value mapped)
scala> emptyOption map { s => s.value }
res11: Option[String] = None
So basically, if you map across an empty option, you always get a None. Map across a non-empty Option and you can extract the contained value and transform it and get the result wrapped back in an Option. Notice that you don't need to explicitly check any patterns...the map method takes care of it.
Flatmap is a bit more challenging to explain, but it basically isn't massively different except that it takes a function which has type:
g: A => M[B]
which basically allows you to take the value out of the Option (the 'A' in the type signature above), do something to it (i.e. a computation) and then return the result ('B') - wrapped in another container such as another Option, List...
The same notion (across Option anyway) that if the Option is a None then nothing really happens still applies. flatMap and map form the basis of Scala "for comprehensions" which you can read about (and are done far more justice than I could!!) in lots of other places.

Why calling a function like this works in Scala?

I have the following Scala code snippet:
type Set = Int => Boolean
def contains(s: Set, element:Int): Boolean = s(element)
def singletonSet(element: Int): Set = Set(element)
val oneElementSet = singletonSet(5)
contains(oneElementSet, 5) // true
contains(oneElementSet, 6) // false
I'm trying to wrap my head around what this does: Set(element). Looks like it'll substitute element in place of an Int argument, to produce this: 5 => Boolean. There is no comparison anywhere, so why does oneElementSet(5) returns true, and oneElementSet(6) returns false?
Thanks!
Scala has separate namespaces for types and values. Your type alias defines what Set is in the type namespace, but in the definition of singletonSet Set comes from the value namespace, in fact it is the companion object scala.collection.immutable.Set. Set(element) invokes the apply method of the companion object, which returns a scala.collection.immutable.Set[Int], which turns out to be a subtype of Int => Boolean and therefore is a Set (your type alias) as well.