> Ideally, I'd like to be able to offer either of these
> on an API I'm creating:

> my_method('a','b','c')

You already gave an example of how to do this. It is via
the splat operator in ruby. You can test this in IRB:

require 'pp'

def foo(*i)
  pp i
end

foo('a','b','c')

You can see that this will return an array:

  ["a", "b", "c"]

That way you can have as many arguments to a method
as you like - they will all be collected into the
variable name you wrote down in the method definition.

So far, so good. Now to the other question you have:

> my_method(first: 'a', second: 'b', third: 'c')

Ok, let's first break down what happens here. I
will replace "my_method" with "foo", I like foo()
as demo-name for methods.

So we have:

  my_method(first: 'a', second: 'b', third: 'c')

which is:

  foo(first: 'a', second: 'b', third: 'c')

which actually is this here:

  foo({first: 'a', second: 'b', third: 'c'})

In other words, this is a hash.

To make this compatible with Ruby 1.8.x, let's make
it even more clear:

  foo({:first => 'a', :second => 'b', :third => 'c'})

Now, if you look at what this code above returns in
IRB (test it please!), you will notice it will return
this here:

  [{:third=>"c", :second=>"b", :first=>"a"}]

In other words, it has simply put the hash that you
passed here into the first element of an array. So
you still have an array!

With splat operator, it seems as if you will always
have an array. :)

Now you could, within the method definition, check
whether you have a hash.

  if i.is_a? Array
    if i[0].is_a? Hash
      # do something special here

Ok? You just check whether your first element contains
a hash or not. If it does contain a hash, you can act
on this information, inside your method!


> I know I can construct the method definition as:

> def my_method(*args)
>  ...
> end

Yes, the splat operator.

> and whatever way they pass things in will get there.

Yes, collected into an array! args in your example will
be an array.

> But how can I easily merge them into a hash for use
> in the rest of the method?

Simple. Check the given argument for .is_a? and
when you find a hash, reconstruct the method and
the variable. It is your method, you are in full
control of what it does and what it will return!

Input, Modify, Output - that is a the basic of
any function (or method in ruby, as functions
are attached to objects).

> I want the end result to look like:
> {:first => 'a', :second => 'b', :third => 'c'}

You already have this! It just resides as the
first element of your array!

In fact, if you would have tested in IRB, you
could have seen it :D

(Btw I just noticed that you used the new hash
syntax. I recommend to use the old hash syntax,
for CONSISTENCY. Right now you seem to switch
beween the two, I don't think this is good at
all.)

> no matter how they enter them.

Hmmmmmm. I am not sure if it is easily possible
to get the same input as output as far as the
new hash syntax is concerned. I would, right now,
simply claim that this is not possible.

> And could you deal with something where a hash
> is entered as a positional parameter, and
> trailing hash values as well?? Like:

> mymethod(({z: 1, x: 2}),'bazinga!', third: 17)

> to end up with:

> {:first => {:z => 1, :x => 2}, :second => 'basinga!', :third => 17}

No, you can not. There is no way for ruby to make a
real difference between the two different syntaxes
on the AST. Perhaps matz could say something about
this - I myself would not need what you need, because
I will forever more use the old way to use a hash ;)
but if others really need the same input as the same
output, well then why not. But internally, I think
it is ALL converted into the same internal representation,
it just seems syntactic sugar to squeeze away a
few extra characters.

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