Mixing types of arguments

Hi,
I was wondering why Ruby was designed so that
def f(u, v=1, *x)
p u, v, x
end
is OK, but
def g(u, *v, x=1)
p u, v, x
end
gives a syntax error.

I would’ve expected g(1) to print
1
[]
1
g(1,2) to print
1
[]
2
and g(1,2,3,4,5) to print
1
[2,3,4]
5

Probably because I’d have expected g(1,2) to print

1
[2]
1

and g(1,2,3,4,5) to print

1
[2,3,4,5]
1

Matthew K. wrote in post #1130722:

Probably because I’d have expected g(1,2) to print

1
[2]
1

and g(1,2,3,4,5) to print

1
[2,3,4,5]
1

This way you won’t be able to assign to x (the optional parameter).

On Mon, Dec 16, 2013 at 2:19 PM, Matthew K. [email protected]
wrote:

Probably because I’d have expected g(1,2) to print

1
[2]
1

and g(1,2,3,4,5) to print

1
[2,3,4,5]
1

In other words: Gandalf, what you ask for is ambiguous. The parser
cannot decide whether g(1,2) should give 1, [], 2 or 1, 2, 1. There
is no automated way to decide this unless some priorities are given
with regard to args with * and those with default value. If you think
about it that can soon get messy and Matz tends to avoid pitfalls like
these.

Note that there are other similar restrictions:

irb(main):008:0> def h(a,*b,c,*d) p [a,b,c,d] end
SyntaxError: (irb):8: syntax error, unexpected tSTAR
def h(a,*b,c,*d) p [a,b,c,d] end
^
(irb):8: syntax error, unexpected keyword_end, expecting $end
from /usr/bin/irb:12:in `’

Kind regards

robert

Robert K. wrote in post #1130727:

On Mon, Dec 16, 2013 at 2:19 PM, Matthew K. [email protected]
wrote:

Probably because I’d have expected g(1,2) to print

1
[2]
1

and g(1,2,3,4,5) to print

1
[2,3,4,5]
1

In other words: Gandalf, what you ask for is ambiguous. The parser
cannot decide whether g(1,2) should give 1, [], 2 or 1, 2, 1. There
is no automated way to decide this unless some priorities are given
with regard to args with * and those with default value.

There is the following sensible rule: it should always be possible to
assign to any parameter.
That’s pretty natural to me, but maybe this is subjective and it would
make Ruby less intuitive.

Subject: Re: mixing types of arguments
Date: lun 16 dic 13 06:58:29 +0100

Quoting Gandalf F. ([email protected]):

There is the following sensible rule: it should always be possible to
assign to any parameter.
That’s pretty natural to me, but maybe this is subjective and it would
make Ruby less intuitive.

Note that, since 2.0, Ruby allows named arguments. At the expense of
having to type a little bit more, you are given much more flexibility
wrt argument passing. I started using this feature a few months ago,
and surely there are cases when it is a godsend.

There are several articles about this feature online. For example:

http://ruby.about.com/od/beginningruby/ss/Keyword-Arguments.htm

Carlo

On Mon, Dec 16, 2013 at 6:58 PM, Gandalf F. [email protected]
wrote:

[2,3,4,5]
1

In other words: Gandalf, what you ask for is ambiguous. The parser
cannot decide whether g(1,2) should give 1, [], 2 or 1, 2, 1. There
is no automated way to decide this unless some priorities are given
with regard to args with * and those with default value.

There is the following sensible rule: it should always be possible to
assign to any parameter.

How do you do that if there are less arguments than parameters? It’s
no use if it cannot be safely and automatically determined which
parameters should receive which values.

That’s pretty natural to me, but maybe this is subjective and it would
make Ruby less intuitive.

It’s more important that semantics of assignment are clear and
unambiguous. For more complex cases use Ruby 2.0 or Hash arguments in
older versions.

Cheers

robert

Robert K. wrote in post #1130770:

On Mon, Dec 16, 2013 at 6:58 PM, Gandalf F. [email protected]
wrote:

[2,3,4,5]
1

In other words: Gandalf, what you ask for is ambiguous. The parser
cannot decide whether g(1,2) should give 1, [], 2 or 1, 2, 1. There
is no automated way to decide this unless some priorities are given
with regard to args with * and those with default value.

There is the following sensible rule: it should always be possible to
assign to any parameter.

How do you do that if there are less arguments than parameters? It’s
no use if it cannot be safely and automatically determined which
parameters should receive which values.

I meant something different.

Let’s consider again
def f(x,*y,z=1)
p x,y,z
end
If we decide that f(1,2,3) prints
1
[2,3]
1
then we’re saying that y should capture anything starting from the
second parameter. That makes it impossible to give a value to z and thus
this should be avoided according to the rule I was talking about.
Basically, if the arguments are more than one, z should always take the
last argument.

On Mon, Dec 16, 2013 at 9:12 PM, Gandalf F. [email protected]
wrote:

def f(x,*y,z=1)
p x,y,z
end
If we decide that f(1,2,3) prints
1
[2,3]
1
then we’re saying that y should capture anything starting from the
second parameter. That makes it impossible to give a value to z and thus
this should be avoided according to the rule I was talking about.

It is avoided because the syntax is illegal.

Basically, if the arguments are more than one, z should always take the
last argument.

Hence you introduce priorities - as I stated above. I think that
makes things too complicated and thus error prone. I assume that it
has not been done exactly because of this.

Cheers

robert