How to create an empty Map in Dart - dart

I'm always forgetting how to create an empty map in Dart. This doesn't work:
final myMap = Map<String, dynamic>{};
This is ok:
final myMap = Map<String, dynamic>();
But I get a warning to use collection literals when possible.
I'm adding my answer below so that it'll be here the next time I forget.

You can create an empty Map by using a map literal:
{}
However, if the type is not already known, it will default to Map<dynamic, dynamic>, which defeats type safety. In order to specify the type for a local variable, you can do this:
final myMap = <String, int>{};
And for non-local variables, you can use the type annotation form:
Map<String, int> myMap = {};
Notes:
DO use collection literals when possible.
Omit type annotations for local variables.

Here's how I remember the syntax:
{} is a literal, and () performs an invocation1. T{} is illegal syntax, and T() invokes the unnamed constructor for T. It doesn't matter what T is, whether it's Map<K, V> or String or any other class.
{} is a literal, but what kind of literal? Is it a Set or a Map? To distinguish between them, you should express the type. The way to express types for generics is put types in angle brackets: <K, V>{} for a Map<K, V>, and <E>{} for a Set<E>.
The same goes for Lists: [] is a literal, and you can specify the type with angle brackets: <E>[].
1 Obviously there are many other uses for {} and () in other contexts.

Related

Dart, Why Iterable<T> can store in List<T> variable?

