Defining a method with an argument with a default value

P

Pedro Côrte-Real

I have this line in a class method to define an initializer:

define_method:)initialize){|value| @value = value}

But I want something more like this:

define_method:)initialize){|value=nil| @value = value if value}

which doesn't seem to be possible because of the "value=nil" part. Is
there some way to do this that isn't eval? Eval would work fine since
this is pretty static code and I have unit tests for it but I try to
avoid it if I can. I've only used it before for performance to turn
some code with runtime tests into eval-time tests.

Pedro.
 
D

Daniel Schierbeck

Pedro said:
I have this line in a class method to define an initializer:

define_method:)initialize){|value| @value = value}

But I want something more like this:

define_method:)initialize){|value=nil| @value = value if value}

First of all, you don't need the `if value' part -- when Ruby sees
@value, it is immediately created, with the value nil, so there's no
problem with giving it the value nil explicitly. Second, I believe you
can just do this:

define_method:)initialize){|value| @value = value}

If #initialize is called with no arguments, `value' will just be nil,
although IRB may issue a warning.


Cheers,
Daniel
 
D

Dr Nic

You could do the following:

Foo.class_eval do
def bar(tar=0)
tar * 2
end
end

Foo.new.tar
=> 0
Foo.new.tar 4
=> 8
 
P

Pedro Côrte-Real

First of all, you don't need the `if value' part -- when Ruby sees
@value, it is immediately created, with the value nil, so there's no
problem with giving it the value nil explicitly.

Yes, I knew that.
Second, I believe you
can just do this:

define_method:)initialize){|value| @value = value}
If #initialize is called with no arguments, `value' will just be nil,
although IRB may issue a warning.


That's what I have but it throws a warning and I wanted to shut it up.
Guess I'll have to do the eval.

Thanks,

Pedro.
 
P

Pedro Côrte-Real

You could do the following:

Foo.class_eval do
def bar(tar=0)
tar * 2
end
end

Yep, this works great, thanks. It's an eval but it's the one with a
block instead of a string. Didn't know "def" worked inside a block.
Must free myself of silly mental restrictions brought over from lesser
languages... :)

Thanks,

Pedro.
 
D

Dr Nic

Must free myself of silly mental restrictions brought over from lesser
languages... :)

If you're feeling really lazy or just want to test something in IRB
before posting on a forum :) then this is what you might type:

Foo.class_eval { def bar(tar=0); tar * 2; end}

Of course then you should reformat it for the forum :)
 
D

Dr Nic

Oooh. And another cool use of class_eval is:
def bar(tar=0)
tar * 2
end
}
=> " def bar(tar=0)\n tar * 2\nend"=> nil
Foo.new.bar 10
=> 20

So, this means you can take the text to eval against the class from
anywhere. :)
 
N

nobu

Hi,

At Tue, 25 Jul 2006 19:33:38 +0900,
=?ISO-8859-1?Q?Pedro_C=F4rte-Real?= wrote in [ruby-talk:203711]:
define_method:)initialize){|value=nil| @value = value if value}

define_method:)initialize) {|*values|
case values.size
when 0
value = nil
when 1
value = values.first
else
raise ArgumentError, "wrong number of arguments (#{values.size} for 0)"
end
@value = value
}
 
D

Dr Nic

[Warning: Anal retentive refactoring ahead]

define_method:)initialize) do |*values|
case values.size
when 0..1
@value = values.first
else
raise ArgumentError, "wrong number of arguments (#{values.size} for
0)"
end
end

or perhaps

define_method:)initialize) do |*values|
@value = values.shift
unless @value.length == 0
raise ArgumentError, "wrong number of arguments (#{values.size} for
0)"
end
end

Too... many... options... ahh!
 
D

Daniel DeLorme

Daniel said:
First of all, you don't need the `if value' part -- when Ruby sees
@value, it is immediately created, with the value nil

Sorry for being pedantic but this is not quite true (although in this
case it doesn't make a difference):

irb(main):001:0> @a = 1 if false
=> nil
irb(main):002:0> b = 2 if false
=> nil
irb(main):003:0> @c = nil
=> nil
irb(main):004:0> defined? @a
=> nil
irb(main):005:0> defined? b
=> "local-variable"
irb(main):006:0> defined? @c
=> "instance-variable"


Daniel
 
D

Daniel Schierbeck

Daniel said:
Sorry for being pedantic but this is not quite true (although in this
case it doesn't make a difference):

irb(main):001:0> @a = 1 if false
=> nil
irb(main):002:0> b = 2 if false
=> nil
irb(main):003:0> @c = nil
=> nil
irb(main):004:0> defined? @a
=> nil
irb(main):005:0> defined? b
=> "local-variable"
irb(main):006:0> defined? @c
=> "instance-variable"

I know, but I was trying to simplify the problem :)


Cheers,
Daniel
 
P

Patrick Ritchie

As long as we're throwing around options...
define_method:)initialize) do |*values|
@value = values.shift
unless @value.length == 0
raise ArgumentError, "wrong number of arguments (#{values.size} for
0)"
end
end
define_method:)initialize) do |*values|
raise ArgumentError, "wrong number of arguments (#{values.size} for 0)" if values.length > 1
@value = values.first
end

Cheers!
Patrick
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top