{"id":7037,"date":"2014-05-17T00:23:51","date_gmt":"2014-05-17T00:23:51","guid":{"rendered":"https:\/\/unknownerror.org\/index.php\/2014\/05\/17\/returning-from-ruby-blocks-outside-of-their-original-scope-collection-of-common-programming-errors\/"},"modified":"2014-05-17T00:23:51","modified_gmt":"2014-05-17T00:23:51","slug":"returning-from-ruby-blocks-outside-of-their-original-scope-collection-of-common-programming-errors","status":"publish","type":"post","link":"https:\/\/unknownerror.org\/index.php\/2014\/05\/17\/returning-from-ruby-blocks-outside-of-their-original-scope-collection-of-common-programming-errors\/","title":{"rendered":"Returning from ruby blocks outside of their original scope-Collection of common programming errors"},"content":{"rendered":"<p>I wanted to make something that looks like this:<\/p>\n<pre><code>def make_wrapped_block(&amp;block)\n  puts \"take_block:before\"\n  func = lambda do\n    puts \"Before calling make_wrapped_block's passed block\"\n    block.call\n    puts \"After calling make_wrapped_block's passed block\"\n  end\n  puts \"take block:after\"\n  func\nend\n\ndef make_block\n  make_wrapped_block do\n    puts \"Before return\"\n    return :pi\n    puts \"After return\"\n  end\nend\n\nmake_block.call\n<\/code><\/pre>\n<p>..where there would be many <code>make_block<\/code> methods which generate closures with similar initialization and cleanup provided by <code>make_wrapped_block<\/code>.<\/p>\n<p>Because the block passed to <code>make_wrapped_block<\/code> in <code>make_block<\/code> returns, this causes a LocalJumpError:<\/p>\n<pre><code>[ cpm juno ~\/tmp\/local-jump ] ruby bad.rb\ntake_block:before\ntake block:after\nBefore calling make_wrapped_block's passed block\nBefore return\nbad.rb:15:in `make_block': unexpected return (LocalJumpError)\n        from bad.rb:5:in `call'\n        from bad.rb:5:in `make_wrapped_block'\n        from bad.rb:20:in `call'\n        from bad.rb:20\n<\/code><\/pre>\n<p>Now, I can get this idea to work with a slightly different syntax:<\/p>\n<pre><code>def make_wrapped_block(block)\n  puts \"take_block:before\"\n  func = lambda do\n    puts \"Before calling make_wrapped_block's passed block\"\n    block.call\n    puts \"After calling make_wrapped_block's passed block\"\n  end\n  puts \"take block:after\"\n  func\nend\n\ndef make_block\n  make_wrapped_block(lambda {\n    puts \"Before return\"\n    return :pi\n    puts \"After return\"\n  })\nend\n\nmake_block.call\n<\/code><\/pre>\n<p>This works because when you return from an anonymous function created with <code>lambda<\/code>, it exits the anonymous function, while with <code>Proc.new<\/code> and anonymous blocks it tries to return from the scope it was defined in. You can&#8217;t pass them around and return safely.<\/p>\n<p><strong>Is there a safe way to return from passed blocks outside of the scope they were created?<\/strong><br \/>\nThe second way works well enough, but the syntax is a bit uglier than the first version.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I wanted to make something that looks like this: def make_wrapped_block(&amp;block) puts &#8220;take_block:before&#8221; func = lambda do puts &#8220;Before calling make_wrapped_block&#8217;s passed block&#8221; block.call puts &#8220;After calling make_wrapped_block&#8217;s passed block&#8221; end puts &#8220;take block:after&#8221; func end def make_block make_wrapped_block do puts &#8220;Before return&#8221; return :pi puts &#8220;After return&#8221; end end make_block.call ..where there would be [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-7037","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/7037","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/comments?post=7037"}],"version-history":[{"count":0,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/7037\/revisions"}],"wp:attachment":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/media?parent=7037"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/categories?post=7037"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/tags?post=7037"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}