On Sun, Jan 12, 2003 at 05:44:04AM +0900, MetalOne wrote:
> I was wondering if anybody thinks there is anything illogical or
> inconsistent with the following two pieces of code.
> 
> code sample 1:  splitting a list into it's head and tail.
> h, *t = [1,2,3]
> h ==> 1
> t ==> [2,3]
> -----------------------
> 
> code sample 2: passing a list to a function accepting two arguments.
> def f(h, *t)
>     # actual result
>     # h ==> [1,2,3]
>     # t ==> []
> 
> 
>     # my expected result
>     # h ==> 1
>     # t ==> [2,3]
> end
> 
> f [1,2,3]
> ---------------
> 
> I was expecting the assignment of parameters to arguments to work the
> same way as normal assignment.
> 
> The downside to the way it works now is demonstrated by the following
> quick sort code:
> def qs(arr)
>    return [] if arr.length <= 0
>    x, *xs = arr
>    qs(xs.select{ |y| y <= x } ) + [x] + qs(xs.select{ |y| y > x } )
> end
> 
> However, it could have been written more concisely as
> #pseudo code
> def qs(x, *xs)
>    return [] if x.nil?
>    qs(xs.select{ |y| y <= x } ) + [x] + qs(xs.select{ |y| y > x } )
> end

irb(main):001:0> def f(h,*t)
irb(main):002:1> p h
irb(main):003:1> p t
irb(main):004:1> end
nil
irb(main):005:0> f *[1,2,3]
1
[2, 3]
nil

batsman@kodos:/tmp$ cat b.rb
 def qs(x=nil, *xs)
    return [] if x.nil?
    qs(*xs.select{ |y| y <= x }) + [x] + qs(*xs.select{ |y| y > x })
end

p qs *[6,2,5,1,9,4,3,7,0,8]
batsman@kodos:/tmp$ ruby b.rb
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Notice I need the 'x=nil' thing because otherwise we'd get the
following
b.rb:3:in `qs': wrong # of arguments(0 for 1) (ArgumentError)
when xs.select returns an empty list (the unary * expands that to 'no
argument')

BTW, I have the feeling I have found something really strange about
Ruby's semantics:
irb(main):001:0> xs = [1,2,3]
[1, 2, 3]
irb(main):002:0> xs.select { |x| x < 0 }
[]
irb(main):003:0> *(xs.select { |x| x < 0 })
SyntaxError: compile error
(irb):3: parse error
        from (irb):3
irb(main):004:0> p(*(xs.select { |x| x < 0 }))
nil
irb(main):005:0> p(*(xs.select { |x| x < 0 })|nil)
TypeError: failed to convert nil into Array
        from (irb):5:in `|'
        from (irb):5
irb(main):006:0> p(*(xs.select { |x| x < 0 })||nil)
nil
irb(main):007:0> p nil
nil
nil

So *([]) is illegal when standing on its own (OK as *whatever is too)
and only works in a method call or assigment. Now comes the weird part: 
sometimes it is expanded as nil (line 005), some others it is some unknown 
true value (kinda like some 'true void') (l. 006).
-- 
 _           _                             
| |__   __ _| |_ ___ _ __ ___   __ _ _ __  
| '_ \ / _` | __/ __| '_ ` _ \ / _` | '_ \ 
| |_) | (_| | |_\__ \ | | | | | (_| | | | |
|_.__/ \__,_|\__|___/_| |_| |_|\__,_|_| |_|
	Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

..you could spend *all day* customizing the title bar.  Believe me.  I
speak from experience.
	-- Matt Welsh