7

I was reading through confident ruby and I was trying out how to define a reusable proc. From the examples given, I wrote this:

DEFAULT_BLOCK = -> { 'block executed' }

answers = {}

answers.fetch(:x, &DEFAULT_BLOCK)

I was expecting it to return block executed since x is not found in the Hash but instead it returned wrong number of arguments (given 1, expected 0) (ArgumentError). What could the problem be? I haven't given the block an argument.

L.T
  • 370
  • 3
  • 8

3 Answers3

9

You have, you just don't see it:

WHAT_AM_I_PASSING = ->(var) { var.inspect }

answers = {}

answers.fetch(:x, &WHAT_AM_I_PASSING)
# => ":x"

The block of Hash#fetch provides an argument, the key that you haven't found. You can either accept an argument in your lambda and just ignore it, or make it a proc:

DEFAULT_BLOCK = proc { 'block executed' }
answers.fetch(:x, &DEFAULT_BLOCK)
# => "block executed" 

The reason that a proc works, is that lambdas verify that the correct number of arguments were provided while procs don't. The fetch method is calling the proc/lambda with one argument (the key).

max pleaner
  • 26,189
  • 9
  • 66
  • 118
Marcin Kołodziej
  • 5,253
  • 1
  • 10
  • 17
3

When Hash#fetch takes a block, the key is passed to the block. But your block created from a proc does not take any block argument. Change the definition to:

DEFAULT_BLOCK = -> x { 'block executed' }
sawa
  • 165,429
  • 45
  • 277
  • 381
0
    2.6.1 :014 > DEFAULT_BLOCK = -> { 'block executed' }
     => #<Proc:0x00005586f6ef9e58@(irb):14 (lambda)> 
    2.6.1 :015 > answers = {}
     => {} 
    2.6.1 :016 > ans = answers.fetch(:x) {DEFAULT_BLOCK}
     => #<Proc:0x00005586f6ef9e58@(irb):14 (lambda)> 
    2.6.1 :017 > ans.call
     => "block executed" 

    Actually we can pass default value for key so that if key not found in the hash it use this default value like,
    my_hash = {}
     => {} 
    2.6.1 :019 > my_hash[:key1] = 'val1'
     => "val1" 
    2.6.1 :020 > p my_hash
    {:key1=>"val1"}
     => {:key1=>"val1"} 
    2.6.1 :022 > my_hash.fetch(:key1)
     => "val1" 
    2.6.1 :023 > my_hash.fetch(:key2)
    KeyError (key not found: :key2)
    Did you mean?  :key1
    2.6.1 :024 > my_hash.fetch(:key2){'val2'}
     => "val2" 
2017kamb
  • 192
  • 3
  • 8
  • 27