On 30 October 2011 11:10, Yusuke Endoh <mame / tsg.ne.jp> wrote:
> Hello,
>
> Koichi told me that I can commit my patch to the trunk.  > I'll do after I fix the issues Benoit reported.
> But I'll remain this ticket open to continue to discuss the
> spec.
>
>
> 2011/10/30 Benoit Daloze <eregontp / gmail.com>:
>> I have a few questions/remarks:
>
> Thank you very much for your trying my patch and your opinion!

It's all my pleasure to test shiny new features.

>> 1) What is the way to pass keyword arguments ?
>> I would guess `**h` like:
>>
>> def meth(a, **h)
>>  
>> end # => syntax error
>
> I didn't implement caller's **.
> I wonder if we need it or not.  ¢
I don't know why I thought keyword arguments were a separate type of
arguments, while there are mostly syntactic sugar for treating the
Hash given, if I understand well (which is fine, except maybe for
optimizations from the implementer POV, but I don't know well).

In that case, it is indeed enough.

>> BTW, using **h in the argument list does not seems to work in some casesor me:
>>
>> def a(**h)
>> end # => syntax error, unexpected tPOW
>
> Currently, my patch allows ** only when there are one or more
> keyword arguments.
>
> This is because I didn't think of any use case.
> In addition, I wanted to simplify the implementation of parser.
> (Unfortunately, adding a new argument type requries *doubling*
>      > Do you think we need it?

No, sorry for the confusion.
(Ugh, doubling the parser rules sounds bad)

>> def m(k: nil, **h, &block)
>> end
>> m() # => undefined method `key?' for nil:NilClass
>
> This must be a bug.  § 

It seems to happen only when there is the &block parameter in my experience.

>> 2) I'm a bit dubious about the `**h` syntax to get (and I guess to
>> pass) a Hash though.
>
> As I said above, it serves as just `get', not `pass,' currently.
>
>
>> I believe `*args` is appropriate for the rest argument, because the
>> star is the splat operator.
>> I cannot think of any clear logic like that for `**h` except "another
>> rest argument".
>> Also `**` is the power operator, which is unrelated.
>> Something related to `{}`, the literal Hash syntax, would fit better
>> in my opinion.
>
> I accept another syntax, if it is allowed by matz, and yacc :-)
>
>> Do you have any idea of an alternate syntax to `**h` ?
>
> No I don't.

Given the above considerations, `**h` will only be used to get the
Hash, so I think it is fine.
Notably, delegating with method missing will stay simple as it is:

def method_missing(*args, &block)
  other(*args, &block)
end

>> 3) What would {Proc,Method,UnboundMethod}#parameters returns for
>> keywords arguments ?
>
> Indeed.     §
I would happily write the tests for that if you want.
Do you agree on the :key and :keyrest (now I'm thinking to :hash) names ?

>> 4)    
>> def a(k: :a, **h)
>>   >> end
>> a(:b, c: :d, e: :f) # => wrong number of arguments (2 for 0) (ArgumentError)
>> It should be "1 for 0"
>
> Yes, the error message should be considered.
> But in the case, you're passing two arguments actually:
> ":b", and "{:c=>:d, :e=>:f}"
> Do you mean the keyword argument (= hash) should be ignored?

Well, it is rather confusing as is.
I would be fine with "1 for 0" since the method does not actually need
any argument.

If we count all arguments, we have indeed two, but then it's "2 for
1", the Hash should be counted at callee side too.
It would be nice if the ArgumentError specified what is missing, or
you might end up with "wrong number of arguments (1 for 1)":

def b(k: nil, **h)
end
b(:a) # => wrong number of arguments (1 for 0) (ArgumentError) # This
would be "1 for 1" if Hash is counted at callee side

I'm thinking to something like:
"positional argument given instead of keyword argument (ArgumentError)"
or
replace "x for y" by something mentioning (y-1) positional arguments
and the keyword argument.
But that's really badly said, I got no inspiration for error messages.

"2 for 0..1" might be a good compromise.
I wonder why this is not implemented with standard arguments (sorry
this is a bit off-topic, but it illustrates my thought):
def f(a, b = nil)
end
f(1, 2, 3) # => wrong number of arguments (3 for 2)
f() # => wrong number of arguments (0 for 1)
It's be nice to have "for 1..2".

>> def a(k: :a)
>>   >> end
>> a(r: :a) # => unknown keyword (TypeError)
>> It should say which keyword is missing
>
> Strongly agreed.     
The first virtue of a programmer :-)

>> (and an ArgumentError rather than TypeError, no?).
>
> Yes, fixed.      庴
>
> Thanks!
>
> --
> Yusuke Endoh <mame / tsg.ne.jp>
>