V version: 0.1.17
OS: MacOS Mojave
What did you do?
Assign a value to map and after reading it back it was not set to the expected value.
See code below, not sure if this is a bug or I should code it different.
How should the struct field be initialised? Should I create a method to return a new instance of the struct initialised to a empty map?
sample code:
struct MyStruct{
mut:
visited map[string]bool // map[string]bool{} not allowed => struct_map.v:4 expected `.name` but got `{`
}
const (
key = 'key'
)
fn main(){
fails()
succeeds()
}
fn fails(){
println('\nfails()')
mut ms := MyStruct{}
println(ms.visited[key].str()) // false (=OK)
ms.visited[key] = true // assign true value to map
println(ms.visited[key].str()) // assigned true so should print true (but prints false!) <------
}
fn succeeds(){
println('\nsucceeds()')
mut ms := MyStruct{}
ms.visited = map[string]bool{} // caller creates empty map
println(ms.visited[key].str()) // false (=OK)
ms.visited[key] = true // assign true value to map
println(ms.visited[key].str()) // true (=OK)_
}
What did you expect to see?
The succeeds() output for both, or a compiler error stating the map was not initialised. Since now the set value is lost without warnings.
What did you see instead?
fails()
false
false
succeeds()
false
true
@mvlootman this is expected behavior as in the first example you did not initialize the map, you can do it when you create a new instance of MyStruct like this:
mut ms := MyStruct{
visited: map[string]bool{}
}
@joe-conigliaro I understand the issue and the solution. But shouldn't this generate a compile/runtime error/panic when assigning to an uninitialised map? Instead of failing silently.
@mvlootman I guess It will eventually be implemented to throw an error when trying to assign to an uninitialized map. I might add it even.
@joe-conigliaro Is there a reason why arrays are initialised and maps are not?
I'm not sure of the reasoning
It's simply not implemented yet.
In that case ill try implement, thought you had it like that for a reason
Will this be implemented in a map?
// Iterate just over the keys
for key in phone_book {
println($key)
}
// Iterate just over the values
for value in phone_book {
println($value)
}
It throws: cannot range over type map_int
but
// Iterate over all key:value pairs
for key, value in phone_book {
println('$key: $value')
}
works fine.
Or will..
keys := phone_book.keys()
for key in keys {
print('$key: ')
}
..be the way to go?
(I'm working on Rosetta Code examples for maps)
edit: Not the official Rosetta homepage, I'm not confident enough for that. Only a small github repo I like. Btw on the official homepage already exists a language called V and V is called Vlang :/
As maps need to be initialised before use, this is the same case as pointers. V doesn't allow null initialisation for pointers, so likewise V should require that all maps are initialised before use. If the user doesn't want to initialise the map when it comes into scope, they should use an optional map.
@ArcDrake fairly certain you can do for k, v in map
@ntrel why not just init to empty map
This PR adds auto initialization for struct map fields: https://github.com/vlang/v/pull/1606
fixed by #1606
why not just init to empty map
If it doesn't allocate that's ok, assuming it gets done in all situations. It looks like it just sets element_size. So after map is made generic, initialization might not be needed.