2

ドキュメントからこの例を取り上げるとyield、関数から値を受け取るブロックを送信できます。

def twice
  yield 1
  yield 2
end

twice do |i|
  puts i
end

私が疑問に思っているのは、関数を手動で呼び出して、最初の呼び出しで1他のことを行い、次の呼び出しで2.

私は(ちょうど推測して)さまざまなことを試しputs twice()ましたが、役に立ちませんでした。これを行う方法はありますか?

4

1 に答える 1

4

スポーンとチャネルを使用できます。これはあなたが得ることができる最も近いものです:

def foo
  yield 1
  yield 2
end

chan = Channel(typeof(foo { |x| x })).new

spawn do
  foo do |x|
    chan.send x
  end
  chan.close
end

p chan.receive?
p chan.receive?
p chan.receive?

http://play.crystal-lang.org/#/r/ijd

おそらくマクロを使用して、それを抽象化することができます。

def foo
  yield 1
  yield 2
end

macro enumerator(call)
  %chan = Channel(typeof({{call}} { |x| x })).new
  spawn do
    {{call}} do |x|
      %chan.send x
    end
    %chan.close
  end
  %chan
end

values = enumerator(foo)

p values.receive?
p values.receive?
p values.receive?

http://play.crystal-lang.org/#/r/ije

そして、おそらくラッパー構造体を使用しているため、イテレーター ( http://crystal-lang.org/api/Iterator.html )のように見えます。ただし、これは少し遅いことに注意してください。少なくとも、反復子または通常のキャプチャされていないブロック呼び出しを使用するよりもはるかに遅いです。

于 2015-10-10T14:06:18.833 に答える