Want to clarify about scala.Null. As I know scala.Null has instance null and class. For example if write like this
val x: Null = null
Type inference set type for the x Null.
According Scala classes hierarhy "please see image" Scala cannot use variables without wrappers like Int, Double, etc. That is why we can found Null for the type inference mechanism resolving. Is it correct vision ?
Scala classes hierarhy
You seem to be mixing some of these concepts:
Type Inference is the ability of the compiler to infer the type when the code doesn't explicitly state it. In your example - you do state the type, and that type is Null - no inference here:
val x: Null = null
Here's a simple example of type inference:
scala> val whoKnows = 12
whoKnows: Int = 12
Compiler inferred the type Int since we assigned the value 12, which is an integer. There's much more to it (see http://docs.scala-lang.org/tutorials/tour/local-type-inference), but that's the basics.
null can be used in Scala just like in Java (although it's very much frowned upon, as Scala offers many safer alternatives, mainly None), for example:
scala> val nullStr: String = null
nullStr: String = null
scala> val nullList: List[Int] = null
nullList: List[Int] = null
Where can't null be used? Just like in Java - for "primitives" like int, double etc. In Scala, there's no such thing as a primitive, but there's still a difference between these "value" types (named with upper-case like other types, e.g. Int, Double) and other types: value types share the common trait AnyVal, whereas all other types share the trait AnyRef - to signify, among other things, this difference.
As for what the Null trait is good for - see Usages of Null / Nothing / Unit in Scala
The type Null in Scala is a special type. What's special about it is that it is a subtype of all reference types - it's a subtype of every type that is a subtype of AnyRef.
The reason for that is to make it possible to assign the value null to any reference type.
Note that besides reference types, Scala also has value types. These are the types that are subtypes of AnyVal. Examples of value types are the built-in types that map to the primitive types of the JVM: Byte, Short, Int, Long, Float, Double, Boolean, and Char, and also the type Unit.
Note that AnyVal and its subtypes are not subtypes of AnyRef. You can't assign null to a variable of a value type.
Note that the value types Int, Double etc. are not like Java's wrapper types (java.lang.Integer, java.lang.Double etc.). When you use the value types, there is no boxing and unboxing going on to/from objects. These value types directly map to the primitive types of the JVM. Therefore you cannot assign null to a variable of one of those types.
In other words: types like Int and Double are not wrappers, they directly represent primitive types.
Related
Here is a simple sample code for my question.
var a:Int=1; //line 1
var a=1; //line 2
Is Int in line 1 needed? or must?
if not ,can I delete it like in line 2?
Since 1 is of type Int, compiler knows that a is of type Int too.
This is called type inference.
You should specify a type explicitly when this is better for code readability.
You must specify a type when compiler can't infer the type or when this helps to infer other types.
In Scala type inference can go in both directions, from right to left and vice versa. For example in val a = 1 type of a is inferred from type of 1, so type inference went from right to left. In
def myMethod[T](): T = ???
val n: Int = myMethod()
since n is expected to be an Int, compiler infers that T in myMethod() should be Int too, so type inference went from left to right.
https://twitter.github.io/scala_school/type-basics.html#inference
http://www.scala-lang.org/old/node/127
http://allaboutscala.com/tutorials/chapter-2-learning-basics-scala-programming/scala-tutorial-overview-scala-type-inference/
How does scala infers the type of a variable?
You don't need to specify the type Int in this case, as it is inferred by the compiler.
There is plenty of documentation about type inference in scala. Check this out: http://docs.scala-lang.org/tour/local-type-inference.html
In most cases the Scala compiler can deduce types automatically. In these cases you do not have to explicitly define the type of your variable declaration.
var a = 1
is perfectly valid Scala code.
It is often recommended to declare explicitly the return types of public methods.
I used a scala immutable map as per below.
val d = "4.55"
This is working fine.
val properties = Map("title"->"title" , "value" -> d )
Its convert from [String , AnyRef] to [String, Any]
val properties = Map("title"->"title" , "value" -> d.toDouble )
Cant convert from Double to Object , runtime error
val properties:Map[String,Object] = Map("title"->"title" , "value" -> d.toDouble )
Why object cant accept the Double?
Working fine.
val properties:Map[String,Object] = Map("title"->"title" , "value" -> d.toDouble.asInstanceOf[Object] )
Cant understand the four scenario of Immutable Map behaviour.
Most important of all: Scala has no primitive types as Java do.
Scala's Double is a class, inherit from AnyVal, has it's own methods
But Java's Object is the base class of all reference types, aka...Class
So, what you did here is using Object as base class of Double.
In my opinion,
Scala's AnyRef is the corresponding type to Java's Object.
Scala's AnyVal is the corresponding type to Java's Primitive Types.
As you can see froom the Scala class hierarchy...
... the Scala equivalent of java.lang.Object is AnyRef, and type String is part of that family, but a Scala Double falls under AnyVal. When the compiler has to reconcile those two types it will find type Any, which can't be promoted to type AnyRef/Object without coercion (i.e. a cast).
If you had d.toSeq instead of d.toDouble the compiler would have gone to AnyRef/Object straight away.
I am trying to execute this function
def sumofdouble[T <:Number] (as:T*): Double = as.foldLeft(0d)(_ + _.doubleValue)
If I try using this function like this,
sumofdouble(1,2)
I am getting this error
<console>:13: error: inferred type arguments [Int] do not conform to method sumofdouble's type parameter bounds [T <: Number]
sumofdouble(1,2)
Isn't Integer a subtype of Number? Please explain if I am missing something.
Looks like you are using java.lang.Number. Unfortunatelly, numeric types in scala do not inherit from this class (for reference look at Int definition - like other scala's numerics it inherits directly from AnyVal - http://www.scala-lang.org/api/2.12.0/scala/Int.html) - it is simply not in their hierarchy. What you want to use is the implicit Numeric type class to convert your numbers.
def foo[T](as: T*)(implicit n: Numeric[T]) = as.foldLeft(0d)(_ + n.toDouble(_))
See this question for further information - Scala equivalent of Java's Number.
The following code
object testType extends App {
def func(x:Int) = if(x==0) 1.0 else 'c'
println(func(0))
println(func(1))
}
results in
1.0
99.0
At first when I wrote this, I thought Scala was not going to allow such a function but it interpreted the function as (Int) => Double. This feels like type coercion.
If I substitute the 'c' for "c" in the function above, it actually returns
1.0
c
where the function is now interpreted as (Int) => Any
Questions: if Scala is strongly typed, why did the first example with 'c' returned a Double and why the difference between (Int) => Double and (Int) => Any for the two examples?
There is a relationship between types in Scala called "weak conformance". Char weakly conforms to Double (because it weakly conforms to Int which weakly conforms to Double). The type of if (<cond>) then <e1> else <e2> is defined to be the weak least upper bound (wlub) of types of <e1> and <e2> (there is a similar rule for other expressions with many branches: match and try/catch). The wlub of Char and Double is Double; the wlub of String and Double is Any.
Scala does implicit conversions between types where necessary. Usually it does this through some implicit conversion defined anywhere in scope (most of the implicit conversions are in scala.Predef which is imported by default)
In order to see all available implicit conversions do this in the repl:
:implicits -v
However, if you do that, you will see that there is no implicit conversion available from char2Double. So whats going on? Here, scala compiler resorts to another type of conversion called numeric widening:
If ee has a primitive number type which weakly conforms to the expected type, it is widened to the expected type using one of the numeric conversion methods toShort, toChar, toInt, toLong, toFloat, toDouble defined here.
So, as #Alexey pointed out in his answer that chars weakly conform to Doubles, the char 'c' gets converted to a Double by applying 'c'.toDouble numeric widening conversion.
Also, you can disable implicit conversions that are defined in Predef like this:
// disable int to Integer conversion
import scala.Predef.{int2Integer => _}
However, am not sure whether the numeric widening conversions can be disabled.
As pointed by #pedrorijo91, numeric widening can also be prevented by adding the suitable scalac flags: -Ywarn-numeric-widen & -Xfatal-warnings
I found myself really can't understand the difference between "Generic type" and "higher-kinded type".
Scala code:
trait Box[T]
I defined a trait whose name is Box, which is a type constructor that accepts a parameter type T. (Is this sentence correct?)
Can I also say:
Box is a generic type
Box is a higher-kinded type
None of above is correct
When I discuss the code with my colleagues, I often struggle between the word "generic" and "higher-kinde" to express it.
It's probably too late to answer now, and you probably know the difference by now, but I'm going to answer just to offer an alternate perspective, since I'm not so sure that what Greg says is right. Generics is more general than higher kinded types. Lots of languages, such as Java and C# have generics, but few have higher-kinded types.
To answer your specific question, yes, Box is a type constructor with a type parameter T. You can also say that it is a generic type, although it is not a higher kinded type. Below is a broader answer.
This is the Wikipedia definition of generic programming:
Generic programming is a style of computer programming in which algorithms are written in terms of types to-be-specified-later that are then instantiated when needed for specific types provided as parameters. This approach, pioneered by ML in 1973,1 permits writing common functions or types that differ only in the set of types on which they operate when used, thus reducing duplication.
Let's say you define Box like this. It holds an element of some type, and has a few special methods. It also defines a map function, something like Iterable and Option, so you can take a box holding an integer and turn it into a box holding a string, without losing all those special methods that Box has.
case class Box(elem: Any) {
..some special methods
def map(f: Any => Any): Box = Box(f(elem))
}
val boxedNum: Box = Box(1)
val extractedNum: Int = boxedString.elem.asInstanceOf[Int]
val boxedString: Box = boxedNum.map(_.toString)
val extractedString: String = boxedString.elem.asInstanceOf[String]
If Box is defined like this, your code would get really ugly because of all the calls to asInstanceOf, but more importantly, it's not typesafe, because everything is an Any.
This is where generics can be useful. Let's say we define Box like this instead:
case class Box[A](elem: A) {
def map[B](f: A => B): Box[B] = Box(f(elem))
}
Then we can use our map function for all kinds of stuff, like changing the object inside the Box while still making sure it's inside a Box. Here, there's no need for asInstanceOf since the compiler knows the type of your Boxes and what they hold (even the type annotations and type arguments are not necessary).
val boxedNum: Box[Int] = Box(1)
val extractedNum: Int = boxedNum.elem
val boxedString: Box[String] = boxedNum.map[String](_.toString)
val extractedString: String = boxedString.elem
Generics basically lets you abstract over different types, letting you use Box[Int] and Box[String] as different types even though you only have to create one Box class.
However, let's say that you don't have control over this Box class, and it's defined merely as
case class Box[A](elem: A) {
//some special methods, but no map function
}
Let's say this API you're using also defines its own Option and List classes (both accepting a single type parameter representing the type of the elements). Now you want to be able to map over all these types, but since you can't modify them yourself, you'll have to define an implicit class to create an extension method for them. Let's add an implicit class Mappable for the extension method and a typeclass Mapper.
trait Mapper[C[_]] {
def map[A, B](context: C[A])(f: A => B): C[B]
}
implicit class Mappable[C[_], A](context: C[A])(implicit mapper: Mapper[C]) {
def map[B](f: A => B): C[B] = mapper.map(context)(f)
}
You could define implicit Mappers like so
implicit object BoxMapper extends Mapper[Box] {
def map[B](box: Box[A])(f: A => B): Box[B] = Box(f(box.elem))
}
implicit object OptionMapper extends Mapper[Option] {
def map[B](opt: Option[A])(f: A => B): Option[B] = ???
}
implicit object ListMapper extends Mapper[List] {
def map[B](list: List[A])(f: A => B): List[B] = ???
}
//and so on
and use it as if Box, Option, List, etc. have always had map methods.
Here, Mappable and Mapper are higher-kinded types, whereas Box, Option, and List are first-order types. All of them are generic types and type constructors. Int and String, however, are proper types. Here are their kinds, (kinds are to types as types are to values).
//To check the kind of a type, you can use :kind in the REPL
Kind of Int and String: *
Kind of Box, Option, and List: * -> *
Kind of Mappable and Mapper: (* -> *) -> *
Type constructors are somewhat analogous to functions (which are sometimes called value constructors). A proper type (kind *) is analogous to a simple value. It's a concrete type that you can use for return types, as the types of your variables, etc. You can just directly say val x: Int without passing Int any type parameters.
A first-order type (kind * -> *) is like a function that looks like Any => Any. Instead of taking a value and giving you a value, it takes a type and gives you another type. You can't use first-order types directly (val x: List won't work) without giving them type parameters (val x: List[Int] works). This is what generics does - it lets you abstract over types and create new types (the JVM just erases that information at runtime, but languages like C++ literally generate new classes and functions). The type parameter C in Mapper is also of this kind. The underscore type parameter (you could also use something else, like x) lets the compiler know that C is of kind * -> *.
A higher-kinded type/higher-order type is like a higher-order function - it takes another type constructor as a parameter. You can't use a Mapper[Int] above, because C is supposed to be of kind * -> * (so that you can do C[A] and C[B]), whereas Int is merely *. It's only in languages like Scala and Haskell with higher-kinded types that you can create types like Mapper above and other things beyond languages with more limited type systems, like Java.
This answer (and others) on a similar question may also help.
Edit: I've stolen this very helpful image from that same answer:
There is no difference between 'Higher-Kinded Types' and 'Generics'.
Box is a 'structure' or 'context' and T can be any type.
So T is generic in the English sense... we don't know what it will be and we don't care because we aren't going to be operating on T directly.
C# also refers to these as Generics. I suspect they chose this language because of its simplicity (to not scare people away).