Ross Bamford
1/2/2006 8:21:00 PM
Hi,
Probably this has been considered before, but I'll ask anyway.
Before I used Ruby, I used Groovy. In some ways they are (well, were
anyway) quite similar, and one feature that I found cool in Groovy that I
often miss in Ruby is the implicit (/default/whatever?) block parameter,
'it':
[1,2,3].each { puts it }
AFAIR this was only provided when no 'it' existed in scope, and the block
had a single argument passed when none were declared. Maybe this would
interfere with Ruby's warnings about block parameter mismatch, or maybe
the implementation doesn't allow for it, but I just wondered if it might
be possible, because I notice I do:
[1,2,3].each { |it| puts it }
and it bugs me a little bit :D
I did try hacking it from the Ruby side and came up with a halfway
solution using instance variables and the Binding extension from Rubyforge:
require 'rubygems'
require 'extensions/binding'
def itproc(&blk)
class << blk
def [](*args)
if args.length == 1
begin
old = binding[:@it]
binding[:@it] = args[0]
super
ensure
binding[:@it] = old
end
else
super
end
end
alias :call :[]
end
blk
end
But of course this doesn't work with regular procs (doing it on Proc
causes a segfault here, I guess because extensions uses procs itself to do
the binding stuff?) and of course it doesn't happen with yielded blocks,
even when passed from procs:
pr = itproc { puts "@it = #{@it.inspect}" }
pr2 = itproc { |one| puts "@it = #{@it.inspect}; one = #{one.inspect}" }
pr3 = itproc { |a, b| puts "@it = #{@it.inspect}; a = #{a.inspect}; b =
#{b}" }
# Works
puts "Call"
pr.call('Hello')
pr2.call('Hello')
pr3.call('He','llo')
# Works
puts "\n[]"
pr['Bye']
pr2['Bye']
pr3['Bye','Bye']
# Doesn't work through yield though :(
puts "\nYield"
[1,2,3].each &pr
[1,2,3].each &pr2
[1,2,3].each &pr3
Anyway, it's a bit of an abuse of instance vars I guess, and obviously
doesn't do the job properly - I wonder if anyone else has thought about
this, and whether it's something that doesn't already exist in Ruby itself
for a reason?
Cheers,
--
Ross Bamford - rosco@roscopeco.remove.co.uk