Why `final var` is illegal in Dart? - dart

The analyzer doesn't say final var is illegal.
but dart2js says final var is illegal
What is correct? Why?

The keyword var means mutable variable with explicit dynamic type specifier.
The explicit type specifier means that this is not possible specify another type in declaration.
The keyword final means val or immutable variable with unspecified type, with implicit dynamic type.
The implicit type specifier means that this is possible specify other type in declaration.
More precisely variable that declared as val are the value and variable at once.
It are variable because has the runtime storage.
But it are also immutable value that can be retrieved from associated storage just once and can be used anywhere.
Now consider the following code:
final var foo;
This is the same as the following pseudo code:
immutable mutable dynamic foo;
Of course, this will not work.

That is probably a bug in the analyzer. final and var are mutual exclusive.
One of the following is allowed
final identifier
final type identifier
const identifier
const type identifier
var identifier
type identifier
Dart Programming Language Specification (1.2) - Variables
finalConstVarOrType:
final type?
| const type?
| varOrType
;
varOrType:
var
| type
;
EDIT
My DartEditor (Dart VM version: 1.3.0-dev.3.2 (Mon Mar 10 10:15:05 2014) on "linux_x64") shows an error for final var xxx (Members can not be declared to be both 'final' and 'var'.)

Related

What if i assign a const to a var?

I tried to run this code
var a = const [1, 2, 3];
a.add(10);
print(a);
but I am having an error. As I knew that assigning and const to a variable doesn't make it a const.
So why is this error occurring?
Unhandled exception: Unsupported operation: Cannot add to an
unmodifiable list
Variables in Dart is always references and the type of the variable does not change the state of the object it points to.
So in your case, you have declared a const list which means it is a compile-constant defined list and is therefore implicit unmodifiable.
You now point to this list by using a normal variable. But the type of the variable does not change the fact that your List is created as const from the beginning.

List loses methods when assigning as Map value

I am trying to assign a List as a value to a field in a Map.
However, if I vary the types in the Map, the methods seem to be no longer available on the List.
Example:
var list = [1,2];
var myMap = {
'list' : list,
//'commentOut' : 3,
};
print("${myMap['list'].runtimeType}");
print("${myMap['list']!.length}");
Output
JSArray<int>
2
However, if I uncomment the line 'commentOut' : '
I get the error
Error: The getter 'length' isn't defined for the class 'Object'.
Is there a way to get this to work, or am I misunderstanding something fundamental we can't do with Maps ?
When you do:
var list = [1,2];
var myMap = {
'list' : list,
};
then the inferred type of myMap is Map<String, List<int>>.
When you instead do:
var myMap = {
'list' : list,
'commentOut' : 3,
};
your Map's values are now heterogeneous, so Dart infers the value type as the nearest common base type. In this case, the common base type of List<int> and int is Object, so myMap's inferred type is Map<String, Object>.
Consequently, static analysis tools (the Dart analyzer and the Dart compiler) know only that the static (known at compile-time) type of myMap['list'] is Object? even though the actual runtime type is List<int>. It therefore will be a compile-time error to attempt to directly access List methods on it, because calling List methods on an arbitrary Object is potentially unsafe.
You either must explicitly cast the value (myMap['list'] as List<int>) or disable static type checking by explicitly declaring myMap to be of type Map<String, dynamic>.
3 is a value type, not an object type. So the property "length" is not defined on a value type. Even though you defined the element 'list' to get the length, it doesn't know how to handle it.

Why one dynamic value can be converted to other without casting and the other one fails?

final dList = <dynamic> [];
final List<String> sList1 = dList; // fails (can't implicitly cast)
final sList2 = dList.cast<String>(); // works (needs manual casting)
dynamic dString = '';
final String sString1 = dString; // works
final sString2 = dString as String; // works
You can see the comments in the code part what I am talking about, it is difficult to point out the piece of code here in writing part, so I added them in the code part.
List fails to convert but other types like bool, int, String works with internal casting.
The point is that dList is a List<dynamic>. The type dynamic is a top type (a supertype of all other types), and it's reified (so you can test it at run time, as opposed to Java where type arguments are erased at run time). With cast you are creating a new object, instance of List<String>, so it's allowed to be the value of a variable of that type.
With dString you already have an instance of type String (because '' evaluates to such an instance), so the cast just verifies that this is indeed a String.
You can never use a cast in Dart to obtain an object whose type is different from the starting point, it will only check the type of the existing object (and confirm that the type is as required, or throw).

