Scala: Why is it necessary to assign values to a var/val during declaration - scala

Unless I've been doing it wrong. It doesn't seem like we can do things like:
var x;
x = 1;
in Scala, but rather you have to declare and assign a value to it. Are there any reasons for why this is the case?

The obvious reason is to help not leave variables uninitialized.
Note that in your declaration without initialization, you will also need to specify the type.
var x: Type;
gives the following error:
only classes can have declared but undefined members (Note that variables need to be initialized to be defined)
Actually only abstract classes can declare members without defining them. You can still get the desired behavior (variables initialized to a default value) as
var x: Type = _
If Type is a reference type, x will be null. This scenario is useful, for example, in case where a factory method completes initialization of an object after object construction.

Related

Swift. When should you define an Object / Value with specific data type

As I started developing with Swift and searching through different tutorials and documentations about the language, I'm not sure about one thing.
You can declare an object / value with a specific data type like this:
var aString:String = "Test"
var anObject:SKScene = ASceneClass()
Or you can just do it like this:
var aString = "Test"
var anObject = ASceneClass()
The result will be exactly the same (ASceneClass inherits from SKScene of course)
As everyone is doing it different I wonder if there's a logical reason behind it or you do it for readability ?
Declaring type right after variable name is called Type Annotation
When you don't do that, you have to provide initial value
var aString = "Test"
Often value is not known at that moment, or you are not even sure if it's going to be not nil value, then you can declare it as optional
var aString:String?
If you would like to declare variable without any initiaization but you are sure it's not going to evaluate to nil, you force unwrap it
var aString:String!
This is the definition. In practice, it's always better to use type annotations even when you initialize variable with value, because later in your program you will notice anytime you mess something with the type of the variable.
Also, When you declare an array or dictionary, usually nested ones, Xcode might expect them to have type annotations since it might have some issues with writing values when the type is not known in advance.
To recap
You will want to use type annotations whenever you can, which means whenever you are sure about the variable's type in advance
Recommended/Documented way to declare a variable in swift is as follow:
var <variable name>: <type> = <initial value/expression>
Note: Given form declares a stored variable or stored variable property. Its used when you are clear about type annotation of it.
Though its valid to declare variable without its Type.
var variableName = <initial value>
Note: When you don't know type annotation its mandatory to assign 'Initial value' to that variable.
Refer Swift Documentation on Declaration for more details.

Why is constant instance of a value type can NOT change its properties while constant instance of a reference type can?

I'm new to Swift and is trying to learn the concept of Property. I saw the statements and code below from "swift programming language 2.1".
struct FixedLengthRange {
var firstvalue: Int
let length: Int
}
let rangeOfFourItems = FixedLengthRange(firstvalue: 0, length: 4)
rangeOfFourItems.firstvalue = 8 //error: cannot assign to property: rangeOfFourItems is a "let" constant
And the book provided the following explanation for the error:
This behavior is due to structures being value types. When an instance
of a value type is marked as a constant, so are all of its properties.
The same is not true for classes, which are reference types. If you
assign an instance of a reference type to a constant, you can still
change that instance’s variable properties.
Why is constant instance of a value type can NOT change its properties while constant instance of a reference type can? What is the reason behind it? The book did say how but failed to explain why. I think it is good practice to understand the reasons behind how things the way they are. Could someone please kindly explain it to me?
why is constant instance of a value type can NOT change its properties
Because value type is treated as an indivisible unit: it gets copied on assignment, passing it as a parameter behaves like a copy, and so using const-ness locks down the entire struct. In a sense, rangeOfFourItems variable represents the structure itself, not a pointer or a reference to it.
while constant instance of a reference type can?
This is not entirely correct to say that declaring a const variable of reference type makes the instance constant as well. Only the reference is constant, not the instance.
If you think about it, that is the only way this could be meaningfully implemented, because multiple variables can reference the same by-reference instance. If one of these variables is constant and the other one is not constant, assigning a non-const reference to a constant variable could not possibly lock down the referenced object, which would lock out the non-const reference as well:
var a = ByRefType()
let b = a; // b is a constant reference to the same instance as "a"
a.property = newValue; // Prohibiting this assignment would be inconsistent
Of course the constant variable itself (e.g. b above) could not be re-assigned, unlike the non-constant variable a.

Scala var type usage results in type mismatch

