Yield does not take a block

Under ruby 1.9.0 (2005-06-23) [i386-linux], irb 0.9.5(05/04/13),
these forms are not permitted:

    yield { .. }
    yield &..

But these are okay:

    Proc.new.call { .. }
    Proc.new.call &..

This is an oversight, right?

···

--
Daniel Brockman <daniel@brockman.se>

Hi,

At Tue, 28 Jun 2005 17:37:06 +0900,
Daniel Brockman wrote in [ruby-talk:146630]:

Under ruby 1.9.0 (2005-06-23) [i386-linux], irb 0.9.5(05/04/13),
these forms are not permitted:

    yield { .. }
    yield &..

But these are okay:

    Proc.new.call { .. }
    Proc.new.call &..

This is an oversight, right?

Right.

Index: eval.c

···

===================================================================
RCS file: /cvs/ruby/src/ruby/eval.c,v
retrieving revision 1.791
diff -U2 -p -r1.791 eval.c
--- eval.c 20 Jun 2005 09:59:58 -0000 1.791
+++ eval.c 28 Jun 2005 10:29:44 -0000
@@ -3201,4 +3201,18 @@ rb_eval(self, n)
       result = Qundef; /* no arg */
   }
+ if (node->nd_body) {
+ PUSH_BLOCK(0, 0);
+ if ((state = EXEC_TAG()) == 0) {
+ struct BLOCK *prev = ruby_block->prev;
+ *ruby_block = *prev;
+ ruby_block->prev = prev;
+ ruby_block->block_obj = rb_eval(self, node->nd_body);
+ SET_CURRENT_SOURCE();
+ result = rb_yield_0(result, 0, 0, YIELD_PROC_CALL, node->nd_state);
+ }
+ POP_BLOCK();
+ if (state) rb_jump_tag(state);
+ break;
+ }
   SET_CURRENT_SOURCE();
   result = rb_yield_0(result, 0, 0, 0, node->nd_state);
Index: parse.y

