Ruby has support for functional programming features like code blocks and higher-level functions (see Array#map, inject, & select).
How can I write functional code in Ruby?
Would appreciate examples like implementing a callback.
You could use yield
def method(foo,bar)
operation=foo+bar
yield operation
end
then you call it like this:
foo=1
bar=2
method(foo,bar) {|result| puts "the result of the operation using arguments #{foo} and #{bar} is #{result}"}
the code in the block (a block is basically "a chunk of code" paraphrasing ruby programmers) gets executed in the "yield operation" line, you pass the method a block of code to be executed inside the method defined. This makes Ruby pretty versatile language.
In this case yield receives an argument called "operation". I wrote it that way because you asked for a way to implement a callback.
but you could just wrote
def method()
puts "I'm inside the method"
yield
end
method(){puts "I'm inside a block"}
and it would output
I'm inside the method
I'm inside a block
Related
I have a need to decipher some Ruby code. Being a Python dev, I am having hard time making sense to some of the syntax.
I need to deal with some (mostly clean and readable) Sinatra code. I started with a Sinatra tutorial, and it looks something like this:
get '/' do
"Hello, World!"
end
Now, I know that in Ruby you don't need parentheses to call a function. So if I were to try to understand the above, I would say:
get is a function that takes as its first argument the route.
'/' is the first argument
do ... end block is an anonymous function
Please correct me if I am wrong above, and explain in detail anything I might be missing.
Also they say that Sinatra is a DSL -- does this mean that it is parsing some special syntax that is not official Ruby?
do ... end (or { ... }) is a block, a very important concept in Ruby. It was noticed that very often functions that take other functions as parameter (map, filter, grep, timeout...) very often accept a single function. So the Ruby designer decided to make a special syntax for it.
It is often said that in Ruby, everything is an object. This is not quite true: code is not an object. Code can be wrapped into an object. But Ruby blocks are pure code - not an object, not a first-order value at all. Blocks are a piece of code associated with a function call.
Your code snippet is equivalent to this:
self.get('/') do
return "Hello, World!"
end
The get method takes one parameter and a block; not two parameters. In a hypothetical example where get did take two parameters, we would have to write something like this:
get('/', lambda { "Hello, World" })
or
get('/', Proc.new { "Hello, World" })
but notice that the way we wrap code into objects involves calling methods lambda and Proc.new - and giving them a block (and zero parameters)!
There are many tutorials on "Ruby blocks", so I will not link any particular one.
Because of the block syntax, Ruby is very good at making dialects (still fully syntactic Ruby) that express certain concepts very neatly. Sinatra uses the get... "syntax" (but actually just a method call) to describe a web server; Rake uses task... "syntax" to describe build processes; RSpec, a testing framework, has its own DSL (that is still Ruby) that describes desired behaviours.
After some reading, I understood the code blocks.
Ruby code blocks are simple. They are 'closures'. There's two ways to write a block
do |x|
do_something(x)
end
{|x| do_something(x) }
The |x| is the argument that gets passed to the code within the block.
The crucial bit to grasping code blocks is to understand how they are used with methods.
In Ruby, methods are a bit different.
In addition to arguments, any method can accept a code block.
Code blocks are NOT arguments, but they are a separate entity that can be passed to a method along with arguments
A method can choose not to call the code block, in which case, any code block that was passed is ignored
If a method calls a code block, then it is necessary to pass it when calling the method, or otherwise Ruby will complain.
yield within a method executes the code block
For more on code blocks read this: http://mixandgo.com/blog/mastering-ruby-blocks-in-less-than-5-minutes
I'm trying to understand when one should code blocks implicitly or explicitly. Given the following code blocks:
Implicit
def two_times_implicit
return "No block" unless block_given?
yield
yield
end
puts two_times_implicit { print "Hello "}
puts two_times_implicit
Explicit
def two_times_explicit (&i_am_a_block)
return "No block" if i_am_a_block.nil?
i_am_a_block.call
i_am_a_block.call
end
puts two_times_explicit { puts "Hello"}
puts two_times_explicit
Is it preferable to code using one over the other? Is there a standard practice and are there instances where one would work better or differently than the other and where one would not work at all?
Receiving a block via & creates a new proc object out of the block, so from the point of view of efficiency, it is better not to use it. However, using & generally makes it easier to define methods that may or may not take a block, and using &, you can also handle blocks together with arguments, so it is preferred by many.
Actually, according to one very interesting read, second variant is 439% slower (related thread on HackerNews).
TL;DR: Creating and passing a block via yield is a highly optimized common case in MRI, which is handled by dedicated C function in interpreter, while passing &block is implemented differently and has a big overhead of creating new environment and creating Proc itself on every call.
Summing up, use &block only if you need passing it further (for example, to a next function), or manipulate it somehow in other way. Otherwise, use yield, since it's way faster.
Apparently in Lisp when you write a block/lambda without parameters, the word "it" takes the value passed in to the block.
This seems elegant; I like it; I want it in Ruby. Is there any way to make it work?
3.times { p it }
should print "0 1 2"
Obviously I could eval a block in a context that included a method_missing that returned a value for :it (or maybe def Object#it). But what value should it return? If I "yield 42" to a block, and the block was declared without parameters, is there any general way to recover the value 42?
(The original version of this question asked about C#, hence the comments. Apparently C# doesn't have this but Lisp does.)
In Ruby, procs seem to have access to local variables that were present at the time they were declared, even if they are executed in a different scope:
module Scope1
def self.scope1_method
puts "In scope1_method"
end
end
module Scope2
def self.get_proc
x = 42
Proc.new do
puts x
puts self
scope1_method
end
end
end
Scope1.instance_eval(&Scope2.get_proc)
Output:
42
Scope1
In scope1_method
How and why does this occur?
The Proc.new call creates a closure for the block that it's given. In creating a closure for the block, the block is bound to the original variables in the scope of the Proc.new call.
Why is this done?
It allows Ruby blocks to function as closures. Closures are extremely useful, and the Wikipedia entry (linked above) does an excellent job of explaining some of their applications.
How is this done?
This is done in the Ruby VM (in C code) by copying the Ruby control frame that exists before entering the Proc.new method. The block is then run in the context of this control frame. This effectively copies all of the bindings that are present in this frame. In Ruby 1.8, you can find the code for this in the proc_alloc function in eval.c. In Ruby 1.9, you can find this in the proc_new function in proc.c.
This behavior is by design. In Ruby, blocks, procs, and lambdas are lexical closures. Read this blog post for a short explanation of the differences between Ruby's three flavors of closure.
I introduced the bug shown below into my code the other day and wanted to better understand the implications.
File.open('test.txt').readlines do |line|
puts "#{line} test"
end
File.open.readlines does exactly as expected and returns an array containing all of the lines in the file. But immediately following that array is a block. The array returned by readlines calls no member methods, each for instance. I'm assuming the block has nothing calling it, therefore it does nothing. In other languages this may have thrown a compiler warning or in C the block would be considered a nested scope and it would execute. But as shown, Ruby (1.9.2) happily runs with no errors, and no output generated by puts.
For completeness here's the corrected version.
File.open('test.txt').each_line do |line|
puts "#{line} test"
end
I would like to understand the behavior of the first example. Is my assumption correct in that the block is essentially anonymous and didn't execute because nothing called it?
Here is what is happening in your particular example. When you call
File.open('test.txt').readlines do |line|
puts "#{line} test"
end
The block is being passed to the readlines method. The block is not passed to the array that is returned by the readlines method. This is a valid case and thus the ruby interpreter does not complain.
Here is a simpler scenario to illustrate this
Let's say I had a class defined as follows
class Foo
def bar
end
end
Now if I call
Foo.new.bar {puts "hello"}
There will be no error from the interpreter and the "hello" will not be printed.
If I yield to the block in bar as follows
class Foo
def bar
yield
end
end
Then the puts will be executed and you should see hello printed
Foo.new.bar {puts "hello"} # prints hello
In summary blocks are passed to methods not objects and you can pass a block to any method in ruby even one which does not expect it.