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