Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Passing blocks around returning value #4605

Closed
TPei opened this issue Jun 22, 2017 · 1 comment
Closed

Passing blocks around returning value #4605

TPei opened this issue Jun 22, 2017 · 1 comment

Comments

@TPei
Copy link

TPei commented Jun 22, 2017

Hey, I'm passing a block around but for some reason, the initially called method never gets a return value. I'm not sure if / what I am doing wrong. I tried different things:

class SomeClass
  # some methods omitted
  def self.wait_for(&block)
    self.new.wait_for &block
  end

  def wait_for
    create_spinner_fiber
    value = yield
    @finished = true
    value
  end
end

I also tried:

class SomeClass
  def self.wait_for(&block)
    self.new.wait_for { block.call }
  end

  def wait_for
    create_spinner_fiber
    value = yield
    @finished = true
    value
  end
end

Calling SomeClass.wait_for { 1 } always returns nil, while SomeClass.new.wait_for { 1 } returns 1

Crystal 0.22.0 [3c71228] (2017-04-20) LLVM 3.5.0

@bew
Copy link
Contributor

bew commented Jun 22, 2017

You must specify the block's return type if you want to get a value back from a captured block:

class SomeClass
  def self.wait_for(&block : -> Int32)
    new.wait_for &block
  end

  def wait_for
    value = yield
    @finished = true
    value
  end
end

puts SomeClass.wait_for { 1 }

https://carc.in/#/r/28nh

This is fully documented in the docs: https://crystal-lang.org/docs/syntax_and_semantics/capturing_blocks.html

You should also look at: https://crystal-lang.org/docs/syntax_and_semantics/block_forwarding.html

Try to avoid forwarding blocks like this if doing yield is enough.

Your example can be rewritten without block capture as:

class SomeClass
  def self.wait_for
    new.wait_for { yield }
  end

  def wait_for
    value = yield
    @finished = true
    value
  end
end

puts SomeClass.wait_for { 1 }

https://carc.in/#/r/28ni

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants