Message from discussion
what's up with return *splat ?
Received: by 10.68.190.104 with SMTP id gp8mr4928210pbc.4.1340401018321;
Fri, 22 Jun 2012 14:36:58 -0700 (PDT)
Path: l9ni8239pbj.0!nntp.google.com!news2.google.com!news3.google.com!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail
From: Robert Klemme <shortcut...@googlemail.com>
Newsgroups: comp.lang.ruby
Subject: Re: what's up with return *splat ?
Date: Fri, 22 Jun 2012 23:36:55 +0200
Lines: 157
Message-ID: <a4k6roF84oU1@mid.individual.net>
References: <0fae13bb-3468-4883-b855-17950bee1117@t2g2000pbl.googlegroups.com> <a3pq3mFm27U1@mid.individual.net> <2a77ca16-20d5-4700-bf7d-0a746f4730d6@e7g2000pbg.googlegroups.com> <a43eidFbv2U1@mid.individual.net> <9040131a-0ad1-4736-a0e3-693b9cf58a27@g4g2000pbn.googlegroups.com> <a4jkhpFss0U1@mid.individual.net> <3a1bf78f-70a5-4856-8fea-6e23671eaa72@y3g2000pbc.googlegroups.com>
Mime-Version: 1.0
X-Trace: individual.net 0JAsYpeExkyidXYT8Uv4zQeyDP0M2cL3JZQPsUxfLQ2HWzf6pvI3Bqnl/+VRwyPN8=
Cancel-Lock: sha1:g8O1r+om2oYD5iDrRVLddMQ6cgw=
User-Agent: Mozilla/5.0 (Windows NT 6.0; WOW64; rv:13.0) Gecko/20120614 Thunderbird/13.0.1
In-Reply-To: <3a1bf78f-70a5-4856-8fea-6e23671eaa72@y3g2000pbc.googlegroups.com>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
On 22.06.2012 19:02, Phlip wrote:
> On Jun 22, 9:24 am, Robert Klemme <shortcut...@googlemail.com> wrote:
>> On 22.06.2012 01:24, Phlip wrote:
>>
>>> Tx for the experiment; it confirmed mine.
>>
>> Strange. I said
>
> Your experiment confirmed 1.9.2 changed the behavior, like mine did.
Yes, but I got different results than those you claimed. Which made me
wonder.
>>> I want the assertions to break, with simple syntax errors, if the
>>> ordinality is wrong.
>>
>> You cannot get syntax errors for this. This is checked at runtime and
>> not at parse time.
>
> I'm aware of the definition of syntax error.
Why then do you use it in the wrong way?
>> irb(main):006:0> x,=f 1,2
>
> That line does not die, with an-error-checked-at-runtime, nor would
> x.member (given [] does not have .member) die with an-error-checked-at-
> runtime.
>
> When the author of a test writes assert_latest() they know whether
> they expect a scalar or a list to return, and they should not waste
> their time checking for a single-element list before using it in the
> assertion that actually checks for the important stuff.
Well, if you use "x,=..." then you have the first element and no
additional checking is needed. But if you really want to ensure the
proper number of values is returned you need to test for the array
length anyway. At least you would need to to something like
irb(main):008:0> x,y,*remainder = f 1,2
=> [1, 2]
irb(main):009:0> remainder
=> []
irb(main):010:0> remainder.empty?
=> true
irb(main):011:0> x,y,*remainder = f 1,2,3
=> [1, 2, 3]
irb(main):012:0> remainder.empty?
=> false
For consistent checking of the returned data you can do
*x = f(...)
x will be an Array even if f returns a single value only.
> If I use record, = assert_latest(), and if a future bug added a second
> record, the assertion would not break, that line would not break (with
> a comma), and lines using record would not break.
>
> Also I'm not sure why I need to justify the use case, if such a low-
> level syntactical thing should not change in a language revision.
Actually most people seem to cope pretty well with this as only corner
cases are affected of the change. If you want to ensure no additional
values are returned you need to splat assign any way to count values, i.e.
*x = f()
> It's
> a bug in return *splat; it no longer behaves the same as = *splat.
It's not syntax but runtime behavior. You can and will never get a
syntax error for this.
AFAIK Matz changed it deliberately - although I have to confess I don't
remember the reasoning. You'll probably find it in the archives.
Note though that also argument assignment changed quite a bit in 1.9
which has much more sophisticated options where 1.8 only allowed for the
last parameter to collect additional values. The 1.9 model is superior
to that:
irb(main):001:0> def f(a, *b, c) p a,b,c end
=> nil
irb(main):002:0> f 1
ArgumentError: wrong number of arguments (1 for 2)
from (irb):1:in `f'
from (irb):2
from /usr/local/bin/irb19:12:in `<main>'
irb(main):003:0> f 1,2
1
[]
2
=> [1, [], 2]
irb(main):004:0> f 1,2,3
1
[2]
3
=> [1, [2], 3]
irb(main):005:0> f 1,2,3,4,5
1
[2, 3, 4]
5
=> [1, [2, 3, 4], 5]
And you have pattern matching with block arguments
irb(main):007:0> f = lambda {|a, (b,c), d| p a,b,c,d}
=> #<Proc:0x202a96c4@(irb):7 (lambda)>
irb(main):008:0> f[1]
ArgumentError: wrong number of arguments (1 for 3)
from (irb):7:in `block in irb_binding'
from (irb):8:in `[]'
from (irb):8
from /usr/local/bin/irb19:12:in `<main>'
irb(main):009:0> f[1,2]
ArgumentError: wrong number of arguments (2 for 3)
from (irb):7:in `block in irb_binding'
from (irb):9:in `[]'
from (irb):9
from /usr/local/bin/irb19:12:in `<main>'
irb(main):010:0> f[1,2,3]
1
2
nil
3
=> [1, 2, nil, 3]
irb(main):011:0> f[1,[2],3]
1
2
nil
3
=> [1, 2, nil, 3]
irb(main):012:0> f[1,[2,3],4]
1
2
3
4
=> [1, 2, 3, 4]
irb(main):013:0> f[1,[2,3,4],5]
1
2
3
5
=> [1, 2, 3, 5]
Cheers
robert
--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/