Blocks are simply pieces of code that is supplied to a method call, also referred to as anonymous functions. They can be enclosed in {} or end do. Blocks can have arguments which are found between two pipes | |
Blocks work by having the method yield the block.
Yield can pass parameters to your block.
A little more complex example creating my own version of the each method.
Yielding without receiving a block will error out.
You can use block_given? to check if a block was passed.
You can use implicit returns in blocks meaning the last line is returned but you cannot use explicit return within a block or it will error out.
Procs and Lambdas
Procs and lambdas are very similar to each other. They are blocks saved to a variable for later execution. To define a proc we use Proc.new and to define a lambda we use lambda or ->. To execute a proc or lamdba we use call.
They can be passed to methods as arguments and you can even pass multiple procs or lambdas to a method (something you can’t do with blocks).
Procs and lambdas are very similar and infact both are Proc objects.
Both can take arguments. Although notice the syntax of passing an argument to a lambda when its defined using ->.
Procs and lambdas can be used where a block is expected by using & along with the proc or lambda.
and blocks can be turned into procs also by using &.
So thats the similarities, now here’s the differences
Lambdas check the number of arguments while procs do not.
Lambdas and procs return differently.
A return inside a proc will return from the current context but becareful because returning from the top level context will return an error.
Return from inside a lambda just returns from inside the lambda.
The method method
It’s also worth noting that normal methods can be passed to other methods similar to blocks, procs and lambdas. This is done using the method method and passing in the method’s name as a symbol.
Closures
Blocks, procs and lambdas are all types of closures. A Closure is a function or reference to a function which retains access to the scope where it was defined.
Closures don’t take in the actual value but instead a reference to them so if they are updated after the proc or lambda is defined it will return the lastest version of it when its called.