You'll miss composable functions

jjore on 2009-07-24T20:34:11

In perl or almost any other functional language (I guess) you can combine functions together and the innards of one thing aren't going to affect the flow control of the other. Here's a simple bit of perl:

method trap (CodeRef $block) {
    $block->() }
    uffda(); # Called in Perl, not called in Ruby
}

method moo ( ... ) { trap( sub {

# Early return because ... return ... if ...;

... } ); }


Writing the equivalent flow control in Ruby and I found out today that the return() calls go all the way through and past the wrapping "trap" function.

WTF? I don't think I understand how Ruby programmers put up with this. Maybe 1.9 is better about this.


Block/Proc

chromatic on 2009-07-24T21:39:19

I don't have time to experiment myself, but is this the difference between a Block and a Proc again?

Re:Block/Proc

erikh on 2009-07-24T22:51:34

It's more-or-less the equivalent of: map { return; } @array

The inline block returns to the previous position in the call stack, which is not the method the map was placed in, but the method above that.

Re:Block/Proc

jjore on 2009-07-25T00:15:10

Oops, yes. So I just learned that blocks aren't functions even though they syntactically look like them. Apparently this would have worked just fine if I'd passed a proc{} in and use .call on it instead.

I'm not sure why Rubyists accept blocks the way they are.

Heck, why do perlers except that map and grep's little lambdas don't treat return() properly?

The Reason Why (I Think)

frew on 2009-07-24T23:55:46

With perl, a coderef is a subroutine, basically.  With rubies coderefs, they are more like perl's blocks:

use feature ':5.10';
sub foo {
   say 'beginning of foo';
   bar();
   say 'ending of foo';
}

sub bar {
   say 'beginning of bar';
   my @foo = grep { return } (1,2,3,4); # I'd say this should mean none
   say 'ending of bar';
}

foo();

Note that the grep kills bar.