tags:

views:

278

answers:

3
+17  Q: 

When to use blocks

I love Ruby blocks! The idea behind them is just very very neat and convenient.

I have just looked back over my code from the past week or so, which is basically every single ruby function I ever have written, and I have noticed that not a single one of them returns a value! Instead of returning values, I always use a block to pass the data back!

I have even caught myself contemplating writing a little status class which would allow me to write code like :

something.do_stuff do |status|
  status.success do 
    # successful code
  end

  status.fail do
    # fail code
    puts status.error_message
  end
end

Am I using blocks too much? Is there a time to use blocks and a time to use return values?

Are there any gotchas to be aware of? Will my huge use of blocks come and bite me sometime?

+3  A: 

I like this style. It's actually very Ruby-like, and often you'll see projects restructure their code to use this format instead of something less readable.

Returning values makes sense where returning values makes sense. If you have an Article object, you want article.title to return the title. But for this particular example of callbacks, it's stellar style, and it's good that you know how to use them. I suspect that many new to Ruby will never figure out how to do it well.

Matchu
Yup, a good example where returning a value is obviously better than blocks!
Mongus Pong
+9  A: 

This is what functional programming people call "continuation-passing style". It's a valid technique, though there are cases where it will tend to complicate things more than it's worth. It might be worth to relook some of the places where you're using it and see if that's the case in your code. But there's nothing inherently wrong with it.

Chuck
Who downvoted this without comment? This *is* continuation-passing style, and it *is* an accepted way of structuring code in the right circumstances. I don't mean "accepted by me" — I mean, like, "this is a technique that has been used by well-respected computer scientists since before many people on this site were born."
Chuck
+1 from me . . .
klochner
I just really want to know what the objection is. As far as I know, my answer is as close to fact (rather than opinion) as it could possibly be.
Chuck
I see no reason for a downvote here! You taught me something. Thanks! ;-)
Mongus Pong
+12  A: 
klochner
+1. I agree. I think blocks in the OP's example is not 'good ruby style' but blocks gone mad...
Peter
Blocks also appear frequently in DSL's, where they are used to encapsulate a scope (rake) or to make the code read more like a natural language (rspec).
Wayne Conrad
I don't like the `if do_something_with_side_effects_and_possibly_long_delays` idiom. The block-based callback is nice because it separates methods based around side effects from methods based around computations, for one. It will also become more useful as parallelism becomes a bigger deal — the CPS version allows `do_stuff` to execute asynchronously and still have the succeed-fail logic called after it knows whether it's succeeded.
Chuck
valid point, but certainly you don't agree with status.success { some_fn() }
klochner
As a general rule, no, that's not very idiomatic in Ruby.
Chuck
@klochner, yup some excellent points there! I think you may have missed that the status object in the block contains more than just success and failure - it also contains an error message. So returning a simple boolean would cut out some of the possible functionality.
Mongus Pong
@Peter, why is it blocks gone mad? Is it just readability or is there something else?
Mongus Pong
@Pongus: it's blocks for the sake of blocks, rather than blocks for the good reasons above. There's nothing wrong with blocks when they're useful, but as @klochner said, don't use blocks just because you can.
Peter
@Peter, I hear ya!
Mongus Pong
@Pongus - see my new example
klochner
@klochner, Excellent! That sums it all up nicely and makes a lot of sense. Thanks! :)
Mongus Pong