RCS file: /cvs/ruby/src/ruby/parse.y,v
retrieving revision 1.387
diff -U2 -p -r1.387 parse.y
--- parse.y 12 Jun 2005 16:56:05 -0000 1.387
+++ parse.y 28 Jun 2005 10:15:29 -0000
@@ -231,5 +231,5 @@ static void void_stmts_gen _((struct par
#define void_stmts(node) void_stmts_gen(parser, node)
static void reduce_nodes _((NODE**));
-static void block_dup_check _((NODE*));
+static NODE *add_iter_block _((NODE*,NODE*));

static NODE *block_append _((NODE*,NODE*));
@@ -1138,7 +1138,5 @@ command : operation command_args
       $$ = new_fcall($1, $2);
       if ($3) {
- block_dup_check($$);
- $3->nd_iter = $$;
- $$ = $3;
+ $$ = add_iter_block($$, $3);
       }
             fixpos($$, $2);
@@ -1162,7 +1160,5 @@ command : operation command_args
       $$ = new_call($1, $3, $4);
       if ($5) {
- block_dup_check($$);
- $5->nd_iter = $$;
- $$ = $5;
+ $$ = add_iter_block($$, $5);
       }
             fixpos($$, $1);
@@ -1186,7 +1182,5 @@ command : operation command_args
       $$ = new_call($1, $3, $4);
       if ($5) {
- block_dup_check($$);
- $5->nd_iter = $$;
- $$ = $5;
+ $$ = add_iter_block($$, $5);
       }
             fixpos($$, $1);
@@ -2561,28 +2555,4 @@ primary : literal
         %*/
         }
- | kYIELD '(' call_args rparen
- {
- /*%%%*/
- $$ = new_yield($3);
- /*%
- $$ = dispatch1(yield, dispatch1(paren, $3));
- %*/
- }
- | kYIELD '(' rparen
- {
- /*%%%*/
- $$ = NEW_YIELD(0, Qfalse);
- /*%
- $$ = dispatch1(yield, dispatch1(paren, arg_new()));
- %*/
- }
- | kYIELD
- {
- /*%%%*/
- $$ = NEW_YIELD(0, Qfalse);
- /*%
- $$ = dispatch0(yield0);
- %*/
- }
     > kDEFINED opt_nl '(' {in_defined = 1;} expr rparen
         {
@@ -2610,7 +2580,5 @@ primary : literal
         {
         /*%%%*/
- block_dup_check($$);
- $2->nd_iter = $1;
- $$ = $2;
+ $$ = add_iter_block($1, $2);
             fixpos($$, $1);
         /*%
@@ -3215,7 +3183,5 @@ block_call : command do_block
         {
         /*%%%*/
- block_dup_check($1);
- $2->nd_iter = $1;
- $$ = $2;
+ $$ = add_iter_block($1, $2);
             fixpos($$, $1);
         /*%
@@ -3296,4 +3262,20 @@ method_call : operation paren_args
         %*/
         }
+ | kYIELD paren_args
+ {
+ /*%%%*/
+ $$ = new_yield($2);
+ /*%
+ $$ = dispatch1(yield, dispatch1(paren, $2));
+ %*/
+ }
+ | kYIELD
+ {
+ /*%%%*/
+ $$ = NEW_YIELD(0, Qfalse);
+ /*%
+ $$ = dispatch0(yield0);
+ %*/
+ }
     > tLPAREN compstmt ')' paren_args
         {
@@ -7212,11 +7194,22 @@ aryset_gen(parser, recv, idx)
}

-static void
-block_dup_check(node)
- NODE *node;
+static NODE *
+add_iter_block(node, block)
+ NODE *node, *block;
{
- if (node && nd_type(node) == NODE_BLOCK_PASS) {
- compile_error(PARSER_ARG "both block arg and actual block given");
+ if (node) {
+ switch (nd_type(node)) {
+ case NODE_YIELD:
+ if (!node->nd_body) {
+ nd_set_type(block, NODE_LAMBDA);
+ node->nd_body = block;
+ return node;
+ }
+ case NODE_BLOCK_PASS:
+ compile_error(PARSER_ARG "both block arg and actual block given");
+ }
     }
+ block->nd_iter = node;
+ return block;
}

@@ -7794,13 +7787,22 @@ new_yield(node)
{
     long state = Qtrue;
+ NODE *body = 0;

     if (node) {
- no_blockarg(node);
- if (nd_type(node) == NODE_ARRAY && node->nd_next == 0) {
+ switch (nd_type(node)) {
+ case NODE_BLOCK_PASS:
+ body = node;
+ node = node->nd_iter;
+ nd_set_type(body, NODE_LAMBDA);
+ body->nd_iter = 0;
+ break;
+ case NODE_ARRAY:
+ if (node->nd_next != 0) break;
             node = node->nd_head;
             state = Qfalse;
- }
- else if (node && nd_type(node) == NODE_SPLAT) {
+ break;
+ case NODE_SPLAT:
             state = Qtrue;
+ break;
         }
     }
@@ -7808,5 +7810,7 @@ new_yield(node)
         state = Qfalse;
     }
- return NEW_YIELD(node, state);
+ node = NEW_YIELD(node, state);
+ node->nd_body = body;
+ return node;
}

--
Nobu Nakada

Hi,

···

In message "Re: yield does not take a block" on Tue, 28 Jun 2005 17:37:06 +0900, Daniel Brockman <daniel@brockman.se> writes:

Under ruby 1.9.0 (2005-06-23) [i386-linux], irb 0.9.5(05/04/13),
these forms are not permitted:

   yield { .. }
   yield &..

But these are okay:

   Proc.new.call { .. }
   Proc.new.call &..

This is an oversight, right?

yield is a keyword to pass a value (and control) to the block attached
to the method. I feel strange when I see yield passes a block to an
outer block.

              matz.

Yukihiro Matsumoto wrote:
...

yield is a keyword to pass a value (and control) to the block attached
to the method. I feel strange when I see yield passes a block to an
outer block.

Is that good strange or bad strange?

James

···

--
http://www.ruby-doc.org - The Ruby Documentation Site
http://www.rubyxml.com - News, Articles, and Listings for Ruby & XML
http://www.rubystuff.com - The Ruby Store for Ruby Stuff
http://www.jamesbritt.com - Playing with Better Toys

Yukihiro Matsumoto <matz@ruby-lang.org> writes:

yield is a keyword to pass a value (and control) to the block
attached to the method. I feel strange when I see yield passes a
block to an outer block.

I feel strange when I see these are not equivalent:

  def foo1 &block
    block.call &bar
  end

  def foo2
    Proc.new.call &bar
  end

  def foo3 &block
    yield &bar
  end

The middle one may be a weird idiom that should be phased out, but I
really think that calling a block captured into a variable should be
equivalent to using yield.

If foo1 and foo3 are not equivalent, then we have an inconsistency.

···

--
Daniel Brockman <daniel@brockman.se>

Hi,

···

In message "Re: yield does not take a block" on Wed, 29 Jun 2005 00:49:17 +0900, James Britt <james_b@neurogami.com> writes:

yield is a keyword to pass a value (and control) to the block attached
to the method. I feel strange when I see yield passes a block to an
outer block.

Is that good strange or bad strange?

I feel bad strange. Do you?

              matz.

Hi,

I feel strange when I see these are not equivalent:

def foo1 &block
   block.call &bar
end

def foo2
   Proc.new.call &bar
end

def foo3 &block
   yield &bar
end

If foo1 and foo3 are not equivalent, then we have an inconsistency.

Indeed we have inconsistency here if those two are not equivalent, but
I don't think consistency matters most in this case. Using yield
emphasizes passing a value and control to a block given to the method.
On the other hand, "call"ing an block argument (&block) emphasizes
treating a block as a procedural object. If they are focusing
different aspect, they might not be exact same.

It's not a technical issue. Just a matter of how we feel when we see

  yield &bar

or

  yield {...}

I feel something strange (bad strange) when I see this, just because
it passes a block to another block, which is apparently strange,
whereas

  block.call &bar

does not make me feel bad strange, since it is valid syntax in the
microscopic view, even when it is semantically strange.

If you have shown me the reason "yield &bar" is not strange (and is
useful) other than consistency, I'd be glad to apply the Nobu's patch
in [ruby-talk:146636].

              matz.

···

In message "Re: yield does not take a block" on Wed, 29 Jun 2005 02:30:05 +0900, Daniel Brockman <daniel@brockman.se> writes:

Yukihiro Matsumoto wrote:

Hi,

>> yield is a keyword to pass a value (and control) to the block attached
>> to the method. I feel strange when I see yield passes a block to an
>> outer block.
>
>Is that good strange or bad strange?

I feel bad strange. Do you?

No. Good strange.

James

···

In message "Re: yield does not take a block" > on Wed, 29 Jun 2005 00:49:17 +0900, James Britt <james_b@neurogami.com> writes:

I tend to agree that the yield should be made consistent with
block.call such that yield would basically be just an alias for
block.call (where block is the block given to the current
method). I think any keyword that can reasonably be made to
look like a method call, should. Makes the syntax more
consistent. If you were starting over, I'd even suggest things
like if/while to be like (or actually) method calls.

but...

Personally, I don't think having yield as a keyword really adds
that much value to the language. The only advantages I see
over explicitly having a &block arg and using block.call are a)
it looks like smalltalk, and b) rdoc parses it better. I think
showing the &block on the def line makes the method interface
clearer up front. I don't use yield at all and haven't missed
it.

···

--- Yukihiro Matsumoto <matz@ruby-lang.org> wrote:

Hi,

In message "Re: yield does not take a block" > on Wed, 29 Jun 2005 02:30:05 +0900, Daniel Brockman > <daniel@brockman.se> writes:

>I feel strange when I see these are not equivalent:
>
> def foo1 &block
> block.call &bar
> end
>
> def foo2
> Proc.new.call &bar
> end
>
> def foo3 &block
> yield &bar
> end

>If foo1 and foo3 are not equivalent, then we have an
inconsistency.

Indeed we have inconsistency here if those two are not
equivalent, but
I don't think consistency matters most in this case. Using
yield
emphasizes passing a value and control to a block given to
the method.
On the other hand, "call"ing an block argument (&block)
emphasizes
treating a block as a procedural object. If they are
focusing
different aspect, they might not be exact same.

It's not a technical issue. Just a matter of how we feel
when we see

  yield &bar

or

  yield {...}

I feel something strange (bad strange) when I see this, just
because
it passes a block to another block, which is apparently
strange,
whereas

  block.call &bar

does not make me feel bad strange, since it is valid syntax
in the
microscopic view, even when it is semantically strange.

If you have shown me the reason "yield &bar" is not strange
(and is
useful) other than consistency, I'd be glad to apply the
Nobu's patch
in [ruby-talk:146636].

              matz.

__________________________________
Do you Yahoo!?
Yahoo! Mail - Find what you need with new enhanced search.
http://info.mail.yahoo.com/mail_250

Hi,

···

Am Mittwoch, 29. Jun 2005, 01:19:16 +0900 schrieb Yukihiro Matsumoto:

In message "Re: yield does not take a block" > on Wed, 29 Jun 2005 00:49:17 +0900, James Britt <james_b@neurogami.com> writes:

>> yield is a keyword to pass a value (and control) to the block attached
>> to the method. I feel strange when I see yield passes a block to an
>> outer block.
>
>Is that good strange or bad strange?

I feel bad strange. Do you?

Logic demands to allow it. Prohibiting it would mean to
introduce an exception rule (POLS?).

Anyway, the programmer should be saved from fooling himself
inventing more and more complicated constructions.

Bad strange.

Bertram

--
Bertram Scharpf
Stuttgart, Deutschland/Germany
http://www.bertram-scharpf.de

Yukihiro Matsumoto <matz@ruby-lang.org> writes:

If you have shown me the reason "yield &bar" is not strange (and is
useful) other than consistency, I'd be glad to apply the Nobu's
patch in [ruby-talk:146636].

I don't have any other reason than consistency. Having used Ruby 1.8
up until yesterday, yield and Proc.new.call are equivalent in my mind.
It seems I will have to drop that identification when moving to 1.9.

The fact that blocks cannot take blocks pre-1.9 has always bugged me,
and I certainly don't think there's anything strange about this code:

    define_method :foo do |*args, &block| ... end

However, I agree that most uses of these metablocks (if you will)
probably do not coincide with the use cases of the yield keyword.

So I will not be upset if Nobu's patch is not applied. I will just
make a mental note that Yield Does Not Take a Block and move on.
Should I ever be tempted to pass a block to yield, I will remember
that it doesn't work, and simply call the block explicitly instead.

I guess the reason why yield &block is not strange to me is that the
yield statement yields values, and blocks are just special values.

···

--
Daniel Brockman <daniel@brockman.se>

Eric Mahurin said:

I tend to agree that the yield should be made consistent with
block.call such that yield would basically be just an alias for
block.call (where block is the block given to the current
method). I think any keyword that can reasonably be made to
look like a method call, should. Makes the syntax more
consistent. If you were starting over, I'd even suggest things
like if/while to be like (or actually) method calls.

Though I understand matz's seeing the yielding of a block as a bad kind of
strangeness, I do think consistency is good. If yield and block.call are
different in any way that could be confusing, especially to all these new
Ruby users we've been getting lately. So I agree with Eric here.

I still would like to see a case where a block is yielded, and just how
that would be used. Sounds like potentially confusing code to me.

I also like the idea of if and while being methods, just as long as the
current syntax sugar is maintained.

Personally, I don't think having yield as a keyword really adds
that much value to the language. The only advantages I see
over explicitly having a &block arg and using block.call are a)
it looks like smalltalk, and b) rdoc parses it better. I think
showing the &block on the def line makes the method interface
clearer up front. I don't use yield at all and haven't missed
it.