Why Dart allow me to store Iterable<T> in List<T> variable?
List<int> list = [1, 2, 3].map((i) => i);
It's caused a lot of problems when I use map function because it returns me Iterable<T> then I store to list variable.
When I try to get an element from list using list[0] it will cause an error.
Dart currently allows implicit downcasts.
When you try to store a value with static type S in a variable of a type T, then:
* If T is a supertype of S, then it just works.
* If S is a subtype of T, then the compiler inserts an implicit downcast to the subtype
* Otherwise it's a compile-time error.
This means that:
List<int> iterable = [1, 2, 3].map((e) => e);
is compiled as
List<int> iterable = [1, 2, 3].map((e) => e) as List<int>;
That will fail at runtime when it tries to do that cast. And it does fail.
It should not fail when you try to read an element, it should fail immediately when you try to assign the iterable to the list variable. If it doesn't, it's probably because you are compiling to JavaScript. The JavaScript compiler omits a number of run-time type checks under the assumption that they'll probably succeed (that's an unsafe optimization, but nevertheless an optimization with a significant impact). So, you are doing an unsafe downcast, the language inserts a check to make sure it's safe, then the compiler omits that check again, and you get the bad behavior later than intended.
Exactly the iterable/list subtyping has caused a lot of issues because it's so easy to accidentally create an iterable when you meant it to be a list.
When Dart introduces non-nullable types, it would get even worse, so at that point, it will remove the implicit downcast feature, and you will get an error when trying to assign an iterable to a list variable.
Call the .toList() method on the Iterable.
List<int> list = [1, 2, 3].map((i) => i).toList();
Your code throws a runtime error, even before using the [] operator, because the .map function returns an Iterable<T> (that doesn't have the [] operator) which cannot be cast to a List<T>. You either want to use .toList to convert your Iterable<T> to a List<T> or .elementAt(index) can be used instead of [].
For example:
var list = [1, 2, 3].map((e) => e).toList(); // Using .toMap
list[1]; // Get the second value.
var iterable = [1, 2, 3].map((e) => e); //Using elementAt
iterable.elementAt(1); // Get the second value.

Clarifying field types in F#

After some practice with F#, I have still some points where I need to clear confusion:
The question is specifically about fields in a type.
This is what I understand and, some must be wrong because the naming wouldn't make sense if I was right:
let x -> private read-only field, evaluated once
let mutable x -> private mutable field
val x -> public read-only field.. difference with let?
val mutable x -> public mutable field
member this.x -> private read-only field, evaluated every time
member val -> public mutable field.. difference with val? why no mutable keyword?
Can someone tell me what is right / wrong, or some concepts I may have gotten wrong.
First of all, you can pretty much ignore val and val mutable. Those two are used with an older syntax for defining classes that is not exactly formally deprecated, but I would almost never use it when writing new normal F# code (there are some rare use cases, but I don't think it's worth worrying about those).
This leaves let and let mutable vs. member and member val.
let defines a private field that can only be accessed within the class. The value you assign to it is evaluated once. You can also define functions like let foo x = x + 1 or let bar () = printfn "hi" which have body that's evaluated when the function is called.
let mutable defines a private mutable field. This is initialized by evaluating the right-hand side, but you can later mutate it using fld <- <new value>.
member this.Foo = (...) defines a get-only property. The expression (...) is evaluated repeatedly whenever the property is accessed. This is a side-effect of how .NET properties work - they have a hidden get() method that's called whenever they are accessed, so the body is the body of this method.
member val Foo = (...) is a way of writing a property that is evaluated only once. In earlier versions of F#, this was not available, so you had to implement this functionality quite tediously yourself by definining a local field (to run the code once) and then returning that from a regular property:
let foo = (...)
member x.Foo = foo

why identical() return true on two strings

I'm new to Dart. The documentation say: "To test whether two objects x and y represent the same thing, use the == operator. (In the rare case where you need to know whether two objects are the exact same object, use the identical() function instead.)"
So, if type this code:
var foo = 'bar';
var baz = 'bar';
print(identical(foo, baz));
If i've well understood, foo and bar do not reference the same object. So identical() must return false, isn't it ?
But it's not the case, at least in DartPad.
Where is the problem.
In this case foo and bar do reference the same object.
That is because the compiler canonicalizes string literals.
The specification requires most constants to be canonicalized. If you create const Duration(seconds: 1) in two places, it will become the same object. Integers, doubles and booleans are always canonicalized, whether constant or not (the language pretends that there is only one instance per value).
Strings are special in that the specification is not entirely clear on whether they need to be canonicalized or not, but constant strings need to be canonicalized for constants to make sense, and all the compilers do that.
A literal is a constant expression, so string literals are always canonicalized. That means that 'bar' denotes the same object no matter where it occurs in your code.
For several built-in "literals", you will always get identical true for equal values.
bool
String
int
double (I think)

What's for type declaration the variable in Dart? What reason we recommend it?

I just wanna know about this functionalities and what's effects if we don't use this on every single projects. Thanks for the explanation before.
Example:
int number = 2;
bool isTrue = true;
double floatNumber = 2.1;
Why we not use like this?
var number = 2;
var isTrue = true;
const floatNumber = 2.1;
There are various related Dart style guide rules
PREFER type annotating public fields and top-level variables if the type isn’t obvious.
CONSIDER type annotating private fields and top-level variables if the type isn’t obvious.
AVOID type annotating initialized local variables.
DO annotate when Dart infers the wrong type.
So for example for local variables the style guide even suggests to omit type annotations. The scope of the type annotations is limited to the function/method so the risk is low that inferred types can cause confusion.
For other situations the style guides suggests to add type annotations to avoid ambiguity.
There was a recent addition to Dart that allows to use integer literals to initialize double variables. This only works if the type annotation is added.
var val = 1;
print(val);
1
double val = 1;
print(val);
1.0
This example isn't too practical, because the feature is mostly used to pass literal double values to function/method/constructor parameters, but it demonstrates that the context is important for the decision when to explicitly specify the type using type annotations and when it is safe to omit.
There are also various linter rules that help to stay consistent.
https://pub.dartlang.org/packages/linter
https://dart-lang.github.io/linter/lints/

defining a tuple data type of unknown length in Rascal

I was curious to know if one could define a data type that we know, should be a tuple, but whose length (or number of elements is indeterminable) currently. The application is as follows:
//I want to declare a data type, one of whose argument is a tuple,
public data MyType=fromListCartesianProduct(tuple<?> product)
//Later I want to instantiate a MyType data by using taking List-CartesianProduct
//instantiate some MyType data
foreach(aTuple in [1,2,3]*["a","b"])
someArr[i]=fromListCartesianProduct(aTuple)
The salient observation is that the number of elements in aTuple is indeterminable while declaring "MyType". Can I still declare such a type in a rascal script?
As an alternate, I would declare MyType as:
public data MyType=fromListCartesianProduct(list[] product)
and convert each tuple from taking the cartesian product into a list before constructing the specific instances. For reasons of clarity and others, I would like to define MyType as I previously did.
In principe the answer is no. Tuples have fixed length and we do not (yet) have row polymorphism.
Having said that, data constructors do support different kinds of polymorphism which might help:
row polymorphism using keyword parameters, you can always add more keyword parameters to a data-type, as in
data MyType = myCons(int j = 0); // initial decl
data MyType(int k = 1); // extension with another field
overloading, you can always add more constructors with more parameters
data MyType = f(int i); // initial declaration
data MyType = f(int i, int j); // overloaded declaration with more fields
You might use the make function from Type to dynamically construct such constructors based on argument lists. At the risk of run-time type exceptions of course.
Another way of dealing with data of unpredictable type is to go up one level in the type hierarchy (let it be value), and later pattern match your way out again:
list[value] myListRelationOfUnknownType = ...;
for (<int i, int j> <- myListRelationOfUnknownType)
println("printing only pairs of ints: <i> - <j>");
for (<int i, int j, int k> <- myListRelationOfUnknownType)
println("printing only the triples of ints: <i> - <j> - <k>");
That's a statically more safe way.

Resources