V: Assigned map value is lost

Created on 8 Aug 2019  路  13Comments  路  Source: vlang/v

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

Bug

All 13 comments

@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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

XVilka picture XVilka  路  3Comments

aurora picture aurora  路  3Comments

vtereshkov picture vtereshkov  路  3Comments

jtkirkpatrick picture jtkirkpatrick  路  3Comments

penguindark picture penguindark  路  3Comments