I thought that Scala var type is cool, helps to avoid tons of some technical code and makes it possible to concentrate on functionality. However, I now face something really strange. When I compile my program, I get an error message from sbt:
type mismatch;
found: java.sql.Connection
required: String
this.conn = DriverManager.getConnection(
^
Please, pay attention that the compiler points to conn property of the class, and this property is defined in the class like so:
class Db{
private var conn = ""
....
}
So, why does compiler care about types matching, if it is Scala and if I'm using var data type?
var is not a data type. It is a keyword for declaring and defining a mutable variable. The type is not dynamic---it is still inferred at compile-time. In this case conn is inferred to be a String, and it is completely identical to writing
private var conn: String = ""
The whole point of Scala's type system is to disallow passing incompatible types around. It's failing because, obviously, you cannot assign an SQL connection to a variable of type String. Type inference does not allow you to ignore the types of objects, it just lets the compiler figure it out where possible.
var is not a data type, it's one keyword used to define variables in Scala. The other one is val. Whether you use var or val only affects whether the variable you define can be re-assigned to (var) or is read-only (val). It does not affect the type of the variable in anyway.
Regardless of whether you use var or val, the type of a variable is either specified explicitly (by writing : theType after the variable name) or inferred implicitly from the value you assign it to.
In your example, you did not explicitly provide a type, so the inferred type was String as that is the type of conn.

var declaration with type vs without

What is the difference between this
var a = ClassA()
and this
var a: ClassA = ClassA()
Why do one vs the other?
I'm not a Swift developer but I'm fairly certain that it operates in the same way as languages like C# in this regard.
In the first case, the type of the variable is inferred from the type of the expression used to initialise it. Your a variable is thus of type ClassA and can thus refer to any object that is that type or is derived from it. In the second case, you are specifying that the variable is type ClassA explicitly rather than allowing it to be inferred.
In that second case, the annotation is redundant because the specified type is the same as that which would be inferred anyway. If those types were different though, then it would be worthwhile, e.g.
var a: BaseType = DerivedType()
In this case, the variable is being initialised with an object that is one type but the variable is specified to be a type that is more general.
If you are declaring a variable without initialising it then you need an annotation too, because there is no initialising expression from which to infer the variable's type.

scala: why does underscore (_) initialization work for fields but not method variables?

this works:
scala> class foo[T] {
| var t: T = _
| }
defined class foo
but this doesn't:
scala> def foo[T] = {
| var t: T = _
| }
<console>:5: error: local variables must be initialized
var t: T = _
why?
(one can use:
var t: T = null.asInstanceOf[T]
)
There is a mailing list thread where Martin answered:
It corresponds to the JVM. You can omit a field initialization but not a local variable initialization. Omitting local variable initializations means that the compiler has to be able to synthesize a default value for every type. That's not so easy in the face of type parameters, specialization, and so on.
When pressed about how there is or should be any distinction between fields and locals in the matter of Scala synthesizing default values, he went on to say:
In terms of bytecodes there IS a clear difference. The JVM will initialize object fields by default and require that local variables are initialized explicitly. […] I am not sure whether we should break a useful principle of Java (locals have to be initialized before being used), or whether we should rather go the full length and introduce flow-based initialization checking as in Java. That would be the better solution, IMO, but would require significant work in terms of spec and implementation. Faced with these choices my natural instinct is to do nothing for now :-)
So if I understand correctly, the Scala compiler does not actually synthesize default values for object fields, it produces bytecode that leaves the JVM to handle this.
According to SI-4437 there was agreement from Martin on actually endorsing the null.asInstanceOf[T] pattern in the language spec, seemingly for lack of being able to feasibly support a better alternative within existing constraints.
This is defined in section 4.2 of the Scala Language Specification (my italics)
A variable definition var x: T = _ can appear only as a member of a template. It
introduces a mutable field with type T and a default initial value
This, of course, does not answer the why this should be so!
Here is at least one use case that I just uncovered. When then superclass initializes member variables via reflection it can actually initialize a subclasses member variables. However, if a subclass also initializes the member variable with a value, then this will have the effect of overwriting the value that the superclass gave it. This can be avoided by initializing the subclasses member variable with the underscore. This is why the language spec talks about giving the variable a getter function that returns the current value a little further down from the quoted sentence in oxbow_lake's sentence.