Faking named parameters and enforcing required params

I come from years of using a language with named params. I prefer the
explicitness of it, so I'm tending to do a lot of it in my Ruby code
using a hash to fake it

  object.method(:shape=>'square', :size='medium')

What I am wondering is whether there's an idiomatc preference to dealing
with the hash inside the method?

Currently, I just do the prozaic:

  def task(parameters)
    shape = parameters[:shape]
    size = parameters[:size]

Should I be doing something else?

In that other language (Lasso), it also offered a way to declare
required and optional parameters

  define_tag:'task',
    -required = 'shape',
    -optional = 'size';

    ...blah...

  /define_tag;

which then got used like this:

  object->task(-shape='square', -size='large') # legal
  object->task(-shape='square') # legal
  object->task(-size='medium') # failed for lack of required param

The required and optional features combined with some other stuff got
very close to a full design by contract implementation.

Anyway, I figured out I could simulate the assignment side of required
and optional with this:

  def task(parameters)
    @shape = parameters[:shape]
    @size = parameters[:size] ||= 'medium'

What I have't figured out is an elegant pattern in Ruby for enforcing
required parameters -- other than a bunch of hand written exception
coding.

To summarize my questions:

A) is there something better than x = parameters[:x]?
B) if :x isn't in (parameters), what's the best way to complain to the
developer about that?

Many thanks.

-- gw

···

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

Maybe something like

class Hash
   def require_all_keys *keys
      keys.all?{ |k| has_key? k } or raise ArgumentError # better
doing an each here and raise an exception which argument was missing
of course, but I guess you got the idea;)
  end
  def provide_defaults defaults={}
     defaults.each_pair{ |nk,nv|
        self[nk]=nv unless has_key? nk
     }
  end
end

def whatever params={}
    params.require :size, :age
    params.provide_defaults :language => "en", :id => 42

end

HTH

Robert

···

On Tue, Jun 24, 2008 at 8:12 AM, Greg Willits <lists@gregwillits.ws> wrote:

--
http://ruby-smalltalk.blogspot.com/

---
Les mêmes questions qu'on se pose
On part vers où et vers qui
Et comme indice pas grand-chose
Des roses et des orties.
-
Francis Cabrel

Greg Willits wrote:

I come from years of using a language with named params. I prefer the
explicitness of it, so I'm tending to do a lot of it in my Ruby code
using a hash to fake it

  object.method(:shape=>'square', :size='medium')

What I am wondering is whether there's an idiomatc preference to dealing
with the hash inside the method?
  object->task(-shape='square', -size='large') # legal
  object->task(-shape='square') # legal
  object->task(-size='medium') # failed for lack of required param

The required and optional features combined with some other stuff got
very close to a full design by contract implementation.

Interestingly, I have also been working on something very similar to
this recently. [a named parameter parser for ruby]

Basically it parses an array as a parameter list, with some required and
some optional parameters.
ex:

[first remember that you can pass parameters to a method via * for a
variable number of parameters, i.e. def method *args; end passes in args
as an array of all parameters]

the syntax it uses is:

def method1 *as
  required1, required2, optional1 = as.args [:required1, :required2],
{:optional1 => 3}
end

and you call it either named or unnamedly, a la:
method1 4, 5, 6
or
method1 4, 5
or
method1 :required1 => 1, :required2 => 2
or
method1 :required1 => 1, :required2 => 2, :optional1 => 4
or
method1 1, 2, :optional1 => 4
whichever floats your boat.

Try it out, let me know if it works.

the file is

http://code.google.com/p/ruby-roger-useful-functions/source/browse/trunk/arg_parser/enhanced_arg_parser.rb

and docs for it http://wilkboardonline.com/roger/arg_parser/doc/ [see
args method for description].
Thanks!

-R

···

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

BTW I guess Facets has things like these already!

Robert

Basically it parses an array as a parameter list, with some required and
some optional parameters.
ex:

[first remember that you can pass parameters to a method via * for a
variable number of parameters, i.e. def method *args; end passes in args
as an array of all parameters]

My question is does anybody know the C code for 'adding' a variable to
the scope above the current?
something like

  scope->prev->local_vars.push(name, object);

Thanks!
-R

···

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

My question is does anybody know the C code for 'adding' a variable to
the scope above the current?
something like

  scope->prev->local_vars.push(name, object);

Thanks!
-R

It appears impossible [from casual glancing at the code] to add an
arbitrary local variable during runtime. This because it uses a 'parse
then run' style execution.
I.e.
a = 3
b
is first translated into
ASSIGN(a, 3)
CALL(b)

and then run consecutively.
And
a = 2
a
is translated into
ASSIGN(a, 2)
VAR_VALUE(a) since a is already defined. Then run.

So it appears that currently the only way to arbitrarily add a local
variable would be to hack the parse tree itself.

Guess I'll file a requested feature of binding.set_local_variable :slight_smile:
-R

···

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

So it appears that currently the only way to arbitrarily add a local
variable would be to hack the parse tree itself.

Appears that ParseTree and ruby2ruby provide this type of functionality
[see Not going dark for an
example].

So my question is
say I've got a method
def method1(a, b=3)
...
end
that I want to allow to accept named parameter [a la method1(2, :b => 3)
or method1(:a => 2]

I could either rewrite the original method's parse tree to allow for
named parameters [i.e. convert it to]
def method1(*args)
a, b = args.parse [:a], {:b => 3}
...
end
then 'eval' the newly created function, replacing the original with the
new

or I could just write a caller function, a la
alias :original_method1 :method1

def method1(*args)
a, b = args.parse [:a], {:b => 3}
original_method1(a, b)
end

so alias chain kind of.
Any thoughts on which of these would might be preferable?
Thanks!
-R

···

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