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