I like yield as a keyword, and I think the only reason to use &block is
when you want to save the given block or do some other manipulation on it
(ask for its arity, etc.) It is a lot of extra typing to use an &block
parameter than just calling yield, especially if all you want to do is
yield a value. Conceptually I think the idea of 'yield'ing control to a
block is nice (though I suppose the idea of 'call'ing a block is just as
nice.) But I still don't think yield should be tossed (not that matz ever
would.)

Ryan

Bertram Scharpf wrote:

Hi,

yield is a keyword to pass a value (and control) to the block attached
to the method. I feel strange when I see yield passes a block to an
outer block.

Is that good strange or bad strange?

I feel bad strange. Do you?

Logic demands to allow it. Prohibiting it would mean to
introduce an exception rule (POLS?).

There's a lot to be said for consistency in a language, to avoid the complexity introduced by "This is the case, except when it's not."

Ruby has fairly few of these instances, which is part of its appeal for me.

It's nice to be able to layout a small set of ground rules and say that everything you can derive from them is valid.

Anyway, the programmer should be saved from fooling himself
inventing more and more complicated constructions.

Saved in what way?

Languages should be designed to enable developers, not protect them from themselves.

James

···

Am Mittwoch, 29. Jun 2005, 01:19:16 +0900 schrieb Yukihiro Matsumoto:

In message "Re: yield does not take a block" >> on Wed, 29 Jun 2005 00:49:17 +0900, James Britt <james_b@neurogami.com> writes:

--

http://www.ruby-doc.org - The Ruby Documentation Site
http://www.rubyxml.com - News, Articles, and Listings for Ruby & XML
http://www.rubystuff.com - The Ruby Store for Ruby Stuff
http://www.jamesbritt.com - Playing with Better Toys

Eric Mahurin wrote:

···

--- Yukihiro Matsumoto <matz@ruby-lang.org> wrote:

Hi,

In message "Re: yield does not take a block" >> on Wed, 29 Jun 2005 02:30:05 +0900, Daniel Brockman >> <daniel@brockman.se> writes:

I feel strange when I see these are not equivalent:

def foo1 &block
   block.call &bar
end

def foo2
   Proc.new.call &bar
end

def foo3 &block
   yield &bar
end

If foo1 and foo3 are not equivalent, then we have an inconsistency.

Indeed we have inconsistency here if those two are not
equivalent, but
I don't think consistency matters most in this case. Using
yield
emphasizes passing a value and control to a block given to
the method.
On the other hand, "call"ing an block argument (&block)
emphasizes
treating a block as a procedural object. If they are
focusing
different aspect, they might not be exact same.

It's not a technical issue. Just a matter of how we feel
when we see

  yield &bar

or

  yield {...}

I feel something strange (bad strange) when I see this, just
because
it passes a block to another block, which is apparently
strange,
whereas

  block.call &bar

does not make me feel bad strange, since it is valid syntax
in the
microscopic view, even when it is semantically strange.

If you have shown me the reason "yield &bar" is not strange
(and is
useful) other than consistency, I'd be glad to apply the
Nobu's patch
in [ruby-talk:146636].

matz.

I tend to agree that the yield should be made consistent with
block.call such that yield would basically be just an alias for
block.call (where block is the block given to the current
method). I think any keyword that can reasonably be made to
look like a method call, should. Makes the syntax more
consistent. If you were starting over, I'd even suggest things
like if/while to be like (or actually) method calls.

but...

Personally, I don't think having yield as a keyword really adds
that much value to the language. The only advantages I see
over explicitly having a &block arg and using block.call are a)
it looks like smalltalk, and b) rdoc parses it better. I think
showing the &block on the def line makes the method interface
clearer up front. I don't use yield at all and haven't missed
it.

Note though that yield and &c.call work quite differently. This has for
example performance implications.

Kind regards

    robert

Eric Mahurin wrote:

Personally, I don't think having yield as a keyword really adds
that much value to the language. The only advantages I see
over explicitly having a &block arg and using block.call are a)
it looks like smalltalk, and b) rdoc parses it better. I think
showing the &block on the def line makes the method interface
clearer up front. I don't use yield at all and haven't missed
it.

I completely agree with this. I think closures are one of the most useful features of Ruby, but I still don't understand what the point of having blocks and yield is. In all other languages I've used that have closures, such as Scheme, ML, Haskell, OCaml, and even Javascript, a closure is just an object like any other object, that happens to have a special literal syntax for creating them. If you want to pass a closure to another function, you just pass it like any other argument.

The way ruby does it with blocks/yield has several disadvantages:

1) There's an arbitrary limit of 1 on the number of blocks you can pass to a function. If you want to pass more than 1, you need to convert all but the last block to a proc.

2) The block argument can be implicit, so you can't see from the function signature that there is a block argument.

3) You get a problem akin to Java's primitive/Object separation, where in some contexts you need a block, and have to convert another callable object to a block, and in other contexts you need a proc, and have to convert a block to a proc.

Let me expand on the last item. In functional languages like Scheme, ML, or Haskell, all functions are closures, whether they're named or anonymous, and can be used interchangeably. So, say I wanted to apply a function to each element of a list, I'd write something like this in ML:

     for_each myArray print

for_each takes a list as its first argument, and a function with 1 parameter as its second argument, and applies the function to each element of the list. In Ruby, since there's a distinction between blocks, closures, and functions, I can't just pass print, even though it's a function of 1 parameter. Rather I have to wrap print in a block:

     myArray.each { |elem| print elem }

Wouldn't it have been cool to just be able to write:

     myArray.each print

Overall, it's not a big problem, but I do think the fact that there's a distinction between blocks, procs, and functions is one of the main warts in the Ruby language.

Adam

* Ryan Leavengood <mrcode@netrox.net> [2005-06-29 05:49:45 +0900]:

I like yield as a keyword, and I think the only reason to use &block is
when you want to save the given block or do some other manipulation on it
(ask for its arity, etc.) It is a lot of extra typing to use an &block
parameter than just calling yield, especially if all you want to do is
yield a value. Conceptually I think the idea of 'yield'ing control to a
block is nice (though I suppose the idea of 'call'ing a block is just as
nice.) But I still don't think yield should be tossed (not that matz ever
would.)

The implicit passing of a block (that follows a method call) and
the 'yield' keyword is one of the key signatures of Ruby and one
that gives Ruby a great deal of power with very little typing.

If we had the principle of absolute explicitness for everything,
then it would be more difficult to write DSL's and we wouldn't
have nice apps like rails. In fact, we would probably even have
to add statement ending identifiers, like semicolons....run away run away...

···

--
Jim Freeze

I didn't know about this advantage. From my quick benchmarks,
I found yield to take half the time as Proc#call in a loop with
the block being empty. I'd imagine the performance difference
is because yield is working with a statically typed Proc,
whereas call is using a normal dynamically typed object to
#call. I'd imagine as ruby matures, the performance difference
between these two would become negligible or zero. I'd hope at
some point ruby would make optimizations when it knows the
exact class of an object - do method lookup at compile time.

···

--- Robert Klemme <bob.news@gmx.net> wrote:

Note though that yield and &c.call work quite differently.
This has for example performance implications.

__________________________________
Yahoo! Mail Mobile
Take Yahoo! Mail with you! Check email on your mobile phone.
http://mobile.yahoo.com/learn/mail

Yes, but consider this:

irb(main):001:0> def display x
irb(main):002:1> puts x
irb(main):003:1> end
=> nil
irb(main):004:0> (1..5).each &method(:display)
1
2
3
4
5
=> 1..5
irb(main):005:0>

Kent.

···

On 6/29/05, Adam P. Jenkins <thorin@theshire.com> wrote:

Eric Mahurin wrote:
> Personally, I don't think having yield as a keyword really adds
> that much value to the language. The only advantages I see
> over explicitly having a &block arg and using block.call are a)
> it looks like smalltalk, and b) rdoc parses it better. I think
> showing the &block on the def line makes the method interface
> clearer up front. I don't use yield at all and haven't missed
> it.

I completely agree with this. I think closures are one of the most
useful features of Ruby, but I still don't understand what the point of
having blocks and yield is. In all other languages I've used that have
closures, such as Scheme, ML, Haskell, OCaml, and even Javascript, a
closure is just an object like any other object, that happens to have a
special literal syntax for creating them. If you want to pass a closure
to another function, you just pass it like any other argument.

