Forum: Ruby Conventions in ruby and the principle of least surprise

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
87349a7a95b3f2e83c20194ef122885c?d=identicon&s=25 Einar Boson (einarmagnus)
on 2009-01-27 03:14
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.

>> hi = "hello world"
=> "hello world"
>> puts hi
hello world
=> nil
>> puts hi.insert(6, "surprising ")
hello surprising world
=> nil
>> puts hi
hello 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.
0ec4920185b657a03edf01fff96b4e9b?d=identicon&s=25 Yukihiro Matsumoto (Guest)
on 2009-01-27 03:50
(Received via mailing list)
Hi,

In message "Re: Conventions in ruby and the principle of least surprise"
    on Tue, 27 Jan 2009 11:11:55 +0900, Einar Boson
<einarmagnus@tistron.se> writes:

|do..end vs. {}

|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

Correct.

|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.

|seriously, wtf? Why not `insert` and `insert!` that behave as expected?

The bang (!) does not mean "destructive" nor lack of it mean non
destructive either.  The bang sign means "the bang version is more
dangerous than its non bang counterpart; handle with care".  Since
Ruby has a lot of "destructive" methods, if bang signs follow your
opinion, every Ruby program would be full of bangs, thus ugly.

              matz.
753dcb78b3a3651127665da4bed3c782?d=identicon&s=25 Brian Candler (candlerb)
on 2009-01-27 09:28
Einar Boson wrote:
> 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!"
  }
Be07c8d0d6867fd9a0d525f7d17600e2?d=identicon&s=25 Damjan Rems (ther)
on 2009-01-27 11:10
My convention is use {} in oneliners. In all other examples I use
do..end.

by
TheR
5a837592409354297424994e8d62f722?d=identicon&s=25 Ryan Davis (Guest)
on 2009-01-27 22:15
(Received via mailing list)
On Jan 27, 2009, at 02:08 , Damjan Rems wrote:

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

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).
A246f7c0ce5f2909483d358bd9e83e4e?d=identicon&s=25 Mike Gold (mikegold)
on 2009-01-28 01:23
Ryan Davis wrote:
> On Jan 27, 2009, at 02:08 , Damjan Rems wrote:
>
>> My convention is use {} in oneliners. In all other examples I use
>> do..end.
>
> 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.
Aafa8848c4b764f080b1b31a51eab73d?d=identicon&s=25 Phlip (Guest)
on 2009-01-29 00:40
(Received via mailing list)
Mike Gold wrote:

>
> 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!
3131fcea0a711e5ad89c8d49cc9253b4?d=identicon&s=25 Julian Leviston (Guest)
on 2009-01-31 00:35
(Received via mailing list)
Awesome :) perhaps these little gems of what certain things mean as a
FAQ could make their way into the web site.

Sent from my iPhone

On 27/01/2009, at 1:47 PM, Yukihiro Matsumoto <matz@ruby-lang.org>
8f6f95c4bd64d5f10dfddfdcd03c19d6?d=identicon&s=25 Rick Denatale (rdenatale)
on 2009-02-02 17:45
(Received via mailing list)
On Tue, Jan 27, 2009 at 4:12 PM, Ryan Davis
<ryand-ruby@zenspider.com>wrote:

>
> {} 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/1...

and Jim agreed in the comments.

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
This topic is locked and can not be replied to.