Crystal: Sending a block to Regex#match gots error

Created on 19 Jun 2016  路  13Comments  路  Source: crystal-lang/crystal

In API docs:

/a(sd)f/.match("_asdf_")                          # => #<Regex::MatchData "asdf" 1:"sd">
/a(sd)f/.match("_asdf_") { |md| md[1] }           # => "sd"

But now (0.18.2) is doesn't support for block and will get the error:

Regex#match' is not expected to be invoked with a block, but a block was given
bug docs

Most helpful comment

And as I pointed out you can still do .match(pat).try {|m| ... }.

All 13 comments

I think this is a doc bug and the second call is meant to be a sub or gsub.

@jhass but match is not for replace right?
IMO, the second call means "if it's matched, do something", and it will promise that will pass a MatchData to the block or just return nil from #match (not calling the block)

If it would then the #=> "sd" is entirely wrong too.

I think #match(..., &block) returns nil or what the block returned.

@jhass If that means to replace something, the return value will be _sd_ not sd, I think

No it would replace the entire match. The match overload you describe would be redundant to match(...).try { ... }

Ruby implements as the same to match(...).try {...}.

I think we can just remove these words from api docs is fine.

I think it's String#match what should be used in those examples, which does have an overload that accepts a block.

Oh, if we do have a String#match overload that does then we should have one for Regex too, out of consistency. I wouldn't mind dropping the String#match overload though...

The only reason the block version in Ruby exists, according to the docs, is so you can do this:

str.match(pat) {|m| ...}

instead of this:

if m = str.match(pat)
  ...
end

But since the second form is more or less an idiom in Crystal, I think dropping the block form should be fine.

And as I pointed out you can still do .match(pat).try {|m| ... }.

The problem I have with this change is now there is no way to do matching without overwriting $~. A bit of a weird way to do things, but still...

if "a" =~ /a/
  "b".match /b/ do |m|
    p m[0]
  end
end
p $~[0]

puts "--------"

if "a" =~ /a/
  if m = "b".match /b/
    p m[0]
  end
end
p $~[0]
"b"
"a"
--------
"b"
"b"

https://carc.in/#/r/13le

Also an interesting moment: match is basically an alias to =~.

I would prefer match not to overwrite $~.

I don't think $~ should be used when nesting matches, I'd only use it in simple cases like:

if foo =~ bar
  # use $~
end

or in a case expression. For more complex things I'd use match and keep the match in a variable.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

asterite picture asterite  路  3Comments

ArthurZ picture ArthurZ  路  3Comments

TechMagister picture TechMagister  路  3Comments

Papierkorb picture Papierkorb  路  3Comments

Sija picture Sija  路  3Comments