a struct must have a `next()` method to be an iterator

464 Views Asked by At

I get this error in vlang:

a struct must have a next() method to be an iterator

struct Items {
    item []Item
}

struct Item {
    name string
    link string
  tags []string
}
pub fn (mut app App) index() vweb.Result {
    text := os.read_file(app.db) or { panic(err) }
    items := json.decode(Items, text) or { panic(err) }
    println(items)
    return $vweb.html()
}

index.html:

@for item in items
    <h2>@item.name</h2>
@end
2

There are 2 best solutions below

1
On

Disclaimer, this is my second day in V lang...

I got 1 step further with this added to stack.v, this is just my main .v file for this scenario

maybe you understand enough to keep you going after this stone step?

pub fn (i &Items) next() Item {
  return i.name
} 

it stopped complaining a struct must have a next() method to be an iterator

and started complaining about return types and insisting on an optional.

I was able to get this far thanks to: V Docs:References V Docs: Heap Structs V Docs: Methods V lib: Method Args

I look forward to hearing if this got you anywhere, I'll keep looking at this tomorrow because I want to understand it. But I been 'grammin 13hrs straight now, and I'll do better with a clear head...

0
On

@DeftconDelta was looking in the right direction

You need to define a method called next that return an optional value (i.e., that returns a type that starts with ?, for example, ?int.

So, for you this method would be something like the following:

// You need to include a pointer to the current item in your struct
struct Items {
    items       []Item
    current_idx int = -1
}

pub fn (mut i Items) next() ?Item {
    i.current_idx++
    if i.current_idx >= i.items.len {
        // tell the iterator that there are no more items
        return none
    }
    return i.items[i.current_idx]
}

Otherwise, if the struct isn't really necessary, you can just use an array of Item, so you don't have to bother with that