[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Verifying keyword arguments

Eli Bendersky

3/24/2006 6:19:00 AM

Hello all,

I'm now writing my first real Ruby module, and on the second function I
already run into a pattern that seems to be very common.
I like using keyword arguments for methods, as follows:

def method(args)
...
end

And then call:

method(:arg1 => value1, :arg2 => value2)

And so on.
Now, often some arguments are compulsory, so I wrote the following code
to verify it:

def method(args)
[:username, :password, :url].each do |arg|
raise(ArgumentError, "Argument :#{arg} is compulsory" unless
args.has_key?(arg)
end

...
end

I have two questions:
1) Is this the right/idiomatic/best way to achieve what I'm attempting
?
2) Is there a library that encapsulates this capability, or is everyone
writing one of his own ? Because if I don't find any, I surely will
write one... It should be enough saying:

verify_args(:username, :password, :url)

Instead of the .each do iteration everywhere

Eli

6 Answers

Eli Bendersky

3/25/2006 5:01:00 AM

0


Eli Bendersky wrote:
> Hello all,
>
> I'm now writing my first real Ruby module, and on the second function I
> already run into a pattern that seems to be very common.
> I like using keyword arguments for methods, as follows:
>
> def method(args)
> ...
> end
>
> And then call:
>
> method(:arg1 => value1, :arg2 => value2)
>
> And so on.
> Now, often some arguments are compulsory, so I wrote the following code
> to verify it:
>
> def method(args)
> [:username, :password, :url].each do |arg|
> raise(ArgumentError, "Argument :#{arg} is compulsory" unless
> args.has_key?(arg)
> end
>
> ...
> end
>
> I have two questions:
> 1) Is this the right/idiomatic/best way to achieve what I'm attempting
> ?
> 2) Is there a library that encapsulates this capability, or is everyone
> writing one of his own ? Because if I don't find any, I surely will
> write one... It should be enough saying:
>
> verify_args(:username, :password, :url)
>
> Instead of the .each do iteration everywhere
>
> Eli

Is this topic of no interest to anyone but me ? :-/

Ross Bamford

3/25/2006 10:03:00 AM

0

On Sat, 2006-03-25 at 14:03 +0900, Eli Bendersky wrote:
> Eli Bendersky wrote:
> > Hello all,
> >
> > I'm now writing my first real Ruby module, and on the second function I
> > already run into a pattern that seems to be very common.
> > I like using keyword arguments for methods, as follows:
> >
> > def method(args)
> > ...
> > end
> >
> > And then call:
> >
> > method(:arg1 => value1, :arg2 => value2)
> >
> > And so on.
> > Now, often some arguments are compulsory, so I wrote the following code
> > to verify it:
> >
> > def method(args)
> > [:username, :password, :url].each do |arg|
> > raise(ArgumentError, "Argument :#{arg} is compulsory" unless
> > args.has_key?(arg)
> > end
> >
> > ...
> > end
> >
> > I have two questions:
> > 1) Is this the right/idiomatic/best way to achieve what I'm attempting
> > ?

It works, and strikes me as more compact and elegant than a simple
'raise unless args[:username] && args[:password] && ...'.

> > 2) Is there a library that encapsulates this capability, or is everyone
> > writing one of his own ? Because if I don't find any, I surely will
> > write one... It should be enough saying:
> >
> > verify_args(:username, :password, :url)
> >
> > Instead of the .each do iteration everywhere
> >

Not sure about libraries (though I'm sure they are out there, check RAA
and Rubyforge) but here's a little trick I've used before:

args = { :one => 'two', :three => 'four' }
# => {:three=>"four", :one=>"two"}

h = Hash.new { |h,k| raise ArgumentError, "#{k}" }.merge(args)
# => {:three=>"four", :one=>"two"}

h[:one]
# => "two"

h[:three]
# => "four"

h[:two]
ArgumentError: two
from (irb):5
from (irb):11

This way, you never actually check the arguments explicitly, but you'll
be told if your method uses one that wasn't passed. Obviously for
optional arguments you go to the original hash.

--
Ross Bamford - rosco@roscopeco.REMOVE.co.uk



Eli Bendersky

3/25/2006 2:05:00 PM

0