The way ruby does it with blocks/yield has several disadvantages:

1) There's an arbitrary limit of 1 on the number of blocks you can pass
to a function. If you want to pass more than 1, you need to convert all
but the last block to a proc.

2) The block argument can be implicit, so you can't see from the
function signature that there is a block argument.

3) You get a problem akin to Java's primitive/Object separation, where
in some contexts you need a block, and have to convert another callable
object to a block, and in other contexts you need a proc, and have to
convert a block to a proc.

Let me expand on the last item. In functional languages like Scheme,
ML, or Haskell, all functions are closures, whether they're named or
anonymous, and can be used interchangeably. So, say I wanted to apply a
function to each element of a list, I'd write something like this in ML:

     for_each myArray print

for_each takes a list as its first argument, and a function with 1
parameter as its second argument, and applies the function to each
element of the list. In Ruby, since there's a distinction between
blocks, closures, and functions, I can't just pass print, even though
it's a function of 1 parameter. Rather I have to wrap print in a block:

     myArray.each { |elem| print elem }

Wouldn't it have been cool to just be able to write:

     myArray.each print

Overall, it's not a big problem, but I do think the fact that there's a
  distinction between blocks, procs, and functions is one of the main
warts in the Ruby language.

Adam

The reason you can't is because a method name by itself calls
the method instead of returning the method object. If you had
to put () to make the call and the method name by itself
returned the method object (I would have preferred that), you
could do this:

myArray.each(&print)

but, this should work fine right now:

myArray.each(&method(:print))

···

--- "Adam P. Jenkins" <thorin@theshire.com> wrote:

Rather I have to wrap print
in a block:

     myArray.each { |elem| print elem }

Wouldn't it have been cool to just be able to write:

     myArray.each print

__________________________________
Discover Yahoo!
Have fun online with music videos, cool games, IM and more. Check it out!
http://discover.yahoo.com/online.html

"Adam P. Jenkins" <thorin@theshire.com> writes:

In all other languages I've used that have closures, such as Scheme,
ML, Haskell, OCaml, and even Javascript, a closure is just an object
like any other object, that happens to have a special literal syntax
for creating them.

[...]

The way ruby does it with blocks/yield has several disadvantages:

1) There's an arbitrary limit of 1 on the number of blocks you can
   pass to a function. If you want to pass more than 1, you need to
   convert all but the last block to a proc.

The languages you mentioned above all have this ``arbitrary limit.''
Consider O'Caml. You can only give one block to the `fun' keyword.
Or JavaScript. Certainly, the `function' keyword only takes one
argument list and one code block.

In fact, these languages have the additional ``arbitrary limit'' that
code blocks cannot be passed to user-defined methods.

What I mean is that Ruby allows this,

   lambda { |a, b, c| ... }

as well as this

   moomin { |a, b, c| ... }

and this ---

   snufkin foo, bar do |a, b, c| ... end

Heck, Ruby 1.9 even allows this shorthand for lambdas,

   { |a, b, c| ... }

but that's beside the point. The point is that JavaScript only
allows this:

   function (a, b, c) { ... }

That is to say, you cannot define `moomin' in a way that makes this
valid JavaScript code:

   moomin (a, b, c) { ... }

The same goes for all the other languages. (Well, except for Scheme,
which really actually lets you define arbitrary syntactic forms, but
we all know that Lisp is inherently superior to everything else, so I
will just pretend you didn't mention it.)
   
Clearly, when it comes to blocks, Ruby's syntax is far more general
than that of other mortal (i.e., non-Lisp) languages.

While a JavaScript programmer would go like this,

   array.sort(function (a, b) { ... })

a Ruby programmer could go like this ---

   array.sort &lambda { |a, b| ... }

that would be the literal translation. But Ruby takes another step;
it lets you give code blocks directly to _any_ method,

   array.sort { |a, b| ... }

not just `lambda'. This is _better_ than most languages can do.

···

--
Daniel Brockman <daniel@brockman.se>