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
Post a Comment