エレファント・ビジュアライザー調査記録

ビジュアルプログラミングで数式の変形を表すことを考えていくブロクです。

関数プログラミングと無限論理多項式(14)

Go の例(2) (ゴルーチン)

次にゴルーチンを使ったものを考えます。GenerateDecimal をゴルーチンを使って以下のように書き直します。これはクロージャーを使っているのでクロージャーの代わりにゴルーチンを使っているわけではありません。

func (xyz *NumbersGenerator) GenerateDecimal() *IteratorSimpleImpl_int {
	current_digit := 0
	ch := make(chan int)
	coBody := func(ch chan int) {
		number := newLongDecimal([]int{})
		square_difference := newLongDecimal([]int{3})
		nums := newNumbers(number, square_difference, 0)
		for {
			ch <- nums.GetNextDecimalDigit()
		}
	}
	go coBody(ch)
	next := func() bool {
		val, ok := <-ch
		current_digit = val
		return ok
	}
	getCurrent := func() int {
		return current_digit
	}
	setCurrent := func(val int) {
	}
	return newIteratorSimpleImpl_int(next, getCurrent, setCurrent)
}

次にクロージャーを使わないように書き直します。チャネルを使ってイテレーターを実現する IteratorChannelImpl_int を作ります。

type IteratorChannelImpl_int struct {
	ch            chan int
	current_digit int
}

func newIteratorChannelImpl_int(ch chan int) *IteratorChannelImpl_int {
	xyz := new(IteratorChannelImpl_int)
	xyz.ch = ch
	xyz.current_digit = 0
	return xyz
}
func (xyz *IteratorChannelImpl_int) GetCurrent() int {
	return xyz.current_digit
}
func (xyz *IteratorChannelImpl_int) SetCurrent(value int) {
	xyz.ch <- value
}
func (xyz *IteratorChannelImpl_int) MoveNext() bool {
	val, ok := <-xyz.ch
	xyz.current_digit = val
	return ok
}
func (xyz *IteratorChannelImpl_int) Take(count int) []int {
	res := make([]int, count)
	iter := xyz
	for i := 0; i < count && iter.MoveNext(); i++ {
		res[i] = iter.GetCurrent()
	}
	return res
}

NumbersGenerator を IteratorChannelImpl_int を使うように書き直します。これでクロージャーを使わない(一部)バージョンができました。

type NumbersGenerator struct {
	generator *IteratorChannelImpl_int
}

func newNumbersGenerator() *NumbersGenerator {
	xyz := new(NumbersGenerator)
	xyz.generator = xyz.GenerateDecimal()
	return xyz
}
func (xyz *NumbersGenerator) GetNextDecimalDigit() int {
	xyz.generator.MoveNext()
	return xyz.generator.GetCurrent()
}

func (xyz *NumbersGenerator) GenerateDecimal() *IteratorChannelImpl_int {
	ch := make(chan int)
	coBody := func(ch chan int) {
		number := newLongDecimal([]int{})
		square_difference := newLongDecimal([]int{3})
		nums := newNumbers(number, square_difference, 0)
		for {
			ch <- nums.GetNextDecimalDigit()
		}
	}
	go coBody(ch)
	return newIteratorChannelImpl_int(ch)
}

まだクロージャーを使っているところがあるので今後検討していきます。