{"action":"opened","issue":{"url":"https://api.github.com/repos/dylanninin/dylanninin.github.com/issues/1","repository_url":"https://api.github.com/repos/dylanninin/dylanninin.github.com","labels_url":"https://api.github.com/repos/dylanninin/dylanninin.github.com/issues/1/labels{/name}","comments_url":"https://api.github.com/repos/dylanninin/dylanninin.github.com/issues/1/comments","events_url":"https://api.github.com/repos/dylanninin/dylanninin.github.com/issues/1/events","html_url":"https://github.com/dylanninin/dylanninin.github.com/issues/1","id":167793042,"number":1,"title":"Closures in Ruby","user":{"login":"dylanninin","id":550518,"avatar_url":"https://avatars.githubusercontent.com/u/550518?v=3","gravatar_id":"","url":"https://api.github.com/users/dylanninin","html_url":"https://github.com/dylanninin","followers_url":"https://api.github.com/users/dylanninin/followers","following_url":"https://api.github.com/users/dylanninin/following{/other_user}","gists_url":"https://api.github.com/users/dylanninin/gists{/gist_id}","starred_url":"https://api.github.com/users/dylanninin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dylanninin/subscriptions","organizations_url":"https://api.github.com/users/dylanninin/orgs","repos_url":"https://api.github.com/users/dylanninin/repos","events_url":"https://api.github.com/users/dylanninin/events{/privacy}","received_events_url":"https://api.github.com/users/dylanninin/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/dylanninin/dylanninin.github.com/labels/note","name":"note","color":"fbca04"},{"url":"https://api.github.com/repos/dylanninin/dylanninin.github.com/labels/wiki","name":"wiki","color":"bfd4f2"}],"state":"open","locked":false,"assignee":{"login":"dylanninin","id":550518,"avatar_url":"https://avatars.githubusercontent.com/u/550518?v=3","gravatar_id":"","url":"https://api.github.com/users/dylanninin","html_url":"https://github.com/dylanninin","followers_url":"https://api.github.com/users/dylanninin/followers","following_url":"https://api.github.com/users/dylanninin/following{/other_user}","gists_url":"https://api.github.com/users/dylanninin/gists{/gist_id}","starred_url":"https://api.github.com/users/dylanninin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dylanninin/subscriptions","organizations_url":"https://api.github.com/users/dylanninin/orgs","repos_url":"https://api.github.com/users/dylanninin/repos","events_url":"https://api.github.com/users/dylanninin/events{/privacy}","received_events_url":"https://api.github.com/users/dylanninin/received_events","type":"User","site_admin":false},"assignees":[{"login":"dylanninin","id":550518,"avatar_url":"https://avatars.githubusercontent.com/u/550518?v=3","gravatar_id":"","url":"https://api.github.com/users/dylanninin","html_url":"https://github.com/dylanninin","followers_url":"https://api.github.com/users/dylanninin/followers","following_url":"https://api.github.com/users/dylanninin/following{/other_user}","gists_url":"https://api.github.com/users/dylanninin/gists{/gist_id}","starred_url":"https://api.github.com/users/dylanninin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dylanninin/subscriptions","organizations_url":"https://api.github.com/users/dylanninin/orgs","repos_url":"https://api.github.com/users/dylanninin/repos","events_url":"https://api.github.com/users/dylanninin/events{/privacy}","received_events_url":"https://api.github.com/users/dylanninin/received_events","type":"User","site_admin":false}],"milestone":null,"comments":0,"created_at":"2016-07-27T07:54:10Z","updated_at":"2016-07-27T07:54:10Z","closed_at":null,"body":"## Closure\r\n\r\n### Definition\r\n\r\n> In programming languages, closures (also lexical closures or function closures) are techniques for implementing lexically scoped name binding in languages with first-class functions. Operationally, **a closure is a record storing a function[a] together with an environment:[1] a mapping associating each free variable of the function** (variables that are used locally, but defined in an enclosing scope) with the value or reference to which the name was bound when the closure was created.[b] **A closure—unlike a plain function—allows the function to access those captured variables through the closure's copies of their values or references, even when the function is invoked outside their scope.**\r\n\r\n### Application\r\n\r\n> Closures are used to implement continuation-passing style, and in this manner, hide state. Constructs such as objects and control structures can thus be implemented with closures. In some languages, a closure may occur when a function is defined within another function, and the inner function refers to local variables of the outer function. At run-time, when the outer function executes, a closure is formed, consisting of the inner function’s code and references (the upvalues) to any variables of the outer function required by the closure.\r\n\r\n- First-class functions\r\n- State representation\r\n- Define control structure for closures' delay evaluation\r\n- Communicate privately by altering that environment\r\n\r\n## Closures in Ruby\r\n\r\n### Blocks\r\n\r\nA code block is a set of Ruby statements and expressions between braces or a do/end pair. \r\n- The block may start with an argument list between vertical bars. \r\n- A code block may appear only immediately after a method invocation. \r\n- The start of the block (the brace or the do) must be on the same logical source line as the end of the invocation.\r\n- Braces have a high precedence; do has a low precedence. \r\n  - If the method invocation has parameters that are not enclosed in parentheses, the brace form of a block will bind to the last parameter, not to the overall invocation. The do form will bind to the invocation.\r\n- blocks example\r\n\r\n```ruby\r\ninvocation do | a1, a2, ... | \r\nend\r\n\r\ninvocation { | a1, a2, ... | }\r\n```\r\n- Within the body of the invoked method, the code block may be called using the yield keyword.\r\n- Parameters passed to yield will be assigned to arguments in the block.\r\n- A warning will be generated if yield passes multiple parameters to a block that takes just one.\r\n- The return value of the yield is the value of the last expression evaluated in the block or the value passed to a next statement executed in the block.\r\n\r\n**block arguments**\r\n\r\nBlocks argument lists are very similar to method argument lists:\r\n- You can specify default values.\r\n- You can specify splat (starred) arguments.\r\n- The last argument can be prefixed with an ampersand, in which case it will collect any block passed when the original block is called.\r\n- Block-local variables are declared by placing them after a semicolon in the argument list.\r\n\r\n**Proc Objects**\r\n\r\nRuby’s blocks are chunks of code attached to a method. Blocks are not objects, but they can be converted into objects of class Proc.\r\n- By passing a block to a method whose last parameter is prefixed with an ampersand. That parameter will receive the block as a Proc object.\r\n- By calling `Proc.new`, again associating it with a block\r\n- By calling the method `Object#lambda`, associating a block with the call.\r\n- Using the `->` syntax.\r\n\r\nThe first two styles of Proc object are identical in use. We’ll call these objects raw procs. The third and fourth styles, generated by lambda and ->, add some functionality to the Proc object, as we’ll see in a minute. We’ll call these objects lambdas.\r\n\r\nHere’s the big thing to remember: raw procs are basically designed to work as the bodies of control structures such as loops. Lambdas are intended to act like methods. So, lambdas are stricter when checking the parameters passed to them, and a return in a lambda exits much as it would from a method.\r\n\r\n**calling a Proc**\r\n\r\nYou call a proc by invoking its methods `call`, `yield`, or `[]`. \r\n- The three forms are identical. \r\n- Each takes arguments that are passed to the proc, just as if it were a regular method. \r\n- If the proc is a lambda, Ruby will check that the number of supplied arguments match the expected parameters. \r\n- You can also invoke a proc using the syntax `name.(args...)`. This is mapped internally into `name.call(args...)`.\r\n\r\n**Procs, break, and next**\r\n\r\nWithin both raw procs and lambdas, executing `next` causes the block to exit back to the caller of the block. The return value is the value (or values) passed to `next`, or `nil` if no values are passed.\r\n\r\n```ruby\r\ndef ten_times \r\n  10.times do |i|\r\n    if yield(i)\r\n        puts \"Caller likes #{i}\"\r\n    end \r\n  end\r\nend\r\n\r\nten_times do |number| \r\n    next(true) if number ==7\r\nend\r\n\r\n# => Caller likes 7\r\n# 10\r\n```\r\n\r\nWithin a raw proc, a break terminates the method that invoked the block. The return value of the method is any parameters passed to the break.\r\n\r\n```ruby\r\nten_times do |number| \r\n    break(true) if number ==7\r\nend\r\n# => \r\n# true\r\n```\r\n\r\n**Return and Blocks**\r\n\r\nA return from inside a raw block that’s still in scope acts as a return from that scope. A return from a block whose original context is no longer valid raises an exception (LocalJumpError or ThreadError depending on the context).\r\n\r\n```ruby\r\ndef meth1\r\n   (1..10).each do |val|\r\n      return val \r\n  end\r\nend\r\n\r\nmeth1 # => 1\r\n```\r\n\r\nThe following example shows a return failing because the context of its block no longer\r\nexists\r\n\r\n```ruby\r\ndef meth2(&b) \r\n  b\r\nend\r\n\r\nres = meth2 { return }\r\nres.call\r\n\r\n# produces:\r\n#        from prog.rb:6:in `call'\r\n#       from prog.rb:6:in `<main>'\r\n# prog.rb:5:in `block in <main>': unexpected return (LocalJumpError)\r\n```\r\n\r\nAnd here’s a return failing because the block is created in one thread and called in another:\r\n\r\n```ruby\r\ndef meth3\r\n  yield\r\nend\r\n\r\nt = Thread.new do \r\n  meth3 { return }\r\nend\r\n\r\nt.join\r\n\r\n# produces:\r\n#        from prog.rb:2:in `meth3'\r\n#        from prog.rb:6:in `block in <main>'\r\n# prog.rb:6:in `block (2 levels) in <main>': unexpected return (LocalJumpError)\r\n```\r\n\r\nThis is also true if you create the raw proc using Proc.new.\r\n\r\n```ruby\r\ndef meth4 \r\n  p = Proc.new { return 99 }\r\n  p.call\r\n  puts \"Never get here\"\r\nend\r\n\r\nmeth4 # => 99\r\n```\r\n\r\nA lambda behaves more like a free-standing method body: a return simply returns from the block to the caller of the block:\r\n\r\n```ruby\r\ndef meth5\r\n    p = lambda { return 99 } \r\n    res = p.call\r\n    \"The block returned #{res}\"\r\nend\r\nmeth5 # => \"The block returned 99\"\r\n```\r\n\r\nBecause of this, if you use `Module#define_method`, you’ll probably want to pass it a proc created using `lambda`, not `Proc.new`, because return will work as expected in the former and will generate a `LocalJumpError` in the latter.\r\n\r\n### Blocks and Closures\r\n\r\nA block is a closure:\r\n- it remembers the context in which it was defined, and it uses that context whenever it is called. \r\n- the context includes the value of self, the constants, the class variables, the local variables, and any captured block.\r\n\r\n```ruby\r\ndef n_times(thing)\r\n  lambda {|n| thing * n}\r\nend\r\n\r\np1 = n_times(23)\r\np1.call(3) # => 69\r\np1.call(4) # => 92\r\n\r\np2 = n_times(\"hello \")\r\np2.call(3) # => \"hello hello hello \"\r\n```\r\n\r\nThe method `n_times` returns a `Proc` object that references the method’s parameter, `thing`. Even though that parameter is out of scope by the time the block is called, the parameter remains accessible to the block. This is called a `closure`—variables in the surrounding scope that are referenced in a block remain accessible for the life of that block and the life of any Proc object created from that block.\r\n\r\n\r\n## Reference\r\n\r\nHere list all the references\r\n- https://en.wikipedia.org/wiki/Closure_(computer_programming)\r\n- https://pragprog.com/book/ruby4/programming-ruby-1-9-2-0"}}
{"actor":{"display_login":"dylanninin"}}