Meaning of '!(...' EG: "myObject.parse!(argv)" ..?

Hi there,

QUESTION:
Whilst “parse(argv)” is obvious, what does “opts.parse!(argv)” do in the
below code? And what is the word use to describe doing this?

CONTEXT:
I am looking at a class called ‘Options’ whose job is to parse command
line options which get passed to a program called ‘PartInspector’. An
extract of this class follows:

class Options

def initialize(argv)
@directory = DEFAULT_DIR
parse(argv)
end

private
def parse(argv)
OptionParser.new do |opts|
opts.banner = “Usage: PartInspector [part_number]”

  opts.on("-h", "Shows this message") do
    puts opts
    exit
  end

  begin
    argv = ["-h"] if argv.empty?
    opts.parse!(argv)                          ## <------- HERE?!!?!
    rescue OptionParser::ParseError => e
      STDERR.puts e.message, "\n", opts
  end
end#def parse()

end#private class

end#option class

I know its probably some basic syntax for ruby, not knowing what it is
called however makes it difficult to look it up.

Thank-you in advance, Michelle

On Nov 16, 2009, at 22:15 , Michelle P. wrote:

QUESTION:
Whilst “parse(argv)” is obvious, what does “opts.parse!(argv)” do in the
below code? And what is the word use to describe doing this?

it is just an argument list. nothing fancy. “!” is valid as part of the
method name, that’s all.

Ryan D. wrote:

it is just an argument list. nothing fancy. “!” is valid as part of the
method name, that’s all.

Thanks for your reply Ryan… I’m surprised! So… are you saying that
the method calls

     opts.parse!(argv)   and     opts.parse(argv)

effectively do the same thing?

Michelle P. wrote:

Thanks for your reply Ryan… I’m surprised! So… are you saying that
the method calls

     opts.parse!(argv)   and     opts.parse(argv)

effectively do the same thing?

Section 6.2 of “The Ruby P.ming Language” by Flanagan & Matsumoto,
explains that a method that ends with an exclamation mark is a naming
convention indicating to the programmer that the method “should be used
with caution.”

It goes on to explain that most of the time this is due to the fact that
the method is a mutator; a method that alters the internal state of the
object.

On Nov 16, 2009, at 23:04 , Michelle P. wrote:

Ryan D. wrote:

it is just an argument list. nothing fancy. “!” is valid as part of the
method name, that’s all.

Thanks for your reply Ryan… I’m surprised! So… are you saying that
the method calls

    opts.parse!(argv)   and     opts.parse(argv)

effectively do the same thing?

Are they both plain happy method calls? Yes. If by “do the same thing”
you mean call the same method, then no.

They are both equivalent to:

opts.send(:parse!, argv)

and

opts.send(:parse, argv)

respectively.

‘parsew’ and ‘parse’. But if thats true… then in my orginal code
above, there wasn’t a ‘parse!’ method defined.


Posted via http://www.ruby-forum.com/.

I think you’ve got it. Basically parse!, and I mean all of it including
the exclamation mark, is a method defined separately from parse. In your
options class, they might look like this:

class Options
def parse!(argv)

parsing code

end
def parse(argv)
opts = self.dup
opts.parse!(argv)
end
end

The example implementation is just a common idiom in ruby where a method
ending in a “bang”, or exclamation point is a destructive method,
altering the state of the object, whereas the non-bang version of the
method acts on a duplicate object, so as to keep the actual object
unaltered. There is nothing special about the bang in how it is
processed in ruby, it’s just taken as part of the method name. So yes,
you can just replace it with “w” or something. The reason for the bang
is just ruby convention. If you wanted, you could reverse the
definitions, and it would work fine, but just be confusing (don’t do
that, go by convention).

Hope that’s clear.

  • Ehsan

Ja, great! Thanks Ehsan - I’ve got it now :slight_smile:

Michelle

Sorry Ryan… I’m still not getting it :frowning:

What is that exclamation mark doing? Could I substitute lets say a ‘w’
for the exclamation mark?

opts.send(:parse!, argv) => opts.send(:parsew, argv)
opts.send(:parse, argv) => opts.send(:parse, argv)

If I can, then I understand it. There are in fact two different methods
‘parsew’ and ‘parse’. But if thats true… then in my orginal code
above, there wasn’t a ‘parse!’ method defined.

On 17.11.2009 09:48, Michelle P. wrote:

Sorry Ryan… I’m still not getting it :frowning:

What is that exclamation mark doing? Could I substitute lets say a ‘w’
for the exclamation mark?

Yes. The exclamation mark is just more visible than the “w”. In the
particular case of OptionParser the difference between #parse and
#parse! is that the latter actually modifies the argument (typically
ARGV), which btw. is a nice thing because what it leaves behind in ARGV
are only file names and so using ARGF works well together with
OptionParser. I typically do

OptionParser.new do |opts|
opts.on …
end.parse! ARGV

Then, depending on what the program does

ARGF.each do |line|
puts “read a line: #{line}”
end

Kind regards

robert