Home  >  Article  >  Backend Development  >  Python-style generators implemented as channels: reading too early

Python-style generators implemented as channels: reading too early

王林
王林forward
2024-02-08 23:06:17351browse

作为通道实现的 Python 风格生成器:过早阅读

php editor Youzi brought an article about the Python style generator for channel implementation. In this post, we'll introduce the concept of premature reading and how to use channels to implement Python-style generators. In this way, we can use generator syntax in PHP similar to that in Python, providing a more flexible and efficient programming experience. Whether you are a PHP developer or someone interested in generators, this article will provide you with valuable knowledge and practical tips. Let’s explore this interesting topic together!

Question content

I try to implement a Python-style generator using the following channel:

package main

import (
    "fmt"
)

type ContainerIterable[T any] struct {
    content []T
}

func NewContainerIterable[T any]() *ContainerIterable[T] {
    return &ContainerIterable[T]{content: make([]T, 0)}
}

func (c *ContainerIterable[T]) Iterate() chan T {
    ch := make(chan T)
    go func() {
        for _, v := range c.content {
            ch <- v
        }
        close(ch)
    }()
    return ch
}

func (c *ContainerIterable[T]) Add(e T) {
    c.content = append(c.content, e)
}

func main() {
    c := NewContainerIterable[int]()

    for i := 0; i < 5; i++ {
        c.Add(i)
    }

    r := make([]int, 0)
    for v := range c.Iterate() {
        r = append(r, v)
    }

    for i := 0; i < 5; i++ {
        fmt.Println(i, r[i], i == r[i])
    }
}

This works fine, the output is

0 0 true
1 1 true
2 2 true
3 3 true
4 4 true

But when I change

r := make([]int, 0)

to

r := make([]int, 5)

The results are different:

0 0 true
1 0 false
2 0 false
3 0 false
4 0 false

I know that in the second case c.Iterate() before starting reading from the channel

go func() {
        for _, v := range c.content {
            ch <- v
        }

Opportunity to send any content to the channel. This does not apply to the first case because when append() is called, the main() goroutine takes some time to reallocate space for the r slice.

Please advise how to adjust my code to make Iterate() work properly?

Solution

This:

r := make([]int, 5)

will initialize a slice containing 5 elements, all 0. You will then add 5 more elements to it. Your program is reading the first 5 zero elements.

Use: r:=make([]int,0,5)

The above is the detailed content of Python-style generators implemented as channels: reading too early. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete