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 }) + + 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).
···
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 } ) + + 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 } ) + + qs(xs.select{ |y| y > x } )
end
–
_ _
__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_
_ \ / ` | ’ \
) | (| | |__ \ | | | | | (| | | | |
.__/ _,|_|/| || ||_,|| |_|
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