From: David Flanagan Date: 2007-12-22T03:43:43+09:00 Subject: Re: named captures assigning to local variables David A. Black wrote: > Hi -- > > On Fri, 21 Dec 2007, David Flanagan wrote: > >> Attached is a variation on my patch that makes it return $~ instead of >> an array of values. In testing this I remembered that $~[0] is the >> entire string on the right-hand side, rather than the first captured >> value, so this return value doesn't actually masquerade as an array of >> the assigned values. So I'm a little less enthusiastic about this >> return value. > > I'm still wondering about making such a big exception to the usual > rhs-returning behavior. Let me make clear that I proposed this assignment syntax as an alternative to the current behavior in which the =~ operator does magic assignment to local variables, but only if the left-hand side is a regexp literal. That seems to me to be a very bad idea. I'm not at all convinced that the assignment syntax is a good idea, but I'm convinced that it is better than the =~ syntax. Akr's objection to returning the right-hand side string with this syntax is that it doesn't allow use in a conditional to test success or failure. One solution is to raise an exception if no match is found. On the theory that if you're using this syntax you must be really pretty sure that there are values to extract from the string. But I might also advocate for dropping both the = and =~ syntaxes for now and thinking about this some more for Ruby 2.0 Here one possible alternative: Ruby 1.9 now allows a block to be associated with a call to match, and passes MatchData on a successful match. Could we make the named captures into local variables of the block? (If so, I might propose the same thing for the blocks associated with sub and gsub). So this code: r = /(?.)(?.)/ r.match(s) {|data| ...} would act like this: r.match(s) { |data;foo,bar| foo = data[:foo] bar = data[:bar] ... } And if this isn't restricted to regexp literals, I don't know how to handle warnings about shadowed variables: would they be dynamically generated at ruime? I assume that the ultimate goal of all this is to make it really easy to refer to the value of named captures. I agree with the goal, but am not sure about the automatic assignment to variables. Here's another possiblity that doesn't involve variables at all: class Symbol def ~ $~[self] end end Then, after any match operation, refer to the value of a named capture as ~:foo. Almost as simple to type as a real local variable, but without the magic. And it is not restricted to literals or any particular matching syntax. The only problem: my Symbol.~ method above doesn't work since $~ is a magic method-local variable. I assume that if it were implemented in C, however, it could access the value it needs based on the call stack. Another option: give MatchData a method_missing method so that named captures can be used as method names: $~.foo would be the same as $~[:foo]. But MatchData probably already has too many existing method names to make this viable. Maybe even simpler, and more in line with existing Perl-style regexp magic: assign named captures to global variables. For a capture named foo, set $~foo. Its kind of ugly, but it is consistent. David