Ross Bamford wrote:
> On Sat, 2006-03-25 at 14:03 +0900, Eli Bendersky wrote:
> > Eli Bendersky wrote:
> > > Hello all,
> > >
> > > I'm now writing my first real Ruby module, and on the second function I
> > > already run into a pattern that seems to be very common.
> > > I like using keyword arguments for methods, as follows:
> > >
> > > def method(args)
> > > ...
> > > end
> > >
> > > And then call:
> > >
> > > method(:arg1 => value1, :arg2 => value2)
> > >
> > > And so on.
> > > Now, often some arguments are compulsory, so I wrote the following code
> > > to verify it:
> > >
> > > def method(args)
> > > [:username, :password, :url].each do |arg|
> > > raise(ArgumentError, "Argument :#{arg} is compulsory" unless
> > > args.has_key?(arg)
> > > end
> > >
> > > ...
> > > end
> > >
> > > I have two questions:
> > > 1) Is this the right/idiomatic/best way to achieve what I'm attempting
> > > ?
>
> It works, and strikes me as more compact and elegant than a simple
> 'raise unless args[:username] && args[:password] && ...'.
>
> > > 2) Is there a library that encapsulates this capability, or is everyone
> > > writing one of his own ? Because if I don't find any, I surely will
> > > write one... It should be enough saying:
> > >
> > > verify_args(:username, :password, :url)
> > >
> > > Instead of the .each do iteration everywhere
> > >
>
> Not sure about libraries (though I'm sure they are out there, check RAA
> and Rubyforge) but here's a little trick I've used before:
>
> args = { :one => 'two', :three => 'four' }
> # => {:three=>"four", :one=>"two"}
>
> h = Hash.new { |h,k| raise ArgumentError, "#{k}" }.merge(args)
> # => {:three=>"four", :one=>"two"}
>
> h[:one]
> # => "two"
>
> h[:three]
> # => "four"
>
> h[:two]
> ArgumentError: two
> from (irb):5
> from (irb):11
>
> This way, you never actually check the arguments explicitly, but you'll
> be told if your method uses one that wasn't passed. Obviously for
> optional arguments you go to the original hash.
>

This is a nice trick that can be used to handle optional keyword
variables with default values, and indeed it helps detect unwanted
variables.
I think it can be somehow combined with the method I presented - the
aim of which is to detect if any compulsory argument wasn't passed in.
After all, there are arguments for which a default value is
meaningless.

Eli -- (http://eliben.bl...)

Joel VanderWerf

3/25/2006 9:08:00 PM

0

Ross Bamford wrote:
...
> Not sure about libraries (though I'm sure they are out there, check RAA
> and Rubyforge) but here's a little trick I've used before:
>
> args = { :one => 'two', :three => 'four' }
> # => {:three=>"four", :one=>"two"}
>
> h = Hash.new { |h,k| raise ArgumentError, "#{k}" }.merge(args)
> # => {:three=>"four", :one=>"two"}
>
> h[:one]
> # => "two"
>
> h[:three]
> # => "four"
>
> h[:two]
> ArgumentError: two
> from (irb):5
> from (irb):11
>
> This way, you never actually check the arguments explicitly, but you'll
> be told if your method uses one that wasn't passed. Obviously for
> optional arguments you go to the original hash.
>

What about using rescue for optional arguments? It might be slower though.

--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407


Eli Bendersky

3/26/2006 5:28:00 PM

0


Joel VanderWerf wrote:
> Ross Bamford wrote:
> ..
> > Not sure about libraries (though I'm sure they are out there, check RAA
> > and Rubyforge) but here's a little trick I've used before:
> >
> > args = { :one => 'two', :three => 'four' }
> > # => {:three=>"four", :one=>"two"}
> >
> > h = Hash.new { |h,k| raise ArgumentError, "#{k}" }.merge(args)
> > # => {:three=>"four", :one=>"two"}
> >
> > h[:one]
> > # => "two"
> >
> > h[:three]
> > # => "four"
> >
> > h[:two]
> > ArgumentError: two
> > from (irb):5
> > from (irb):11
> >
> > This way, you never actually check the arguments explicitly, but you'll
> > be told if your method uses one that wasn't passed. Obviously for
> > optional arguments you go to the original hash.
> >
>
> What about using rescue for optional arguments? It might be slower though.
>

What do you mean ? Can you provide an example ?

Joel VanderWerf

3/26/2006 7:29:00 PM

0

Eli Bendersky wrote:
> Joel VanderWerf wrote:
>> Ross Bamford wrote:
>> ..
>>> Not sure about libraries (though I'm sure they are out there, check RAA
>>> and Rubyforge) but here's a little trick I've used before:
>>>
>>> args = { :one => 'two', :three => 'four' }
>>> # => {:three=>"four", :one=>"two"}
>>>
>>> h = Hash.new { |h,k| raise ArgumentError, "#{k}" }.merge(args)
>>> # => {:three=>"four", :one=>"two"}
>>>
>>> h[:one]
>>> # => "two"
>>>
>>> h[:three]
>>> # => "four"
>>>
>>> h[:two]
>>> ArgumentError: two
>>> from (irb):5
>>> from (irb):11
>>>
>>> This way, you never actually check the arguments explicitly, but you'll
>>> be told if your method uses one that wasn't passed. Obviously for
>>> optional arguments you go to the original hash.
>>>
>> What about using rescue for optional arguments? It might be slower though.
>>
>
> What do you mean ? Can you provide an example ?
>

args = { :one => 'two', :three => 'four' }
# => {:three=>"four", :one=>"two"}

h = Hash.new { |h,k| raise ArgumentError, "#{k}" }.merge(args)
# => {:three=>"four", :one=>"two"}

h[:one]
# => "two"

h[:three]
# => "four"

v = h[:two] rescue "this string is the default for 'two'"
p v
# => "this string is the default for 'two'"

--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407