Skip to content

"Alternatively" gives unexpected behaviour #11

@tom-lord

Description

@tom-lord
def alternatively(value = nil)
  @prefixes += "(?:" unless @prefixes.include?("(")
  @suffixes = ")" + @suffixes unless @suffixes.include?(")")
  add(")|(?:")
  find(value) if value
end

I don't like this abuse of the @prefixes and @suffixes. Especially given that we also have the methods:

def start_of_line(enable = true)
  @prefixes = '^' if enable
end

def end_of_line(enable=true)
  @suffixes = '$' if enable
end

For example, the following code creates an invalid RegEx:

VerEx.new do
  find 'a'
  alternatively
  find 'b'
  end_of_line
end

(The @suffixes gets overwritten by end_of_line, so we are left with a trailing bracket.)

There were two possible solutions to this: Fix the end_of_line method by using += rather than just =, or (what I chose to do instead):

def start_of_line
  add('^')
end

def end_of_line
  add('$')
end

This gives the important added benefit that we can now match start/end of lines in the middle of strings!


However, with the new code I wrote, we can still end up with slightly unexpected behaviour such as:

VerEx.new do
  start_of_line
  find 'a'
  alternatively
  find 'b'
end
#=> /(?:^a)|(?:b)

Rather than ^(?:a)|(?:b)/, as one might expect. In order to achieve this, our VerEx would have needed to be:

VerEx.new do
  start_of_line
  find 'a'
  alternatively
  start_of_line
  find 'b'
end
#=> /(?:^a)|(?^:b)

This is a slight change in behaviour.
Basically, to cut a long story short, this alternatively method may be simple and powerful, but must be used with caution. A little usage example, such as the one I gave above, would be a good idea for the README.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions