Forum: Ruby Implicit block parameter?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
82e62c756d89bc6fa0a0a2d7f2b1e617?d=identicon&s=25 Ross Bamford (Guest)
on 2006-01-02 21:34
(Received via mailing list)
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,
82e62c756d89bc6fa0a0a2d7f2b1e617?d=identicon&s=25 Ross Bamford (Guest)
on 2006-01-02 22:45
(Received via mailing list)
On Mon, 02 Jan 2006 20:20:30 -0000, I wrote:

> solution using instance variables and the Binding extension from
> Rubyforge:
>

I got a bit closer by defining an attr_reader 'it' on Kernel, but still
it
doesn't work with all Procs or via Yield...
896cfc242a7762467c2a0b2af86598e5?d=identicon&s=25 Simon Strandgaard (Guest)
on 2006-01-02 23:06
(Received via mailing list)
On 1/2/06, Ross Bamford <rosco@roscopeco.remove.co.uk> wrote:
> On Mon, 02 Jan 2006 20:20:30 -0000, I wrote:
>
> > 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 }

how about?

class Array
  alias :each1 :each
  def each(&b)
    each1{|i| b.call($i = i) }
  end
end
%w(a b c).each{p $i}          #-> "a" "b" "c"
896cfc242a7762467c2a0b2af86598e5?d=identicon&s=25 Simon Strandgaard (Guest)
on 2006-01-02 23:09
(Received via mailing list)
On 1/2/06, Simon Strandgaard <neoneye@gmail.com> wrote:
> On 1/2/06, Ross Bamford <rosco@roscopeco.remove.co.uk> wrote:
> > On Mon, 02 Jan 2006 20:20:30 -0000, I wrote:
> >
> > > 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 }
>
or how about?

module Kernel
  def it
    $i
  end
end
class Array
  alias :each1 :each
  def each(&b)
    each1{|i| b.call($i = i) }
  end
end

[1, 2, 3].each{ puts it }           # 1 2 3
682fff6db11e1a150d6ce17f3b862448?d=identicon&s=25 Doug H (Guest)
on 2006-01-02 23:30
(Received via mailing list)
I think he wants this for any single parameter block though, not just
arrays.

What about automatically creating aliases, too?  Like where you put
"alias :each1 :each", have it automatically create an alias
":old_methodname" whenever you overwrite an existing method (replace
"methodname" with actual name").
..
18ca239ffade6df0b839d26062f173fb?d=identicon&s=25 Dominik Bathon (Guest)
on 2006-01-02 23:54
(Received via mailing list)
On Mon, 02 Jan 2006 21:32:57 +0100, Ross Bamford
<rosco@roscopeco.remove.co.uk> wrote:

> Hi,
>
> Probably this has been considered before, but I'll ask anyway.

I have also proposed this in October:

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/...

And it seems to have been proposed before.

I have actually implemented it for ruby 1.9 lately (it should work
similar
for 1.8). It's just a small patch for eval.c:

--- eval_org.c  2005-12-30 02:17:49.000000000 +0100
+++ eval.c      2006-01-02 23:25:46.000000000 +0100
@@ -4656,6 +4656,7 @@ rb_yield_0(VALUE val, VALUE self, VALUE
      NODE *cnode = ruby_current_node;
      int lambda = flags & YIELD_LAMBDA_CALL;
      int state;
+    VALUE it_val = Qnil;

      rb_need_block();

@@ -4675,8 +4676,10 @@ rb_yield_0(VALUE val, VALUE self, VALUE
      scope_vmode = (flags & YIELD_PUBLIC_DEF) ? SCOPE_PUBLIC :
block->vmode;
      ruby_block = block->prev;
      if (block->flags & BLOCK_D_SCOPE) {
+       if (avalue && RARRAY(val)->len != 0) it_val =
RARRAY(val)->ptr[0];
+       if (!avalue && val != Qundef) it_val = val;
         /* put place holder for dynamic (in-block) local variables */
-       ruby_dyna_vars = new_dvar(0, 0, block->dyna_vars);
+       ruby_dyna_vars = new_dvar(0, it_val, block->dyna_vars);
      }
      else {
         /* FOR does not introduce new scope */
@@ -7596,6 +7599,15 @@ rb_exec_end_proc(void)
      ruby_safe_level = safe;
  }

+static VALUE
+rb_f_it(void)
+{
+    if (ruby_dyna_vars) {
+       if (ruby_dyna_vars->id == 0) return ruby_dyna_vars->val;
+    }
+    return Qnil;
+}
+
  void
  Init_eval(void)
  {
@@ -7650,6 +7662,8 @@ Init_eval(void)
      rb_define_global_function("global_variables",
rb_f_global_variables,
0); /* in variable.c */
      rb_define_global_function("local_variables", rb_f_local_variables,
0);

+    rb_define_global_function("it", rb_f_it, 0);
+
      rb_define_method(rb_mKernel, "send", rb_f_send, -1);
      rb_define_method(rb_mKernel, "__send__", rb_f_send, -1);
      rb_define_method(rb_mKernel, "funcall", rb_f_funcall, -1);


This defines a global function #it that always returns the first block
argument, it is not assignable. #it is available whether other block
parameters are there or not. #it defaults to nil (if no arguments are
given or if not in a block context.

$ cat test_it.rb
p (1..5).to_a.map { -it }

%w[a b c].each { |x| p [x, it] }

p it
$ ./miniruby test_it.rb
[-1, -2, -3, -4, -5]
["a", "a"]
["b", "b"]
["c", "c"]
nil


Dominik
82e62c756d89bc6fa0a0a2d7f2b1e617?d=identicon&s=25 Ross Bamford (Guest)
on 2006-01-03 01:41
(Received via mailing list)
On Mon, 02 Jan 2006 22:06:49 -0000, Simon Strandgaard
<neoneye@gmail.com>
wrote:

>> > >       [1,2,3].each { puts it }
>   def each(&b)
>     each1{|i| b.call($i = i) }
>   end
> end
>
> [1, 2, 3].each{ puts it }           # 1 2 3
>

Cool, didn't consider doing it that way :) I was thinking in more
general
terms, but this way does get it working with each. I did notice, though,
that it doesn't seem too happy with other Enumerable methods (select and
collect seem pretty odd)...

Cheers,
82e62c756d89bc6fa0a0a2d7f2b1e617?d=identicon&s=25 Ross Bamford (Guest)
on 2006-01-03 01:44
(Received via mailing list)
On Mon, 02 Jan 2006 22:26:46 -0000, Doug H <doug00@gmail.com> wrote:

> What about automatically creating aliases, too?  Like where you put
> "alias :each1 :each", have it automatically create an alias
> ":old_methodname" whenever you overwrite an existing method (replace
> "methodname" with actual name").
> .
>

That would be nice, but I wonder what'd happen if a method was aliased
more than once. The alias is another bit of noise, and doesn't protect
you
 from manually overwriting a previous alias, but at least you get the
chance to fix it.

Cheers,
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2006-01-03 03:36
(Received via mailing list)
Hi --

On Tue, 3 Jan 2006, Doug H wrote:

> I think he wants this for any single parameter block though, not just
> arrays.
>
> What about automatically creating aliases, too?  Like where you put
> "alias :each1 :each", have it automatically create an alias
> ":old_methodname" whenever you overwrite an existing method (replace
> "methodname" with actual name").

I've done that sometimes (alias old_meth meth), but I wouldn't want it
happening automatically.  It would have the potential to clutter the
program space with methods I hadn't asked for and wouldn't need.


David

--
David A. Black
dblack@wobblini.net

"Ruby for Rails", from Manning Publications, coming April 2006!
http://www.manning.com/books/black
Fa0d14a176f060c96eef797fa48e6bcc?d=identicon&s=25 unknown (Guest)
on 2006-01-03 09:36
(Received via mailing list)
Simon Strandgaard <neoneye@gmail.com> wrote:

> class Array
>   alias :each1 :each
>   def each(&b)
>     each1{|i| b.call($i = i) }
>   end
> end
> %w(a b c).each{p $i}          #-> "a" "b" "c"


could I use this mechanisms for String ?

actually i've a function call :

s="Happy new year!"
s_utf8=to_UTF8(s)
p s_utf8

with :

def to_UTF8(s)
    return Iconv.new('UTF-8', 'MacRoman').iconv(s)
end

something like :

class String
    def to_utf8(s)
        return Iconv.new('UTF-8', 'MacRoman').iconv(s)
    end
end

p "Happy new year!".to_UTF8

does that make sense ?
82e62c756d89bc6fa0a0a2d7f2b1e617?d=identicon&s=25 Ross Bamford (Guest)
on 2006-01-03 10:45
(Received via mailing list)
On Mon, 02 Jan 2006 22:54:43 -0000, Dominik Bathon <dbatml@gmx.de>
wrote:

>
> And it seems to have been proposed before.
>
> I have actually implemented it for ruby 1.9 lately (it should work
> similar for 1.8). It's just a small patch for eval.c:
>
> ... [snipped patch] ...

Wicked :) I can confirm that seems to work in 1.8 (though I had to make
one change manually because the source is slightly different of course).
I
guessed it'd be something that would be reasonably easy (when you know
how
;)) from the C side.

FWIW +1 for inclusion in a future Ruby.

Cheers,
32edd0717b3144d5c58a352d613abdc9?d=identicon&s=25 gabriele renzi (Guest)
on 2006-01-03 13:39
(Received via mailing list)
Ross Bamford ha scritto:
>
> 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

eh, I alwaya thought the same.
And I just discovered that "it" is used in at least another environment:
AliceML seem to use it to mean "the result of the last expression",
similarly to how we use "_" in irb.

Isn't it nice to write
  x= 2+2
  print it

;)
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2006-01-03 14:31
(Received via mailing list)
Hi --

On Tue, 3 Jan 2006, Ross Bamford wrote:

>>
> change manually because the source is slightly different of course). I
> guessed it'd be something that would be reasonably easy (when you know how
> ;)) from the C side.
>
> FWIW +1 for inclusion in a future Ruby.

You can submit it as an RCR if you wish, at http://www.rcrchive.net.
(I'll vote "Strongly opposed", but don't let that stop you :-)


David

--
David A. Black
dblack@wobblini.net

"Ruby for Rails", from Manning Publications, coming April 2006!
http://www.manning.com/books/black
918c6daad03c85e51ad1a11f57017947?d=identicon&s=25 Devin Mullins (Guest)
on 2006-01-03 14:52
(Received via mailing list)
dblack@wobblini.net wrote:

> You can submit it as an RCR if you wish, at http://www.rcrchive.net.
> (I'll vote "Strongly opposed", but don't let that stop you :-)

For what it's worth, I'll probably only vote "neutral" for the lack of
readability it encourages (not naming the things). It's not as if people
name their variables "it" a lot... :)

Devin
32edd0717b3144d5c58a352d613abdc9?d=identicon&s=25 gabriele renzi (Guest)
on 2006-01-03 19:00
(Received via mailing list)
Devin Mullins ha scritto:


> For what it's worth, I'll probably only vote "neutral" for the lack of
> readability it encourages (not naming the things). It's not as if people
> name their variables "it" a lot... :)

True, but considering how often people write
  each {|x| stuff(x)}
I don't think it would be a great less in readability.
Not really advocating "it", but neither against it. No pun intended.
F3b7b8756d0c7f71cc7460cc33aefaee?d=identicon&s=25 Daniel Berger (Guest)
on 2006-01-03 19:00
(Received via mailing list)
gabriele renzi wrote:
> I don't think it would be a great less in readability.
> Not really advocating "it", but neither against it. No pun intended.

AGH! NOT THAT WORD!

- Knights of Ni
82e62c756d89bc6fa0a0a2d7f2b1e617?d=identicon&s=25 Ross Bamford (Guest)
on 2006-01-03 19:00
(Received via mailing list)
On Tue, 03 Jan 2006 13:52:03 -0000, Devin Mullins <twifkak@comcast.net>
wrote:

> dblack@wobblini.net wrote:

(David, can't see your message in the newsgroup, so I'll reply with this
one)

>>
>> You can submit it as an RCR if you wish, at http://www.rcrchive.net.
>> (I'll vote "Strongly opposed", but don't let that stop you :-)
>

Hmm, I might put together a bit of a proposal and do that. I hope you'll
comment when you vote no, I'd be interested in your perspective on this
:)

(Replying to Devin's message)

> For what it's worth, I'll probably only vote "neutral" for the lack of
> readability it encourages (not naming the things). It's not as if people
> name their variables "it" a lot... :)

Yeah, readability is a downside but I think with a name like 'it' it
would
mostly be pretty self evident, and of course it shouldn't preclude doing
it the current way (declaring the argument).

That was the reason I didn't mention another idea, about making $_ the
implicit block arg so you could do:

	['one','two','three'].select { ~/t[a-z]*/ }

(I don't actually advocate that but it occured while I was playing with
the 'it' thing).
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2006-01-03 19:00
(Received via mailing list)
Hi --

On Wed, 4 Jan 2006, Ross Bamford wrote:

>>>
>
> Hmm, I might put together a bit of a proposal and do that. I hope you'll
> comment when you vote no, I'd be interested in your perspective on this :)

I don't like it.  I've never felt there was a problem to solve in this
area, since it's so easy to specify an argument list.  Having a magic
variable ("it" or $_ or whatever) seems like a step backwards, in
terms of clarity and consistency.

I can't come up with a technical argument against it, since obviously
it can be done (as witness Perl and other languages).  It just strikes
me as needless, and very afterthought-like (in the sense that the fact
that blocks have named arguments always seemed to me to be what
happens *instead* of $_/it and @_ and so forth).


David

--
David A. Black
dblack@wobblini.net

"Ruby for Rails", from Manning Publications, coming April 2006!
http://www.manning.com/books/black
82e62c756d89bc6fa0a0a2d7f2b1e617?d=identicon&s=25 Ross Bamford (Guest)
on 2006-01-03 19:25
(Received via mailing list)
On Tue, 03 Jan 2006 17:26:15 -0000, <dblack@wobblini.net> wrote:

>>
>> Hmm, I might put together a bit of a proposal and do that. I hope
>> you'll comment when you vote no, I'd be interested in your perspective
>> on this :)
>
> I don't like it.  I've never felt there was a problem to solve in this
> area, since it's so easy to specify an argument list.  Having a magic
> variable ("it" or $_ or whatever) seems like a step backwards, in
> terms of clarity and consistency.
>

I do agree that from a readability point of view it's potentially
confusing, and newcomers to Ruby could look at it and wonder where the
hell 'it' came from. I think though that $_ is a different argument
(again, no pun intended), since that introduces stuff like:

	[1,2,3].each { print if ~/.../ }

which I couldn't convincingly argue for even were I paid to do so. This
kind of 'invisible data' confuses the hell out of me, and is IMHO one of
Perl's most evil features. On the other hand:

	[1,2,3].each { puts it if it =~ /.../ }

(again ignoring the TMTOWTDI aspect for the sake of example) at least
(to
me) implies some relationship between the message sent and the data - it
says to me "take each number from the array and output it if it matches
this". Granted, it's not vastly different from:

	[1,2,3].each { |it| puts it if it =~ /.../ }

but the extra 'it' (or whatever) in there just grates (admittedly only
slightly) on my nerves. It also gets a bit worse when you have stuff
like:

	[[1,2,3],[2,3,4],[3,4,5]].each { |it| it.select { |it| it % 2 == 0 } }
	[[1,2,3],[2,3,4],[3,4,5]].each { it.select { it % 2 == 0 } }

(I've not tested that btw but you get the idea). However I guess with
that
it's also potentially confusing when using the implicit idea, since it
has
the same magic variable meaning two different things in the same line. I
guess in this case I'd probably declare the argument in the select block
anyway (as 'i' or something).
32edd0717b3144d5c58a352d613abdc9?d=identicon&s=25 gabriele renzi (Guest)
on 2006-01-03 19:34
(Received via mailing list)
> I don't like it.  I've never felt there was a problem to solve in this
> area, since it's so easy to specify an argument list.  Having a magic
> variable ("it" or $_ or whatever) seems like a step backwards, in
> terms of clarity and consistency.

<ot>
eheh, I had this *exact* answer from a pythonista friend talking about
the mandatory naming of "self" in python methods :)
I guess it all comes down to taste.
</ot>
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2006-01-03 19:40
(Received via mailing list)
Hi --

On Wed, 4 Jan 2006, Ross Bamford wrote:

> 	[[1,2,3],[2,3,4],[3,4,5]].each { it.select { it % 2 == 0 } }
>
> (I've not tested that btw but you get the idea). However I guess with that
> it's also potentially confusing when using the implicit idea, since it has
> the same magic variable meaning two different things in the same line. I
> guess in this case I'd probably declare the argument in the select block
> anyway (as 'i' or something).

That's actually another good argument against "it": you'd be trampling
the outer it with the inner it.  And having to remember to declare the
inner argument to protect it from this really puts the whole thing in
the "added to the language as an afterthought" category.


David

--
David A. Black
dblack@wobblini.net

"Ruby for Rails", from Manning Publications, coming April 2006!
http://www.manning.com/books/black
682fff6db11e1a150d6ce17f3b862448?d=identicon&s=25 Doug H (Guest)
on 2006-01-03 21:24
(Received via mailing list)
For what it's worth, some of us proposed the same thing for the boo
language [1].  Also groovy has this feature [2].  (might be worth
putting in proposal that two other ruby & python inspired languages use
or want to use this, as well as AliceML)
Pnuts also has a related feature [3]:

print myitems[it % 2 == 0]

Essentially you can pass a boolean expression or a closure to an
indexer.  Above would return all even items.  I'm not proposing it for
ruby, just mentioning.  "it" is very powerful.
Comega (or c-omega from microsoft) also has this feature [4]

1.
http://groups.google.com/group/boolang/browse_frm/...
2. http://groovy.codehaus.org/Closures
3. http://pnuts.org/snapshot/latest/doc/lang.html
4. http://research.microsoft.com/Comega/
30a69d3e9ddb45dda39df00ca36a2eeb?d=identicon&s=25 Andrew McGuinness (Guest)
on 2006-01-03 21:59
(Received via mailing list)
gabriele renzi wrote:
 >
 > True, but considering how often people write
 >  each {|x| stuff(x)}
 > I don't think it would be a great less in readability.
 > Not really advocating "it", but neither against it. No pun intended.

Another way of dealing with it would be if it were easier to get from a
method to a Proc object, so instead of, say

heads = queues.map { |x| x.first }

You could have something more like:

heads = queues.map( &:first )

As with the "it" thing, you can do it for a specific method -

module Enumerable
    def map_method( method, *args )
      map { |x| x.send( method, *args ) }
    end
end

heads = queues.map_method( :first )

For  things.each { |x| stuff(x) }  it's possible in principle:

things.each( &method(:stuff).to_proc )

But that's not exactly a simplification - I'm hoping for something more
like lisp, where:

(setq heads (mapcar (lambda (x) (first x)) queues))

can be replaced exactly by:

(setq heads (mapcar #'first queues))


I don't know if there's a good way of doing what I want - Ruby is
fundamentally unlike lisp in that objects are more fundamental than
functions.  I think it would be possible to allow Symbol and Method as
alternatives to Proc in a "block" parameter, but I'm not sure it would
be a good idea.

heads = queues.map( &:first )

things.each( &method(:stuff) )
18ca239ffade6df0b839d26062f173fb?d=identicon&s=25 Dominik Bathon (Guest)
on 2006-01-03 22:00
(Received via mailing list)
On Tue, 03 Jan 2006 19:39:48 +0100, <dblack@wobblini.net> wrote:

>> in the select block anyway (as 'i' or something).
>
> That's actually another good argument against "it": you'd be trampling
> the outer it with the inner it.  And having to remember to declare the
> inner argument to protect it from this really puts the whole thing in
> the "added to the language as an afterthought" category.

With the patch I sent the outer "it" is not "overwritten" by the inner
"it", because it's a global function and not a variable and it always
returns the first argument of the current block (if none was given it
returns nil).

And for the other point: if it gets to complicated, just don't use "it"
and declare the argument(s).

Dominik
Cff9eed5d8099e4c2d34eae663aae87e?d=identicon&s=25 Jacob Fugal (Guest)
on 2006-01-03 22:09
(Received via mailing list)
On 1/3/06, Andrew McGuinness <a.mcguinness@ntlworld.com> wrote:
> Another way of dealing with it would be if it were easier to get from a
> method to a Proc object, so instead of, say
>
> heads = queues.map { |x| x.first }
>
> You could have something more like:
>
> heads = queues.map( &:first )

Take a look at this:

  http://blogs.pragprog.com/cgi-bin/pragdave.cgi/Tec...

Jacob Fugal
82e62c756d89bc6fa0a0a2d7f2b1e617?d=identicon&s=25 Ross Bamford (Guest)
on 2006-01-03 22:25
(Received via mailing list)
On Tue, 03 Jan 2006 18:39:48 -0000, <dblack@wobblini.net> wrote:

>> in the select block anyway (as 'i' or something).
>
> That's actually another good argument against "it": you'd be trampling
> the outer it with the inner it.  And having to remember to declare the
> inner argument to protect it from this really puts the whole thing in
> the "added to the language as an afterthought" category.
>

Hmm, I know. As I was writing it I started thinking about that and all
the
other little subtleties it could create. Generally I'm never happy with
a
solution that requires me to do more thinking :D. Based on the C-side
patch that was posted by Dominik Bathon the inner/outer it thing does
actually work, but isn't ideal from a readability perspective I guess.

(As an aside, with that patch the approach I suggested *doesn't* work,
since it doesn't check whether 'it' is already declared so tramples the
outer it even if you declare a block argument on the inner).

I'm not sure I understand the afterthought thing, though - wouldn't any
suggested enhancement that happened to be implemented now be an
afterthought? But anyhow this has snowballed a bit - originally I really
wanted a way to do it from the Ruby side, and more for fun than profit.
I've not been here long enough to start suggesting changes in Ruby
itself
but I just wondered if it'd been considered before...

Cheers,
82e62c756d89bc6fa0a0a2d7f2b1e617?d=identicon&s=25 Ross Bamford (Guest)
on 2006-01-03 22:25
(Received via mailing list)
On Tue, 03 Jan 2006 20:55:02 -0000, Andrew McGuinness
<a.mcguinness@ntlworld.com> wrote:

> heads = queues.map { |x| x.first }
>
> You could have something more like:
>
> heads = queues.map( &:first )
>

Hmm, check out http://extensions.rubyforge.org/rdoc/classes/Symbol.html
.
I'd not thought about it until now but it's actually a pretty good way
to
cut that verbosity in the simple cases..:

	require 'extensions/symbol'
	['one','two','three'].map &:upcase		# => ['ONE','TWO','THREE']

Nice one :)
30a69d3e9ddb45dda39df00ca36a2eeb?d=identicon&s=25 Andrew McGuinness (Guest)
on 2006-01-03 23:06
(Received via mailing list)
Jacob Fugal wrote:
>
>
> Take a look at this:
>
>   http://blogs.pragprog.com/cgi-bin/pragdave.cgi/Tec...
>
That's good - if I'm mad, at least I'm not alone.

And I didn't realise that  thing.each( &method(:stuff) )  works already
(the same as  thing.each( &method(:stuff).to_proc )  )
82e62c756d89bc6fa0a0a2d7f2b1e617?d=identicon&s=25 Ross Bamford (Guest)
on 2006-01-04 00:04
(Received via mailing list)
On Tue, 03 Jan 2006 22:01:02 -0000, Andrew McGuinness
<a.mcguinness@ntlworld.com> wrote:

>>> heads = queues.map( &:first )
>>   Take a look at this:
>>    http://blogs.pragprog.com/cgi-bin/pragdave.cgi/Tec...
>>
> That's good - if I'm mad, at least I'm not alone.
>
> And I didn't realise that  thing.each( &method(:stuff) )  works already
> (the same as  thing.each( &method(:stuff).to_proc )  )

:D

Yeah, AUIU '&' works a bit like splat but for procs (with to_proc). For
a
silly example:

	class String
	  def to_proc
	    lambda { eval self }
	  end
	end

	[1,2,3].each &"puts it"

gives:

	1
	2
	3

	=> [1, 2, 3]
Cff9eed5d8099e4c2d34eae663aae87e?d=identicon&s=25 Jacob Fugal (Guest)
on 2006-01-04 00:20
(Received via mailing list)
On 1/3/06, Ross Bamford <rosco@roscopeco.remove.co.uk> wrote:
>         1
>         2
>         3
>
>         => [1, 2, 3]

Except, of course, for the exception:

  NameError: undefined local variable or method `it'

;)

Jacob Fugal
82e62c756d89bc6fa0a0a2d7f2b1e617?d=identicon&s=25 Ross Bamford (Guest)
on 2006-01-04 00:48
(Received via mailing list)
On Tue, 03 Jan 2006 23:20:01 -0000, Jacob Fugal <lukfugl@gmail.com>
wrote:

>>
> ;)
>
> Jacob Fugal
>

Oops, yes I'm working with the Ruby I patched this morning... Sorry for
the confusion.
5d510f013e2e482e4a986ea015e7b212?d=identicon&s=25 Matthias Georgi (Guest)
on 2006-01-04 01:56
(Received via mailing list)
It is also possible to instance_eval a passed block, like:

module Enumerable
  def map_i(&block)
    map { |i| i.instance_eval(&block) }
  end
end

heads = queues.map_i { first }

Now the block is evaled in the scope of each item, which is a little
bit confusing, as you can't call methods of the surrounding scope.

I don't like the implicit 'it', because there are already enough things
to remember in ruby's syntax.
31ab75f7ddda241830659630746cdd3a?d=identicon&s=25 Austin Ziegler (Guest)
on 2006-01-04 20:03
(Received via mailing list)
On 03/01/06, Doug H <doug00@gmail.com> wrote:
> For what it's worth, some of us proposed the same thing for the boo
> language [1].  Also groovy has this feature [2].  (might be worth
> putting in proposal that two other ruby & python inspired languages use
> or want to use this, as well as AliceML)
> Pnuts also has a related feature [3]:

None of which I think is actually a reason for Ruby to get it.

I am in the "opposed" camp on this, because I think that it will
result in less-readable code overall.

-austin
This topic is locked and can not be replied to.