From: Ruby-Lang@... Date: 2017-01-25T03:28:32+00:00 Subject: [ruby-core:79260] [Ruby trunk Feature#12901] Anonymous functions without scope lookup overhead Issue #12901 has been updated by J��rg W Mittag. I have thought about this a number of times, but never got around to writing a feature request: we already have a way to tell Ruby that we don't want to capture certain variables from the surrounding scope: block local variables. We also have "wildcard" syntax for block parameters. So, let's just combine the two, to tell Ruby that we don't want to capture any variables: Proc.new {|a, b:, *c; d, e, *| } # or -> (a, b:, *c; d, e, *) {} This will make `d` and `e` block local variables, and make the block not close over the surrounding environment. This is a conservative extension of existing syntax. We can even further extend it to provide a "whitelist" of variables to capture: Proc.new {|a, b:, *c; d, e, *; f, g| } # or -> (a, b:, *c; d, e, *; f, g) {} This will make it an error if there are no local variables named `f` and `g` in the surrounding scope. The *current* behavior would then be equivalent to: Proc.new {|a, b:, *c;; *| } # or -> (a, b:, *c;; *) {} I.e.: no block local variables, capture all variables. We will need to make a decision, though, as to whether this should include lexical binding of `self` or not. We could easily allow both explicit opt-out and explicit opt-in by allowing `self` as a legal identifier in the parameter list. E.g. a block that captures no variables, but *does* capture `self` would be declared like: Proc.new {|a, b:, *c;* ; self| } # or -> (a, b:, *c; *; self) {} A block that captures all variables but does not capture `self`: Proc.new {|a, b:, *c;self ; *| } # or -> (a, b:, *c; self; *) {} and a block that captures *nothing*: Proc.new {|a, b:, *c;*, self| } # or -> (a, b:, *c; *, self) {} An open question is: what should the default for capturing `self` be, when there is only a wildcard, i.e. these two cases: Proc.new {|a, b:, *c;; *| } # or -> (a, b:, *c;; *) {} Proc.new {|a, b:, *c; *| } # or -> (a, b:, *c; *) {} I have no preference either way. ---------------------------------------- Feature #12901: Anonymous functions without scope lookup overhead https://bugs.ruby-lang.org/issues/12901#change-62674 * Author: Richard Schneeman * Status: Open * Priority: Normal * Assignee: * Target version: ---------------------------------------- Right now if you are writing performance sensitive code you can get a performance bump by not using anonymous functions (procs, lambdas, blocks) due to the scope lookup overhead. https://twitter.com/apotonick/status/791167782532493312?lang=en I would like to be able to create an anonymous function and specify I don't need it to perform the lookup when called. I am thinking that this code: ~~~ Proc.new(scope: false) {|var| puts var } ~~~ Would be the equivalent of ~~~ def anon(var) puts var end ~~~ If you call it while trying to access something from outside of the scope it would error ~~~ var = "hello" Proc.new(scope: false) { puts var }.call # => NameError: undefined local variable or method `var' for main:Object ~~~ An example of a case where this could be used is found in https://github.com/rails/sprockets/pull/417. In this case we are getting rid of anonymous functions in favor of a method created with refinements. This solution works but it was not an obvious optimization. It would be convenient to have a syntax for defining anonymous functions that do not need access to caller scope. -- https://bugs.ruby-lang.org/ Unsubscribe: