On semantic Ruby block constructs

I was cruising around my Github notifications and I found an interesting open issue created by Jim Weirich : “The Semantic Rule for { } VS do/end” in the Ruby style guide repository .

The semantic rule says use { } for blocks where the primary purpose of the block is to return a value, use do/end for blocks where the primary purpose of the block is to execute side effects.

The main issue with this rule is that it implies the existence of some cases when one must use do/end on a single line. So what's the problem with this ? Well, most will argue it's not very good looking, it's verbose and it feels a bit hacky e.g. :

# one-liner that abides to the semantic rule
(1..10).each do |i| some_instance.side_effect = i end

versus :

# idiomatic Ruby one-liner
(1..10).each { |i| some_instance.side_effect = i } 

I would say the difference is not that big and by abiding to the semantic rule one could make code more readable. Moreover it's not only about the aesthetics of code but also on its inherent semantics.

This can branch out in two directions : good i.e. improves codes readability or bad i.e. it might be confusing to developers that don't know how to interpret it.

This can also be applied to the lambda notation :

-> { ... }
->(obj) { ... }

versus

-> do ... end
->(obj) do ... end

Lambdas have one more semantic bagagge so to say: I usually use them to do some computation and return the result to be used somewhere else without creating side-effects for everything else procs are better suited.

One could argue that the { } VS do/end distinction is superfluous for lambdas.

Pondering on it, the visual difference doesn't seem colossal so I think I'll adhere to this rule in my codebases from now on.

Credits :

Tagged under: