Newbie: two cool discoveries

Hi all,
I just wanted to share a couple of things I've found out lately. I
imagine they are well known to the experts here, but I thought maybe
there are other newbies out there that could benefit from it too.

1) Using proc in the case statement:

I find the case statement particularly elegant: especially when
there's a long list of choices I much prefer it to using if...
elsif... else... end. That said the latter offers a lot more
flexibility. Still a lot can be accomplished by using procs. For
example:

case val
when Hash
...
when lambda{|x| x.respond_to?(:to_ary) && x.length>1}
...
end

The block takes the case argument and its output (generally true or
false...) is used to decide if the branch should be run or not.

2) Passing a block to map or similar methods.

Say you have an array of numbers, and you want to invoke #abs for each
number. Rather than:
x = [1,-2,3,-4,5]
x.map{|x| x.abs}

you can use:
x = [1,-2,3,-4,5]
x.map(&:abs)

It may not seem much in this instance, but I found it a lot cleaner in
some cases, especially when there is a long chain of methods.

Hope that helped _someone_ :slight_smile:

Diego

the "&" is a shortcut to "to_proc"

class Symbol
  def to_proc
    lambda { |x| x.__send__(self) }
  end
end

So in theory, you could use to send *any* message

( Ruby 1.9* btw )

···

On Friday 26 November 2010 14:00:15 Diego Virasoro wrote:

Hi all,
I just wanted to share a couple of things I've found out lately. I
imagine they are well known to the experts here, but I thought maybe
there are other newbies out there that could benefit from it too.

1) Using proc in the case statement:

I find the case statement particularly elegant: especially when
there's a long list of choices I much prefer it to using if...
elsif... else... end. That said the latter offers a lot more
flexibility. Still a lot can be accomplished by using procs. For
example:

case val
when Hash
...
when lambda{|x| x.respond_to?(:to_ary) && x.length>1}
...
end

The block takes the case argument and its output (generally true or
false...) is used to decide if the branch should be run or not.

2) Passing a block to map or similar methods.

Say you have an array of numbers, and you want to invoke #abs for each
number. Rather than:
x = [1,-2,3,-4,5]
x.map{|x| x.abs}

you can use:
x = [1,-2,3,-4,5]
x.map(&:abs)

It may not seem much in this instance, but I found it a lot cleaner in
some cases, especially when there is a long chain of methods.

Hope that helped _someone_ :slight_smile:

Diego

I'm curios to hear whether you maintain that statement after seeing
the other (apparently mostly unknown) variant of case:

case # nothing here!
when x > 1
  puts "great"
when sun.shines && temp > 20
  puts "warm"
when 3 == 9, 21 < 17
  puts "weird"
else
  puts "what?"
end

This is basically the same as an if-elsif-else-end cascade with a
shorter syntax for "||" (i.e. the comma after "when").

Also, you can return values from case statements:

puts case # nothing here!
when x > 1
  "great"
when sun.shines && temp > 20
  "warm"
when 3 == 9, 21 < 17
  "weird"
else
  "what?"
end

Of course this can also be done with if-elsif-else-end.

Cheers

robert

···

On Fri, Nov 26, 2010 at 3:00 PM, Diego Virasoro <diego.virasoro@gmail.com> wrote:

I find the case statement particularly elegant: especially when
there's a long list of choices I much prefer it to using if...
elsif... else... end. That said the latter offers a lot more
flexibility.

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

when proc{|x| x.respond_to?(:to_a) && x.size>1}

Using a Proc in this way doesn't work under Ruby 1.8.7.

···

On Nov 26, 7:56 am, Diego Virasoro <diego.viras...@gmail.com> wrote:

Hi all,
I just wanted to share a couple of things I've found out lately. I
imagine they are well known to the experts here, but I thought maybe
there are other newbies out there that could benefit from it too.

1) Using proc in the case statement:

I find the case statement particularly elegant: especially when
there's a long list of choices I much prefer it to using if...
elsif... else... end. That said the latter offers a lot more
flexibility. Still a lot can be accomplished by using procs. For
example:

case val
when Hash
...
when lambda{|x| x.respond_to?(:to_ary) && x.length>1}

This is basically the same as an if-elsif-else-end cascade with a
shorter syntax for "||" (i.e. the comma after "when").

Good point. It never came to my mind that you could forget to give
"case" an argument to turn it into an if-elsif-else-end. :slight_smile: Very nice.

About the comma though I don't find it very legible: it's fine for
normal use (like 1,3 or Array,Hash), but not as a generic or.
(obviously this is a very personal opinion). But I imagine that
there's nothing stopping you from using || when you feel it reads
better.

Anyway, I must admit that this makes case at least as useable than if-
elsif-else-end while possibly being more readable in a lot of cases.
I'd still prefer to use the latter when it's more readable, and I can
of prefer it if there are not many branches, but this is purely
personal opinion. Long live CASE!!! :slight_smile:

Diego

the "&" is a shortcut to "to_proc"

class Symbol
def to_proc
lambda { |x| x.__send__(self) }

Note that it's to_proc, not to_lambda. I don't see why
anyone would want to type the gibberish "lambda" when
he could type the shorter and clearer "proc".

end
end

So in theory, you could use to send *any* message

( Ruby 1.9* btw )

Why in the world do you say that?

[-9].map(&:abs)
    ==>[9]
VERSION
    ==>"1.8.7"

···

On Nov 26, 8:11 am, Arturo Garcia <arturo.g.art...@gmail.com> wrote:

Because lambda is more pretentious (at least, thats why I use it)

They actually have different meanings, though (sometimes)

$ cat proc_vs_lambda.rb
def invoke_lambda
  lambda { return 1 }.call
  return 2
end

def invoke_proc
  proc { return 1 }.call
  return 2
end

require 'pp'
puts ENV['RUBY_VERSION']
puts invoke_lambda # => 2
puts invoke_proc # => 1
puts

$ rvm proc_vs_lambda.rb
jruby-1.5.3
2
2

macruby-0.7
2
1

rbx-1.1.0-20100923
2
2

ruby-1.8.6-p399
2
2

ruby-1.8.7-p302
2
2

ruby-1.9.1-p378
2
1

ruby-1.9.2-p0
2
1

···

On Fri, Nov 26, 2010 at 6:45 PM, w_a_x_man <w_a_x_man@yahoo.com> wrote:

On Nov 26, 8:11 am, Arturo Garcia <arturo.g.art...@gmail.com> wrote:
> the "&" is a shortcut to "to_proc"
>
> class Symbol
> def to_proc
> lambda { |x| x.__send__(self) }

Note that it's to_proc, not to_lambda. I don't see why
anyone would want to type the gibberish "lambda" when
he could type the shorter and clearer "proc".

Yes, is to_proc. not because is shorter and clearer, btw, but because is
to_proc.

···

On Saturday 27 November 2010 00:45:14 w_a_x_man wrote:

On Nov 26, 8:11 am, Arturo Garcia <arturo.g.art...@gmail.com> wrote:
> the "&" is a shortcut to "to_proc"
>
> class Symbol
> def to_proc
> lambda { |x| x.__send__(self) }

Note that it's to_proc, not to_lambda. I don't see why
anyone would want to type the gibberish "lambda" when
he could type the shorter and clearer "proc".