エレファント・コンピューティング調査報告

極限に関する順序を論理プログラミングの手法を使って指定することを目指すブロクです。

関数プログラミングと無限論理多項式(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)
}

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