outputting a value to a typedef pointer in swift

I'm almost certain the title of this isn't correct but here goes...
I'm bridging to an Objective-C class to set a typedef. The bridge is set up and I'm able to declare the typedef var correctly.
In Objective-C I also called a method from the same class that, when called, output a value to the variable TestHandle.
var TestHandle : TESTHANDLE
TestInit(&TestHandle)
When I try this using Swift 5 I get this error:
Cannot convert value of type 'inout TESTHANDLE' (aka 'inout UnsafeMutableRawPointer') to expected argument type 'UnsafeMutablePointer<TESTHANDLE?>?' (aka 'Optional<UnsafeMutablePointer<Optional<UnsafeMutableRawPointer>>>')
Any pointers?
Some observations:
TESTHANDLE appears to be an alias for UnsafeMutableRawPointer
&testHandle is taking a reference (a pointer to the location) of the testHandle, producing a value of type inout UnsafeMutableRawPointer
As the error says, your TestInit function takes a variable of type UnsafeMutablePointer<TESTHANDLE?>?, a.k.a. Optional<UnsafeMutablePointer<Optional<UnsafeMutableRawPointer>>>
Swift has some rules about how & automatically bridges to the various pointer types, but to be frank, I don't understand them very well.
As far as I know, the Swift pointer types cannot represent nil (0x000...000). To do that, they need to be wrapped within an optional. So when you see the type
Optional<UnsafeMutablePointer<Optional<UnsafeMutableRawPointer>>>
It's actually two "semantic" parts:
Optional<UnsafeMutablePointer< Optional<UnsafeMutableRawPointer> >>
↳ A nullable pointer to ... ↳ ... something that's a nullable pointer of unspecified (void) type
The reason you're getting your error is because &testHandle can only bridge your UnsafeMutableRawPointer to a Optional<UnsafeMutablePointer<UnsafeMutableRawPointer>>, but not the required Optional<UnsafeMutablePointer<Optional<UnsafeMutableRawPointer>>> (the difference is in that missing layer of "inner" nullability). To get around this, make your testHandle optional, yourself:
var testHandle: TESTHANDLE? // a.k.a. Optional<TESTHANDLE>, a.k.a. Optional< UnsafeMutableRawPointer>
Then, when you use the & operator, Swift will wrap your value in the required Optional<UnsafeMutablePointer< ... >> outter layer.
typealias TESTHANDLE = UnsafeMutableRawPointer
func testInit(_ p: UnsafeMutablePointer<TESTHANDLE?>?) {
print("Success!")
}
var testHandle: TESTHANDLE? = nil
testInit(&testHandle)

Declare const String from const String

const String IP_ADDRESS = "http://192.168.1.103:8088/";
const String HOME_EXPECTED = IP_ADDRESS + "index.html";
This code returns unexpected error message from Dart Editor.
An expression of type 'num' was expected
Why? and how can I fix it?
I tried using 'final', 'final const', and static. but failed :(
Update
http://dartbug.com/15853 says
So String+ String is a constant (and has been for a while). String* int isn't and is not expected to be.
I created http://dartbug.com/22408
Original
In Dart it is very limited how you can construct consts. The + operator on String isn't whitelisted for const creation.
Try this instead:
const String HOME_EXPECTED = "${IP_ADDRESS}index.html";
or
final String HOME_EXPECTED = IP_ADDRESS + "index.html";
if const is not required.
I don't know this language 'Dart' but looking at the language description, it is not possible to achieve what you want using 'const':
Use const for variables that you want to be compile-time constants. If the const variable is at the class level, mark it static const. (Instance variables can’t be const.) Where you declare the variable, set the value to a compile-time constant such as a literal, a const variable, or the result of an arithmetic operation on constant numbers.
Your second variable declaration is not a literal, a simple assignment to another const variable, nor is it an arithmetic operation of such.
Source: https://www.dartlang.org/docs/dart-up-and-running/ch02.html

Resources