Conventions in ruby and the principle of least surprise

E

Einar Boson

Hi guys, and hi Matz. I have a few questions about ruby syntax and
library that so far has had me surprised. I know Matz doesn't say that
ruby shouldn't surprise me, but rather not surprise him but still, i
would like to hear the reasoning behind a few weird things:

do..end vs. {}

Say I have this function:

def save_block name, &b
@blocks ||= {}
@blocks[name] = b
end

Now this is fine:

save_block :say_hello do
puts "hello!"
end

but not this:

save_block :say_hello {
puts "hello!"
}

I find that rather annoying but I guess it's to be able to write things
like

save_block ["name1_long", "name2_long", "short"].find {|n| n.size <=
5}.to_sym do
puts "hello!"
end

Personally I would rather have had to use parentheses to bind the block
to find, but I realize that it's hardly up to me :)

Anyways. More serious, in my oppinion, is the fact that Array#insert and
String#insert are destructive without having an exclamation mark. Why is
that? I really do not expect them to change their owner.
hello world
=> nilhello surprising world
=> nilhello surprising world
=> nil

seriously, wtf? Why not `insert` and `insert!` that behave as expected?
Before I realized this I had a hard time tracking down some unexpected
behaviour.
 
B

Brian Candler

Einar said:
Now this is fine:

save_block :say_hello do
puts "hello!"
end

but not this:

save_block :say_hello {
puts "hello!"
}

Although this is fine:

save_block:)say_hello) {
puts "hello!"
}
 
D

Damjan Rems

My convention is use {} in oneliners. In all other examples I use
do..end.

by
TheR
 
M

Mike Gold

Ryan said:
I follow (and teach) the weirich method:

http://onestepback.org/index.cgi/Tech/Ruby/BraceVsDoEnd.rdoc

{} for block values I care about (think map), do/end for regular block
sends (think each).

I use {} for blocks that return values (think #map) and do/end for all
other blocks (think #each).

funcs = []
(1..5).each do |i|
funcs << lambda { i }
end
p funcs.map { |f| f.call } # => [1, 2, 3, 4, 5]

funcs2 = []
for j in 1..5
funcs2 << lambda { j }
end
p funcs2.map { |f| f.call } # => [5, 5, 5, 5, 5]

I prefer to make the new binding scope of a block visually obvious,
therefore I always use {}. do/end tricks me into thinking it belongs to
the same category as for/end or while/end or if/end, but it's quite
different (above).

Also, I like one rule better than two rules.
 
P

Phlip

Mike said:
funcs2 = []
for j in 1..5
funcs2 << lambda { j }
end
p funcs2.map { |f| f.call } # => [5, 5, 5, 5, 5]

I prefer to make the new binding scope of a block visually obvious,
therefore I always use {}. do/end tricks me into thinking it belongs to
the same category as for/end or while/end or if/end, but it's quite
different (above).

Also, I like one rule better than two rules.

Curiously, Ruby departs with 40 years of Structural Programming tradition - the
statement groups controlled by if-end, and their ilk, do _not_ introduce a new
variable scope, while the statement groups inside true blocks _do_ introduce
scoped variables.

Furtherless, the region inside a block _might_ be someone else's scope! Rails's
render :update do ... end does this to us. Principle of Most Surprise applies.

So making dangerous things like blocks look ugly is a good way to help us
respect them!
 
R

Rick DeNatale

[Note: parts of this message were removed to make it a legal post.]

On Jan 27, 2009, at 02:08 , Damjan Rems wrote:

My convention is use {} in oneliners. In all other examples I use

I follow (and teach) the weirich method:

http://onestepback.org/index.cgi/Tech/Ruby/BraceVsDoEnd.rdoc

{} for block values I care about (think map), do/end for regular block
sends (think each).

I use {} for blocks that return values (think #map) and do/end for all
other blocks (think #each).

Yes, it's the "I care about' that matters, a subtle distinction to the
weirich method, which I wrote about:

http://talklikeaduck.denhaven2.com/articles/2007/10/02/ruby-blocks-do-or-brace

and Jim agreed in the comments.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top