I'm using a MultiMap from the quiver package. I'm trying to populate the map with 2 lists like I would with an ordinary map:
final keys = myMap.keys.toList();
final values = myMap.values.toList();
for (var i = 0; i < values.length; i++) {
map[values[i]] = itemSpit[I];
}
However the for loop doesn't compile: value
The operator '[]=' isn't defined for the type 'Multimap<dynamic, dynamic>'.
How can I add the lists to the multimap
Dart has two versions of the square brackets operator; one for reading (operator []) and one for writing (operator []=). Multimap providers operator [] but does not provide operator []=. Presumably this is because it would be unclear to readers whether multimap[key] = value intends to add a new value or to replace the existing values.
Instead, Multimap provides add and addValues methods for adding values. (Replacing requires explicitly calling removeAll first.)
Related
Is there an idiomatic way to apply a function to all items in a list ?
For example, in Python, say we wish to capitalize all strings in a list, we can use a loop :
regimentNames = ['Night Riflemen', 'Jungle Scouts', 'The Dragoons', 'Midnight Revengence', 'Wily Warriors']
# create a variable for the for loop results
regimentNamesCapitalized_f = []
# for every item in regimentNames
for i in regimentNames:
# capitalize the item and add it to regimentNamesCapitalized_f
regimentNamesCapitalized_f.append(i.upper())
But a more concise way is:
capitalizer = lambda x: x.upper()
regimentNamesCapitalized_m = list(map(capitalizer, regimentNames)); regimentNamesCapitalized_m
What is an equivalent way to call a function on all items in a list in Dart ?
If you want to apply a function to all items in a List (or Iterable) and collect the results, Dart provides an Iterable.map function that is equivalent to Python's map:
// Dart
regimentNamesCapitalized_m = regimentNames.map((x) => x.toUpperCase()).toList();
Python also provides list comprehensions, which usually are considered more Pythonic and often are preferred to the functional approach:
# Python
regimentNamesCapitalized_m = [x.upper() for x in regimentNames]
Dart's equivalent of Python's list comprehensions is collection-for:
// Dart
regimentNamesCapitalized_m = [for (var x in regimentNames) x.toUpperCase()];
If you're calling a function for its side-effect and don't care about its return value, you could use Iterable.forEach instead of Iterable.map. In such cases, however, I personally prefer explicit loops:
I think they're more readable by virtue of being more common.
They're more flexible. You can use break or continue to control iteration.
They might be more efficient. .forEach involves an extra function call per iteration to invoke the supplied callback.
The answer seems to be to use anonymous functions, or pass a function to a lists forEach method.
Passing a function:
void capitalise(var string) {
var foo = string.toUpperCase();
print(foo);
}
var list = ['apples', 'bananas', 'oranges'];
list.forEach(capitalise);
Using an anonymous function:
list.forEach((item){
print(item.toUpperCase());
});
If the function is going to be used only in one place, I think its better to use the anonymous function, as it is easy to read what is happening in the list.
If the function is going to be used in multiple places, then its better to pass the function instead of using an anonymous function.
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/
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.
Are there any documents or examples out there on how one can extend/add new keywords to query expressions? Is this even possible?
For example, I'd like to add a lead/lag operator.
In addition to the query builder for the Rx Framework mentioned by #pad, there is also a talk by Wonseok Chae from the F# team about Computation Expressions that includes query expressions. I'm not sure if the meeting was recorded, but there are very detailed slides with a cool example on query syntax for generating .NET IL code.
The source code of the standard F# query builder is probably the best resource for finding out what types of operations are supported and how to annotate them with attributes.
The key attributes that you'll probably need are demonstrated by the where clause:
[<CustomOperation("where",MaintainsVariableSpace=true,AllowIntoPattern=true)>]
member Where :
: source:QuerySource<'T,'Q> *
[<ProjectionParameter>] predicate:('T -> bool) -> QuerySource<'T,'Q>
The CustomOperation attribute defines the name of the operation. The (quite important) parameter MaintainsVariableSpace allows you to say that the operation returns the same type of values as it takes as the input. In that case, the variables defined earlier are still available after the operation. For example:
query { for p in db.Products do
let name = p.ProductName
where (p.UnitPrice.Value > 100.0M)
select name }
Here, the variables p and name are still accessible after where because where only filters the input, but it does not transform the values in the list.
Finally, the ProjectionParameter allows you to say that p.UnitValue > 100.0M should actually be turned into a function that takes the context (available variables) and evaluates this expression. If you do not specify this attribute, then the operation just gets the value of the argument as in:
query { for p in .. do
take 10 }
Here, the argument 10 is just a simple expression that cannot use values in p.
Pretty cool feature for the language. Just implemented the reverse to query QuerySource.
Simple example, but just a demonstration.
module QueryExtensions
type ExtendedQueryBuilder() =
inherit Linq.QueryBuilder()
/// Defines an operation 'reverse' that reverses the sequence
[<CustomOperation("reverse", MaintainsVariableSpace = true)>]
member __.Reverse (source : Linq.QuerySource<'T,System.Collections.IEnumerable>) =
let reversed = source.Source |> List.ofSeq |> List.rev
new Linq.QuerySource<'T,System.Collections.IEnumerable>(reversed)
let query = ExtendedQueryBuilder()
And now it being used.
let a = [1 .. 100]
let specialReverse =
query {
for i in a do
select i
reverse
}
In F# what is the type annotation for a typed list (e..g list of int)? With a simple function I can do annotations as follows:
let square(x:int) = ...
I've annotated x as an int type. But what if I want to do a type annotation for an int list? For example, let's say I have a max function that expects a list - how would I do a type annotation for it?
let max(numbers:??) = ...
There are two options:
let max (numbers:int list) = ...
let max (numbers:list<int>) = ...
The first version uses syntax that is inherited from OCaml (and is frequently used for primitive F# types such as lists). The second version uses .NET syntax (and is more frequently used for .NET types or when writing object-oriented code in F#). However, both of them mean exactly the same thing.
In any case, the form of type annotation is always (<something> : <type>) where <something> is either a pattern (as in parameter list) or an expression. This means that int list and list<int> are just names of types. F# Interactive prints the type if you enter some value, so you can use this to learn more about how type names are written:
> [1;2;3]
val it : int list = [ 1; 2; 3 ]