From: "Eregon (Benoit Daloze) via ruby-core" Date: 2024-03-19T20:01:58+00:00 Subject: [ruby-core:117235] [Ruby master Feature#20349] Pattern Matching - Expose local variable captures Issue #20349 has been updated by Eregon (Benoit Daloze). This would make every pattern matching a lot slower which seems a big no-no performance wise. I think that's enough to reject this proposal. Because it would force to create that binding/Hash eagerly in case `PatternMatch.last_match` is used later. Actually, `$~`/`Regexp.last_match` and `$_` are already causing significant performance problems for Ruby implementations, so I am strongly against any more of these "magically create variables in the caller". BTW the example doesn't show how this is useful, is it to print the current state for debugging? If so a helper method taking a `binding` seems appropriate (called inside the `longform_block?` method, not outside). ---------------------------------------- Feature #20349: Pattern Matching - Expose local variable captures https://bugs.ruby-lang.org/issues/20349#change-107322 * Author: baweaver (Brandon Weaver) * Status: Open ---------------------------------------- In Regular Expressions we have the ability to utilize `Regexp.last_match` ([link](https://ruby-doc.org/3.2.2/Regexp.html#method-c-last_match)) to access the most recent match data from a regular expression match. I would like to propose that we have similar functionality for pattern matching: ```ruby require "rubocop" def ast_from(string) case string when String then processed_source_from(string).ast when RuboCop::ProcessedSource then string.ast when RuboCop::AST::Node then string else nil end end def longform_block?(node) node in [:block, # s(:block, [:send, target, target_method], # s(:send, s(:array), :select), [[:arg, v]], # s(:args, s(:arg, :v)), [:send, [:lvar, ^v], block_method] # s(:send, s(:lvar, :v), :even?)) ] end longform_block?(ast_from("[1, 2, 3].select { |v| v.even? }")) # => true # Name is not important, idea is, name can be debated. `source` is used to not # show AST nodes PatternMatch.last_match.transform_values(&:source) # => {:node=>"[1, 2, 3].select { |v| v.even? }", # :result=>"[1, 2, 3].select { |v| v.even? }", # :target=>"[1, 2, 3]", # :target_method=>:select, # :v=>:v, # :block_method=>:even?} # Hacky version to show how / where behavior could be captured def longform_block?(node) result = node in [:block, # s(:block, [:send, target, target_method], # s(:send, s(:array), :select), [[:arg, v]], # s(:args, s(:arg, :v)), [:send, [:lvar, ^v], block_method] # s(:send, s(:lvar, :v), :even?)) ] pp(binding.local_variables.to_h { [_1, binding.local_variable_get(_1).then { |s| s.source rescue s }] }) result end ``` -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/