void main() {
final num = [];
num.add(1);
print(num);
}
Output
1
If a final variable is initialized it can't be changed but why does it allow me to change the value whereas it doesn't allow me to reassign the value like num = 5;?
By calling
final nums = [];
you created an empty List of dynamic types.
This list by itself is final and you can't reassign it
However, you can easily add new items to the List as this is just a method on the List.
In other words making a variable final means that it cannot be reassigned, but it doesn't mean that it cannot change.
A final variable can be set only once
Please refer to the Dart language tour to learn more.
One important remark is that num is a class in Dart that may be double or integer, so it's not a good practice to use it as variable name.
Related
void main() {
int a=4;
var b=a;
var c=[1,2,3];
var d=c;
b.truncate();
d.clear();
print("$a,$b,$c,$d");
}
Output
4,4,[],[]
Anyone please explain it.
Why it is clearing c also?
Everything you can place in a variable is an object, and every object is an instance of a class. Even numbers, functions, and null are objects. All objects inherit from the Object class.
When you assign an object to another, dart makes a copy by reference, unlike for basic types (int, bool etc.) where it only copies the current value.
When you use var d=c d will point (refer) to whatever value stored at the memory address of list c. Any change in either c or d will impact both of them.
If you want to work with a deep copy (meaning that d takes values from c and then exists on its own) you will have to use ... : var d = [...c];
If you are interested about these behaviors I would suggest that you read more about "by reference or by value" and about pointers in C language.
On equating the 2 lists ,changes in one list will be reflectd in the other too. If you want the same values in d also then rather then equating them you can do:-
d.addAll(c);
Dart variables do not hold objects, they hold references to objects.
In object oriented programming, objects have identity. An object can be distinguished from a different object which otherwise has the same state (using the identical function, which checks whether two object references reference the same object). Having identity is why you can change an object's state - the object will maintain that change over time because the object exists over time. Objects exist independently of whether there are variables referencing them.
Two different variables can hold references to the same object.
That's what's happening here. The c and d variables reference the same single list object, and the clear method on lists change the state of the existing object, it doesn't create a new object.
Consider this:
void main() {
num a = 4.4; // Bind `a` to (a reference to) the double `4.4`
num b = a; // Bind `b` to the same (reference) value as `a`.
var c = [1,2,3]; // Bind `c` to (a reference to) a new list (call it List#1).
var d = c; // Bind `d` to the same (reference) value as `c` (List#1).
print(identical(a, b)); // "true". It's the same (reference) value.
b.truncate();
print(b); // "4.4", `truncate` doesn't change the object, it returns a new one.
b = b.truncate(); // Changes the (reference) value bound to `b`
print(identical(a, b)); // "false"
print(b); // "4"
print(a); // "4.4" - didn't change the (reference) value bound to `a`
print(identical(c, d)); // "true". It's the same object (reference).
d.clear();
print(identical(c, d)); // "true". It's still the same object (reference).
print(d); // "[]" - clear *changed* the (referenced) object's state.
print(c); // "[]" - and that *object* is now an empty list.
d = []; // Create (a reference to) a new empty list and bind `d` to it.
print("$c - $d"); // "[] - []". Now (references to) different empty lists
c.add(1);
print("$c - $d"); // "[1] - []". Now (references to) different lists
}
Technically: Objects exist and have identity independently of everything else. Objects are not values in the language in the sense that expressions evaluate to values and variables store values (they're neither expressible, denotable, nor storable). Instead references to objects are values that expressions evaluate to and which can be stored in variables. When you create a new object using new Foo(), the object starts existing, and the expression evaluates to a reference to the new object.
In most cases, this distinction between objects and references isn't important enough for people to say "reference to object" all the time, so most of the time the "reference to" is implicit when we talk about "objects". It's still necessary to understand the underlying distinction because it explains what happens when two variables contain references to the same object (aka. "aliasing"), and that an object referenced by a variable can change state even when accessed through a different variable.
The answer is simple d and c have same List Object. So if you do anything on d or c, it will affect the same List Object.
void main() {
int a=4;
var b=a;
var c=[1,2,3];
var d=c;
b.truncate();
d.clear(); // because d and c have same list object
d.add(8); //even if you add anything it will go to the same object
print("$a,$b,$c,$d");
}
This will be the output if you add a item to List d.
OUTPUT:
4,4,[8],[8]
If you want two List Object then use this :
var c = [1, 2, 3];
var d = List.from(c);
Now if you clear List d :
d.clear();
Only List d will get cleared as List c have another List Object
OUTPUT :
4,4,[1, 2, 3],[]
In Dart, looking at the code below, does it 'pass by reference' for list and 'pass by value' for integers? If that's the case, what type of data will be passed by reference/value? If that isn't the case, what's the issue that causes such output?
void main() {
var foo = ['a','b'];
var bar = foo;
bar.add('c');
print(aoo); // [a, b, c]
print(bar); // [a, b, c]
var a = 3;
int b = a;
b += 2;
print(a); // 3
print(b); // 5
}
The question your asking can be answered by looking at the difference between a value and a reference type.
Dart like almost every other programming langue makes a distinction between the two. The reason for this is that you divide memory into the so called stack and the heap. The stack is fast but very limited so it cannot hold that much data. (By the way, if you have too much data stored in the stack you will get a Stack Overflow exception which is where the name of this site comes from ;) ). The heap on the other hand is slower but can hold nearly infinite data.
This is why you have value and reference types. The value types are all your primitive data types (in Dart all the data type that are written small like int, bool, double and so on). Their values are small enough to be stored directly in the stack. On the other hand you have all the other data types that may potentially be much bigger so they cannot be stored in the stack. This is why all the other so called reference types are basically stored in the heap and only an address or a reference is stored in the stack.
So when you are setting the reference type bar to foo you're essentially just copying the storage address from bar to foo. Therefore if you change the data stored under that reference it seems like your changing both values because both have the same reference. In contrast when you say b = a your not transferring the reference but the actual value instead so it is not effected if you make any changes to the original value.
I really hope I could help answering your question :)
In Dart, all type are reference types. All parameters are passed by value. The "value" of a reference type is its reference. (That's why it's possible to have two variables containing the "same object" - there is only one object, but both variables contain references to that object). You never ever make a copy of an object just by passing the reference around.
Dart does not have "pass by reference" where you pass a variable as an argument (so the called function can change the value bound to the variable, like C#'s ref parameters).
Dart does not have primitive types, at all. However (big caveat), numbers are always (pretending to be) canonicalized, so there is only ever one 1 object in the program. You can't create a different 1 object. In a way it acts similarly to other languages' primitive types, but it isn't one. You can use int as a type argument to List<int>, unlike in Java where you need to do List<Integer>, you can ask about the identity of an int like identical(1, 2), and you can call methods on integers like 1.hashCode.
If you want to clone or copy a list
var foo = ['a', 'b'];
var bar = [...foo];
bar.add('c');
print(bar); // [a, b, c]
print(foo); // [a, b]
var bar_two = []; //or init an empty list
bar_two.addAll([...bar]);
print(bar_two); // [a, b, c]
Reference link
Clone a List, Map or Set in Dart
I am using an IntegerChromosome which is an encoding for the actual problem. To determine the fitness I have to decode from the IntegerChromosome, or more the IntegerGene values, to the actual base type for the optimization problem. So, e.g. IntegerGene value 0 means an instance of type Class with values A, 1 means an instance of type Class with values B and so on. So, 01233210 would translate to ABCDDCBA. Only the latter I can evaluate. I get this information at runtime in a class FitnessInput.
Therefore I need to pass FitnessInput to the determination of the fitness function. Looking at a simple example I found that the determination of the fitness, in the eval() method in the example, takes place in a static method. Is there a concept and a related example how to pass runtime objects to the determination of the fitness rather than overwriting a static variable in the class where fitness() is implemented?
A second question related to the problem of fitness determination. I found examples where simple data types Integer, Double are used for the determination of the fitness. While this is of course reasonable, I would like to return an object to the user for the best phenotype, which contains all intermediate results for the determination of its fitness. I guess this should be possible if my return object implements Comparable. How can I make use, e.g., of the Function interface for that?
You might have a look at the Codec interface. This interface is responsible for converting the objects of your problem domain into a Genotype. If I understand your problem correctly, a possible encoding might look like this:
static final List<String> OBJECTS = List.of("A", "B", "C", "D");
static final int LENGTH = 10;
static final Codec<List<String>, IntegerGene> CODEC = Codec.of(
// Create the Genotype the GA is working with.
Genotype.of(IntegerChromosome.of(0, OBJECTS.size() - 1, LENGTH)),
// Convert the Genotype back to your problem domain.
gt -> gt.chromosome().stream()
.map(IntegerGene::allele)
.map(OBJECTS::get)
.collect(Collectors.toList())
);
// Calculate the fitness function in terms of your problem domain.
static double fitness(final List<String> objects) {
return 0;
}
static final Engine<IntegerGene, Double> ENGINE = Engine
.builder(Main::fitness, CODEC)
.build();
The Codec creates a Genotype which consists of an IntegerChromosome of length 10 and converts it back to your problem domain.
I'm not sure if I understood your second question correctly. But if you want to collect the intermediate results as well, you can use the Stream::peek method.
public static void main(final String[] args) {
final List<Phenotype<IntegerGene, Double>> intermediateResults = new ArrayList<>();
final var bestPhenotype = ENGINE.stream()
.limit(Limits.bySteadyFitness(25))
.peek(er -> intermediateResults.add(er.bestPhenotype()))
.collect(EvolutionResult.toBestPhenotype());
}
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.)
For the past few days am trying to learn if pass by value and pass by reference impact the memory differently. Googling this query, people kept repeating themselves about a copy being created in terms of pass by value and how the original value is affected in terms pass by reference. But I was wondering if someone could zero in on the memory part.
This question actually depends heavily on the particular language as some allow you to be explicit and define when you want to pass a variable by value and when by reference and some do it always the same way for different types of variables.
A quite popular type of behavior is to use passing by value (by default) for simple times: like int, string, long, float, double, bool etc.
Let us show the memory impact on a theoretical language:
int $myVariable = 5;
at this moment you have created a one variable in memory which takes the size required to store an integer (let us say 32 bits).
Now you want to pass it to a function:
function someFunction(int parameter)
{
printOnScreen(parameter);
}
so your code would look like:
function someFunction(int $parameter)
{
printOnScreen($parameter);
}
int $myVariable = 5; //Position A
someFunction($myVariable); //Position B
...rest of the code //Position C
Since simple types are passed by value the value is copied in memory to another storage place - therefore:
during Position A you have memory occupied by ONE int (with value 5);
during Position B you have memory occupied by TWO ints (with values of 5) as your $myVariable was copied in memory
during Position C you have again memory occupied by ONE int (with value of 5) as the second one was already destroyed as it was needed only for the time of execution of the function
This has some other implications: modifications on a variable passed by value DO NOT affect the original variable - for example:
function someFunction(int $parameter)
{
$parameter = $parameter + 1;
printOnScreen($parameter);
}
int $myVariable = 5; //Position A
someFunction($myVariable); //Position B
printOnScreen($myVariable); //Position C
During position A you set value of 5 under variable $myVariable.
During position B you pass it BY VALUE to a function which adds 1 to your passed value. YET since it was a simple type, passed by value, it actually operates on a LOCAL variable, a COPY of your variable. Therefore position C will again write just 5 (your original variable as it was not modified).
Some languages allow you to be explicit and inform that you want to pass a reference and not the value itself using a special operator -for example &. So let us again follow the same example but with explicit info that we want a reference (in function's arguments
- note the &):
function someFunction(int &$parameter)
{
$parameter = $parameter + 1;
printOnScreen($parameter);
}
int $myVariable = 5; //Position A
someFunction($myVariable); //Position B
printOnScreen($myVariable); //Position C
This time operation and memory implications will be different.
During Position A an int is created (every variable is always consisted of two elements: place in memory and a pointer, an identifier which place is it. For ease of the process let us say that pointer is always one byte). So whenever you create a variable you actually create two things:
reserved place in memory for the VALUE (in this case 32 bits as it was an int)
pointer (8 bits [1 byte])
Now during position B, the function expects A POINTER to a memory place. Which means that it will locally, for itself create only a copy of the pointer (1 byte) and not copy the actual reserved place as the new pointer WILLL POINT to the same place as the original one. This means that during operation of the function you have:
TWO POINTERS to an int in memory
ONE place reserved for VALUE of the int
Both of those pointer POINT to the same VALUE
Which means that any modification of the value will affect both.
So looking at the same example position C will not print out also 6 as inside the function we have modified the value under the SAME POINTER as $myVariable.
For COMPLEX TYPES (objects) the default action in most programming environments is to pass the reference (pointer).
So for example - if you have a class:
class Person {
public string $name;
}
and create an instance of it and set a value:
$john = new Person();
$john->name = "John Malkovic";
and later pass it to a function:
function printName(Person $instanceOfPerson)
{
printOnScreen($instanceOfPerson);
}
in terms of memory it will again create only a new POINTER in memory (1 byte) which points to the same value. So having a code like this:
function printName(Person $instanceOfPerson)
{
printOnScreen($instanceOfPerson);
}
$john = new Person(); // position A
printName($john); // position B
...rest of the code // position C
during position A you have: 1 Person (which means 1 pointer [1 byte] to a place in memory which has size to store an object of class person)
during position B you have: 2 pointers [2 bytes] but STILL one place in memory to store an object of class person's value [instance]
during position C you have again situation from position A
I hope that this clarifies the topic for you - generally there is more to cover and what I have mentioned above is just a general explanation.
Pass-by-value and pass-by-reference are language semantics concepts; they don't imply anything about the implementation. Usually, languages that have pass-by-reference implement it by passing a pointer by value, and then when you read or write to the variable inside the function, the compiler translates it into reading or writing from a dereference of the pointer. So you can imagine, for example, if you have a function that takes a parameter by reference in C++:
struct Foo { int x; }
void bar(Foo &f) {
f.x = 42;
}
Foo a;
bar(a);
it is really syntactic sugar for something like:
struct Foo { int x; }
void bar(Foo *f_ptr) {
(*f_ptr).x = 42;
}
Foo a;
bar(&a);
And so passing by reference has the same cost as passing a pointer by value, which does involve a "copy", but it's the copy of a pointer, which is a few bytes, regardless of the size of the thing pointed to.
When you talk about pass-by-value doing a "copy", that doesn't really tell you much unless you know what exactly the variable or value passed represents in the language. For example, Java only has pass-by-value. But every type in Java is either a primitive type or a reference type, and the values of reference types are "reference", i.e. pointers to objects. So you can never have a value in Java (what a variable holds or what an expression evaluates to) which "is" an "object"; objects in Java can only be manipulated through these "references" (pointers to objects). So when you ask the cost of passing a object in Java, it's actually wrong because you cannot "pass" an object in Java; you can only pass references (pointers to objects), and the copy the happens for pass-by-value, is the copy of the pointer, which is a few bytes.
So the only case where you would actually copy a big structure when passing, is if you have a language where objects or structs are values directly (not behind a reference), and you do pass-by-reference of that object/struct type. So for example, in C++, you can have objects which are values directly, or you can have pointers to them, and you can pass them by value or by reference:
struct Foo { int x; }
void bar1(Foo f1) { } // pass Foo by value; this copies the entire size of Foo
void bar2(Foo *f2) { } // pass pointer by value; this copies the size of a pointer
void bar3(Foo &f3) { } // pass Foo by reference; this copies the size of a pointer
void bar4(Foo *&f4) { } // pass pointer by reference; this copies the size of a pointer
(Of course, each of those have different semantic meanings; for example, the last one allows the code inside the function to modify the pointer variable passed to point to somewhere else. But if you are concerned about the amount copied. Only the first one is different. In Java, effectively only the second one is possible.)