[Ici](http://qiita.com/hiroykam/items/2fea445fd2d489354c34#%E3%82%B8%E3%82%A7%E3%83%8D%E3%83%AC%E3%83%BC%E3 Lorsque j'étudiais des générateurs en PHP et Python3 avec% 82% BF), j'ai étudié comment cela pouvait être réalisé dans Golang et Ruby.
J'ai lu "numbers.txt" et j'ai préparé un générateur simple qui produit les résultats de sortie suivants.
numbers.txt
zero
one
two
three
four
five
Résultat de sortie
0:zero
1:one
2:two
3:three
4:four
5:five
Vérifié avec PHP 5.6. Je n'ai pas sélectionné PHP7 car je n'ai pas utilisé yield from
cette fois.
<?php
function my_generator($name)
{
$file = fopen($name, "r");
if ($file) {
while ($line = fgets($file)) {
yield $line;
}
}
fclose($file);
}
$g = my_generator("numbers.txt");
foreach ($g as $k => $v) {
print($k. ":". $v);
}
Cela peut être réalisé de la même manière que PHP. J'ai utilisé la version 3.5 comme version Python.
def my_generator(name):
with open(name) as lines:
for line in lines:
yield line
g = my_generator("numbers.txt")
for k, v in enumerate(g):
print("%s:%s" % (k, v), end="")
Golang n'a pas l'équivalent de PHP ou Python yield
(voir Reference ici). Par conséquent, nous avons réalisé quelque chose de similaire en utilisant le canal ou la fermeture Goroutine.
En supposant que le nombre de lignes dans numbers.txt
sera énorme, il y a des problèmes de performances.
package main
import (
"bufio"
"fmt"
"os"
)
func yield(fp *os.File) chan string {
ch := make(chan string)
go func() {
defer close(ch)
scanner := bufio.NewScanner(fp)
for scanner.Scan() {
ch <- scanner.Text()
}
if err := scanner.Err(); err != nil {
panic(err)
}
} ()
return ch
}
func main() {
fp, err := os.Open("numbers.txt")
if err != nil {
panic(err)
}
defer fp.Close()
i := 0
for s := range(yield(fp)) {
fmt.Printf("%d:%s\n", i, s)
i++
}
}
Il peut y avoir un moyen de synchroniser avec sync.Mutex
.
package main
import (
"bufio"
"fmt"
"os"
)
func yield(fp *os.File) func() (bool, string) {
scanner := bufio.NewScanner(fp)
return func() (bool, string) {
t := scanner.Scan()
if err := scanner.Err(); err != nil {
panic(err)
}
return t, scanner.Text()
}
}
func main() {
fp, err := os.Open("numbers.txt")
if err != nil {
panic(err)
}
defer fp.Close()
y := yield(fp)
for i := 0;;i++ {
t, s := y()
if !t { break }
fmt.Printf("%d:%s\n", i, s)
}
}
Ruby a aussi yield
, mais c'est une définition de fonction qui reçoit des blocs au lieu d'un générateur comme PHP / Python. Il y a ʻEnumerator` comme fonction équivalente au générateur PHP / Python, et il est décrit comme suit.
def my_generator(name)
return to_enum(__method__, name) unless block_given?
IO.foreach(name) do |line|
yield(line.chomp)
end
end
g = my_generator('numbers.txt')
g.with_index { |l, i| p '%d:%s' % [i, l] }
Ici, s'il y a un bloc, le bloc est traité, et s'il n'y a pas de bloc, il peut être traité comme une méthode qui renvoie Enumerator.
Recommended Posts