Is Ruby's code block same as C#'s lambda expression? -


are these 2 same thing? similar me.

did lambda expression borrow idea ruby?

ruby has 4 constructs extremely similar

the block

the idea behind blocks sort of way implement light weight strategy patterns. block define coroutine on function, function can delegate control yield keyword. use blocks in ruby, including pretty looping constructs or anywhere use using in c#. outside block in scope block, inverse not true, exception return inside block return outer scope. this

def foo   yield 'called foo' end  #usage foo {|msg| puts msg} #idiomatic 1 liners  foo |msg| #idiomatic multiline blocks   puts msg end 

proc

a proc taking block , passing around parameter. 1 extremely interesting use of can pass proc in replacement block in method. ruby has special character proc coercion &, , special rule if last param in method signature starts &, proc representation of block method call. finally, there builtin method called block_given?, return true if current method has block defined. looks this

def foo(&block)   return block end  b = foo {puts 'hi'} b.call # hi 

to go little deeper this, there neat trick rails added symbol (and got merged core ruby in 1.9). basically, & coercion magic calling to_proc on whatever next to. rails guys added symbol#to_proc call on whatever passed in. lets write terse code aggregation style function calling method on every object in list

class foo   def bar     'this bar'   end end  list = [foo.new, foo.new, foo.new]  list.map {|foo| foo.bar} # returns ['this bar', 'this bar', 'this bar'] list.map &:bar # returns _exactly_ same thing 

more advanced stuff, imo illustrates sort of magic can procs

lambdas

the purpose of lambda pretty same in ruby in c#, way create inline function either pass around, or use internally. blocks , procs, lambdas closures, unlike first 2 enforces arity, , return lambda exits lambda, not containing scope. create 1 passing block lambda method, or -> in ruby 1.9

l = lambda {|msg| puts msg} #ruby 1.8 l = -> {|msg| puts msg} #ruby 1.9  l.call('foo') # => foo 

methods

only serious ruby geeks understand 1 :) method way turn existing function can put in variable. method calling method function, , passing in symbol method name. can re bind method, or can coerce proc if want show off. way re-write previous method be

l = lambda &method(:puts) l.call('foo') 

what happening here creating method puts, coercing proc, passing in replacement block lambda method, in turn returns lambda


feel free ask isn't clear (writing late on weeknight without irb, isn't pure gibberish)

edit: address questions in comments

list.map &:bar can use syntax code block takes more 1 argument? have hash = { 0 => "hello", 1 => "world" }, , want select elements has 0 key. maybe not example. – bryan shen

gonna go kind of deep here, understand how works need understand how ruby method calls work.

basically, ruby doesn't have concept of invoking method, happens objects pass messages each other. obj.method arg syntax use sugar around more explicit form, obj.send :method, arg, , functionally equivalent first syntax. fundamental concept in language, , why things method_missing , respond_to? make sense, in first case handling unrecognized message, second checking see if listening message.

the other thing know rather esoteric "splat" operator, *. depending on used, different things.

def foo(bar, *baz) 

in method call, if last parameter, splat make parameter glob additional parameters passed in function (sort of params in c#)

obj.foo(bar, *[biz, baz]) 

when in method call (or else takes argument lists), turn array bare argument list. snippet below equivilent snippet above.

obj.foo(bar, biz, baz) 

now, send , * in mind, symbol#to_proc implemented this

class symbol   def to_proc     proc.new { |obj, *args| obj.send(self, *args) }   end end 

so, &:sym going make new proc, calls .send :sym on first argument passed it. if additional args passed, globbed array called args, , splatted send method call.

i notice & used in 3 places: def foo(&block), list.map &:bar, , l = lambda &method(:puts). share same meaning? – bryan shen

yes, do. & call to_proc on ever beside. in case of method definition has special meaning when on last parameter, pulling in co-routine defined block, , turning proc. method definitions 1 of complex parts of language, there huge amount of tricks , special meanings can in parameters, , placement of parameters.

b = {0 => "df", 1 => "kl"} p b.select {|key, value| key.zero? } tried transform p b.select &:zero?, failed. guess that's because number of parameters code block two, &:zero? can take 1 param. there way can that? – bryan shen

this should addressed earlier, unfortunately can't trick.

"a method way turn existing function can put in variable." why l = method(:puts) not sufficient? lambda & mean in context? – bryan shen

that example exceptionally contrived, wanted show equivalent code example before it, passing proc lambda method. take time later , re-write bit, correct, method(:puts) totally sufficient. trying show can use &method(:puts) anywhere take block. better example this

['hello', 'world'].each &method(:puts) # => hello\nworld 

l = -> {|msg| puts msg} #ruby 1.9: doesn't work me. after checked jörg's answer, think should l = -> (msg) {puts msg}. or maybe i'm using incorrect version of ruby? mine ruby 1.9.1p738 – bryan shen

like said in post, didn't have irb available when writing answer, , right, goofed (spend vast majority of time in 1.8.7, not used new syntax yet)

there no space between stabby bit , parens. try l = ->(msg) {puts msg}. there lot of resistance syntax, since different else in language.


Comments

Popular posts from this blog

asp.net - repeatedly call AddImageUrl(url) to assemble pdf document -

java - Android recognize cell phone with keyboard or not? -

iphone - How would you achieve a LED Scrolling effect? -