Declaring a Ruby lambda with a yield -


i'm writing method splits array of struct couple of different, arrays while eliminating elements nil values.

what want write is:

def my_func(some_data)     f = lambda{|data| data.select{|m| yield(m).present? }.map { |m| [m.date, yield(m)]}}      x = f.call(some_data) {|m| m.first_var}     y = f.call(some_data) {|m| m.second_var}      return x, y end 

this appears not work ruby doesn't handle yield inside lambda in way expect.

localjumperror: no block given(yield)

is there way define f x , y give result i'm looking for?

you cannot yield lambda directly nonexplicit block passed doing (see comments below source provided @cremno showing yield may used in method , singleton class definitions)

source extraction:

if ((type != iseq_type_method && type != iseq_type_class) || block == 0) {   rb_vm_localjump_error("no block given (yield)", qnil, 0); } 

primary solution:

you explicit block

f = lambda |data,&block|        data.select |m|          block.call(m)       end.map |m|          [m, block.call(m)]       end     end d = ["string",1,2,3,4,"string2"] f.call(d) { |n| n.is_a?(string) } #=>[["string", true], ["string2", true]] 

secondary solution:

however can yield inside lambda if block passed method instead e.g.

def some_method(data)   #extended syntax readability works fine    #f = lambda{|data,&block| data.select{|m| block.call(m) }.map { |m| [m, block.call(m)]}}   f = lambda |data|          data.select |m|            yield(m)         end.map |m|            [m, yield(m)]         end       end   f.call(data) end some_method(["string",1,2,3,4,"string2"]) { |s| s.is_a?(string) }  #=> [["string", true], ["string2", true]] 

tertiary soultion: (a spawn of secondary solution more closely matches question)

define secondary method

def some_method(some_data)    x = filter(some_data) {|m| m.is_a?(string)}    y = filter(some_data) {|m| m.is_a?(fixnum)}    [x, y] end   def filter(data)    data.select |m|      yield(m)   end.map |m|      [m, yield(m)]   end end some_method(["string",1,2,3,4,"string2"]) #=>[     [["string", true], ["string2", true]],      [[1, true], [2, true], [3, true], [4, true]]    ] 

quaternary solution:

there technically fourth option , posting sake because represents original code closely possible. far strangest pattern (almost strange word quaternary) of 4 thorough:

def some_method(some_data)     f = lambda{|data| data.select{|m| yield(m) }.map { |m| [m, yield(m)]}}     if block_given?       f.call(some_data)     else         x = some_method(some_data) {|m| m.is_a?(string)}       y = some_method(some_data) {|m| m.is_a?(fixnum)}       [x,y]      end end some_method(["string",1,2,3,4,"string2"]) #=>[     [["string", true], ["string2", true]],      [[1, true], [2, true], [3, true], [4, true]]    ] 

Comments

Popular posts from this blog

Magento/PHP - Get phones on all members in a customer group -

php - Bypass Geo Redirect for specific directories -

php - .htaccess mod_rewrite for dynamic url which has domain names -