At Surface,
Ruby appears to be quite similar to other object orieinted languages like Java,Php,C etc.
but, things get bit weird when we start to bump into blocks.
for example, this works
(0...8).max()
=> 7
but this doesn't
(0...8).map(puts "hello world")
hello world
ArgumentError: wrong number of arguments(1 for 0)
Apprantly, map method doesn't take arguments but takes blocks, so passing replacing () with {} fix the error.
(0...8).map{puts "hello world"}
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
=> [nil, nil, nil, nil, nil, nil, nil, nil]
And then, there are some methods should take both -- blocks & arguments
8.downto(1){puts "hello world"}
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
=> 8
The problem I have is the confusion on if I should be using () , {} or both on given method. On what basis it gets decided?
Is it fixed on per method basis & I just to have remember what the method takes(Blocks or params)?
Or is there any other logical reasoning on basis of which it gets decided, if the method takes blocks{} or params()?
Please help me understand
Parenthesis after method calls are actually optional.
(0...8).map{puts "hello world"} is equivalent to (0...8).map() {puts "hello world"}
So you don't really replace them.
The acceptance of blocks is entirely up to the method, they can be specified in the method declaration:
def method(param, &block)
block.call
end
which will allow the block to be accessed as a variable from within the method, and be invoked via block.call for example.
They can also be used implicitely via the use of the yield keyword:
def method(param)
yield
end
So you have to refer to the API documentations to be sure what is accepted or not.
It should be documented in the API of the method.
If there is a method that accepts an argument, the block usually is optional - in such a case it is used to "refine" the way the method works - e.g. Hash.new, that may accept an argument (the default hash value) and a block, which is used to do smart things during key-value initialization. But most of the methods that require a block, don't accept an argument, e.g. Array#select or Array#map.
You use parenthesise to pass arguments to a function. This is always a comma separated list of Objects. They may be the result of a function, but don't have to. The function they are a result of will always only be called exactly once.
Example:
x = Array.new
=> []
x.push(2)
=> [2]
x.push(7.modulo(4))
=> [2,3]
You use blocks to pass functional behaviour to a method. These functions are usually intended to be called with many different arguments or a certain amount of times. puts "hello world" is a function that prints something, but does only return nil. So you will almost never try to use that as an argument for a function (as you would be passing nil to that function), but usually pass that as a block to a function so that it can be called multiple times.
Most of the time you will want to have the block, that you pass to a function, use arguments, so that it actually does something different for every time it is called.
Example:
(0..8).each{ |number|
if number.odd?
puts "#{number} is odd"
end
}
=> 1 is odd
=> 3 is odd
=> 5 is odd
=> 7 is odd
=> => 0..8
Related
I'm unclear on why there is a need to pass block arguments when calling a function.
why not just pass in as function arguments and what happens to the block arguments, how are they passed and used?
m.call(somevalue) {|_k, v| v['abc'] = 'xyz'}
module m
def call ( arg1, *arg2, &arg3)
end
end
Ruby, like almost all mainstream programming languages, is a strict language, meaning that arguments are fully evaluated before being passed into the method.
Now, imagine you want to implement (a simplified version of) Integer#times. The implementation would look a little bit like this:
class Integer
def my_times(action_to_be_executed)
raise ArgumentError, "`self` must be non-negative but is `#{inspect}`" if negative?
return if zero?
action_to_be_executed
pred.my_times(action_to_be_executed)
end
end
3.my_times(puts "Hello")
# Hello
0.my_times(puts "Hello")
# Hello
-1.my_times(puts "Hello")
# Hello
# ArgumentError (`self` must be non-negative but is `-1`)
As you can see, 3.my_times(puts "Hello") printed Hello exactly once, instead of thrice, as it should do. Also, 0.my_times(puts "Hello") printed Hello exactly once, instead of not at all, as it should do, despite the fact that it returns in the second line of the method, and thus action_to_be_executed is never even evaluated. Even -1.my_times(puts "Hello") printed Hello exactly once, despite that fact that it raises an ArgumentError exception as the very first thing in the method and thus the entire rest of the method body is never evaluated.
Why is that? Because Ruby is strict! Again, strict means that arguments are fully evaluated before being passed. So, what this means is that before my_times even gets called, the puts "Hello" is evaluated (which prints Hello to the standard output stream), and the result of that evaluation (which is just nil because Kernel#puts always returns nil) is passed into the method.
So, what we need to do, is somehow delay the evaluation of the argument. One way we know how to delay evaluation, is by using a method: methods are only evaluated when they are called.
So, we take a page out of Java's playbook, and define a Single Abstract Method Protocol: the argument that is being passed to my_each must be an object which implements a method with a specific name. Let's call it call, because, well, we are going to call it.
This would look a little bit like this:
class Integer
def my_times(action_to_be_executed)
raise ArgumentError, "`self` must be non-negative but is `#{inspect}`" if negative?
return if zero?
action_to_be_executed.call
pred.my_times(action_to_be_executed)
end
end
def (hello = Object.new).call
puts "Hello"
end
3.my_times(hello)
# Hello
# Hello
# Hello
0.my_times(hello)
-1.my_times(hello)
# ArgumentError (`self` must be non-negative but is `-1`)
Nice! It works! The argument that is passed is of course still strictly evaluated before being passed (we can't change the fundamental nature of Ruby from within Ruby itself), but this evaluation only results in the object that is bound by the local variable hello. The code that we want to run is another layer of indirection away and will only be executed at the point where we actually call it.
It also has another advantage: Integer#times actually makes the index of the current iteration available to the action as an argument. This was impossible to implement with our first solution, but here we can do it, because we are using a method and methods can take arguments:
class Integer
def my_times(action_to_be_executed)
raise ArgumentError, "`self` must be non-negative but is `#{inspect}`" if negative?
__my_times_helper(action_to_be_executed)
end
protected
def __my_times_helper(action_to_be_executed, index = 0)
return if zero?
action_to_be_executed.call(index)
pred.__my_times_helper(action_to_be_executed, index + 1)
end
end
def (hello = Object.new).call(i)
puts "Hello from iteration #{i}"
end
3.my_times(hello)
# Hello from iteration 0
# Hello from iteration 1
# Hello from iteration 2
0.my_times(hello)
-1.my_times(hello)
# ArgumentError (`self` must be non-negative but is `-1`)
However, this is not actually very readable. If you didn't want to give a name to this action that we are trying to pass but instead simply literally write it down inside the argument list, it would look something like this:
3.my_times(Object.new.tap do |obj|
def obj.call(i)
puts "Hello from iteration #{i}"
end
end)
# Hello from iteration 0
# Hello from iteration 1
# Hello from iteration 2
or on one line:
3.my_times(Object.new.tap do |obj| def obj.call; puts "Hello from iteration #{i}" end end)
# Hello from iteration 0
# Hello from iteration 1
# Hello from iteration 2
# or:
3.my_times(Object.new.tap {|obj| def obj.call; puts "Hello from iteration #{i}" end })
# Hello from iteration 0
# Hello from iteration 1
# Hello from iteration 2
Now, I don't know about you, but I find that pretty ugly.
In Ruby 1.9, Ruby added Proc literals aka stabby lambda literals to the language. Lambda literals are a concise literal syntax for writing objects with a call method, specifically Proc objects with Proc#call.
Using lambda literals, and without any changes to our existing code, it looks something like this:
3.my_times(-> i { puts "Hello from iteration #{i}" })
# Hello from iteration 0
# Hello from iteration 1
# Hello from iteration 2
This does not look bad!
When Yukihiro "matz" Matsumoto designed Ruby almost thirty years ago in early 1993, he did a survey of the core libraries and standard libraries of languages like Smalltalk, Scheme, and Common Lisp to figure out how such methods that take a piece of code as an argument are actually used, and he found that the overwhelming majority of such methods take exactly one code argument and all they do with that argument is call it.
So, he decided to add special language support for a single argument that contains code and can only be called. This argument is both syntactically and semantically lightweight, in particular, it looks syntactically exactly like any other control structure, and it is semantically not an object.
This special language feature, you probably guessed it, are blocks.
Every method in Ruby has an optional block parameter. I can always pass a block to a method. It's up to the method to do anything with the block. Here, for example, the block is useless because Kernel#puts doesn't do anything with a block:
puts("Hello") { puts "from the block" }
# Hello
Because blocks are not objects, you cannot call methods on them. Also, because there can be only one block argument, there is no need to give it a name: if you refer to a block, it's always clear which block because there can be only one. But, if the block doesn't have methods and doesn't have a name, how can we call it?
That's what the yield keyword is for. It temporarily "yields" control flow to the block, or, in other words, it calls the block.
With blocks, our solution would look like this:
class Integer
def my_times(&action_to_be_executed)
raise ArgumentError, "`self` must be non-negative but is `#{inspect}`" if negative?
return enum_for(__callee__) unless block_given?
__my_times_helper(&action_to_be_executed)
end
protected
def __my_times_helper(&action_to_be_executed, index = 0)
return if zero?
yield index
pred.__my_times_helper(&action_to_be_executed, index + 1)
end
end
3.my_times do
puts "Hello from iteration #{i}"
end
# Hello from iteration 0
# Hello from iteration 1
# Hello from iteration 2
0.my_times do
puts "Hello from iteration #{i}"
end
-1.my_times do
puts "Hello from iteration #{i}"
end
# ArgumentError (`self` must be non-negative but is `-1`)
Okay, you might notice that I simplified a bit when I wrote above that the only thing you can do with a block is call it. There are two other things you can do with it:
You can check whether a block argument was passed using Kernel#block_given?. Since blocks are always optional, and blocks have no names, there must be a way to check whether a block was passed or not.
You can "roll up" a block (which is not an object and doesn't have a name) into a Proc object (which is an object) and bind it to a parameter (which gives it a name) using the & ampersand unary prefix sigil in the parameter list of the method. Now that we have an object, and a way to refer to it, we can store it in a variable, return it from a method, or (as we are doing here) pass it along as an argument to a different method, which otherwise wouldn't be possible.
There is also the opposite operation: with the & ampersand unary prefix operator, you can "unroll" a Proc object into a block in an argument list; this makes it so that the method behaves as if you had passed the code that is stored inside the Proc as a literal block argument to the method.
And there you have it! That's what blocks are for: a semantically and syntactically lightweight form of passing code to a method.
There are other possible approaches, of course. The approach that is closest to Ruby is probably Smalltalk. Smalltalk also has a concept called blocks (in fact, that is where Ruby got both the idea and the name from). Similarly to Ruby, Smalltalk blocks have a syntactically light-weight literal form, but they are objects, and you can pass more than one to a method. Thanks to Smalltalk's generally light-weight and simple syntax, especially the keyword method syntax which intersperses parts of the method name with the arguments, even passing multiple blocks to a method call is very concise and readable.
For example, Smalltalk actually does not have an if / then / else conditional expression, in fact, Smalltalk has no control structures at all. Everything is done with methods. So, the way that a conditional works, is that the two boolean classes TrueClass and FalseClass each have a method named ifTrue:ifFalse: which takes two block arguments, and the two implementations will simply either evaluate the first or the second block. For example, the implementation in TrueClass might look a little bit like this (note that Smalltalk has no syntax for classes or methods, instead classes and methods are created in the IDE by creating class objects and method objects via the GUI):
True>>ifTrue: trueBlock ifFalse: falseBlock
"Answer with the value of `trueBlock`."
↑trueBlock value
The corresponding implementation in FalseClass would then look like this:
FalseClass>>ifTrue: trueBlock ifFalse: falseBlock
"Answer with the value of `falseBlock`."
↑falseBlock value
And you would call it like this:
2 < 3 ifTrue: [ Transcript show: 'yes' ] ifFalse: [ Transcript show: 'no' ].
"yes"
4 < 3 ifTrue: [ Transcript show: 'yes' ] ifFalse: [ Transcript show: 'no' ].
"no"
In ECMAScript, you can simply use function definitions as expressions, and there is also lightweight syntax for functions.
In the various Lisps, code is just data, and data is code, so you can just pass the code as an argument as data, then inside the function, treat that data as code again.
Scala has call-by-name parameters which are only evaluated when you use their name, and they are evaluated every time you use their name. It would look something like this:
implicit class IntegerTimes(val i: Int) extends AnyVal {
#scala.annotation.tailrec
def times(actionToBeExecuted: => Unit): Unit = {
if (i < 0) throw new Error()
if (i == 0) () else { actionToBeExecuted; (i - 1).times(actionToBeExecuted) }
}
}
3.times { println("Hello") }
// Hello
// Hello
// Hello
How can I make a list of methods without running it and using it latter?
For example
def somedef
(anything)
end
a = [system("echo 'hello'"), 1, somedef]
After you type a=[system("echo 'hello'"), 1, somedef] you get hello and the result of somedef method. But I want to for example concatenate lists with methods within.
Use a proc
a = [Proc.new {system("echo 'hello'")}, Proc.new {1}, Proc.new{somedef}]
Whenever you have to execute the methods execute the call method of the proc.
a[0].call #Output: hello
a[1].call #Output: 1
In Ruby, you can leave out the parentheses when calling a method. (I am quite surprised that you have never seen this before, as it is indeed quite common to do so.) Ergo, what you are doing is simply calling the methods.
If you want to get a reference to the method as an object, you can call the method method, which returns a Method object:
a = [system("echo 'hello'"), 1, method(:somedef)]
Using method():
def hello
system("echo 'hello'")
end
=> nil
a = [method(:hello), 1]
=> [#<Method: Object#hello>, 1]
foo[0].call
hello
=> true
Depending on what your needs are you can also just save symbols and then send them to the appropriate object when necessary. For example:
def some_def
...
end
a = [:some_def]
self.send(a[0])
It's just an alternative to the other good answers on this page. It's a weak contract (you have to know that the object you are sending this messages to will respond to them) but it may be enough for some scenarios.
Consider this, which works fine:
:>.to_proc.curry(2)[9][8] #=> true, because 9 > 8
However, even though > is a binary operator, the above won't work without the arity specified:
:>.to_proc.curry[9][8] #=> ArgumentError: wrong number of arguments (0 for 1)
Why aren't the two equivalent?
Note: I specifically want to create the intermediate curried function with one arg supplied, and then call then call that with the 2nd arg.
curry has to know the arity of the proc passed in, right?
:<.to_proc.arity # => -1
Negative values from arity are confusing, but basically mean 'variable number of arguments' one way or another.
Compare to:
less_than = lambda {|a, b| a < b}
less_than.arity # => 2
When you create a lambda saying it takes two arguments, it knows it takes two arguments, and will work fine with that style of calling #curry.
less_than.curry[9][8] # => false, no problem!
But when you use the symbol #to_proc trick, it's just got a symbol to go on, it has no idea how many arguments it takes. While I don't think < is actually an ordinary method in ruby, I think you're right it neccessarily takes two args, the Symbol#to_proc thing is a general purpose method that works on any method name, it has no idea how many args the method should take, so defines the proc with variable arguments.
I don't read C well enough to follow the MRI implementation, but I assume Symbol#to_proc defines a proc with variable arguments. The more typical use of Symbol#to_proc, of course, is for a no-argument methods. You can for instance do this with it if you want:
hello_proc = :hello.to_proc
class SomeClass
def hello(name = nil)
puts "Hello, #{name}!"
end
end
obj = SomeClass.new
obj.hello #=> "Hello, !"
obj.hello("jrochkind") #=> "Hello, jrochkind!"
obj.hello("jrochkind", "another")
# => ArgumentError: wrong number of arguments calling `hello` (2 for 1)
hello_proc.call(obj) # => "Hello, !"
hello_proc.call(obj, "jrochkind") # => "Hello, jrochkind!"
hello_proc.call(obj, "jrochkind", "another")
# => ArgumentError: wrong number of arguments calling `hello` (2 for 1)
hello_proc.call("Some string")
# => NoMethodError: undefined method `hello' for "Some string":String
Note I did hello_proc = :hello.to_proc before I even defined SomeClass. The Symbol#to_proc mechanism creates a variable arity proc, that knows nothing about how or where or on what class it will be called, it creates a proc that can be called on any class at all, and can be used with any number of arguments.
If it were defined in ruby instead of C, it would look something like this:
class Symbol
def to_proc
method_name = self
proc {|receiver, *other_args| receiver.send(method_name, *other_args) }
end
end
I think it is because Symbol#to_proc creates a proc with one argument. When turned into a proc, :> does not look like:
->x, y{...}
but it looks like:
->x{...}
with the requirement of the original single argument of > somehow tucked inside the proc body (notice that > is not a method that takes two arguments, it is a method called on one receiver with one argument). In fact,
:>.to_proc.arity # => -1
->x, y{}.arity # => 2
which means that applying curry to it without argument would only have a trivial effect; it takes a proc with one parameter, and returns itself. By explicitly specifying 2, it does something non-trivial. For comparison, consider join:
:join.to_proc.arity # => -1
:join.to_proc.call(["x", "y"]) # => "xy"
:join.to_proc.curry.call(["x", "y"]) # => "xy"
Notice that providing a single argument after Currying :join already evaluates the whole method.
#jrochkind's answer does a great job of explaining why :>.to_proc.curry doesn't have the behavior you want. I wanted to mention, though, that there's a solution to this part of your question:
I specifically want to create the intermediate curried function with one arg supplied, and then call then call that with the 2nd arg.
The solution is Object#method. Instead of this:
nine_is_greater_than = :>.to_proc.curry[9]
nine_is_greater_than[8]
#=> ArgumentError: wrong number of arguments (0 for 1)
...do this:
nine_is_greater_than = 9.method(:>)
nine_is_greater_than[8]
# => true
Object#method returns a Method object, which acts just like a Proc: it responds to call, [], and even (as of Ruby 2.2) curry. However, if you need a real proc (or want to use curry with Ruby < 2.2) you can also call to_proc on it (or use &, the to_proc operator):
[ 1, 4, 8, 10, 20, 30 ].map(&nine_is_greater_than)
# => [ true, true, true, false, false, false ]
I'm very new to Ruby, so please bear with me.
Why is it a syntax error to have "test" {|s| print s}? How about "test" do |s| print s end?
Thanks
You can't say this:
"test" { |s| print s }
because "test" is a string literal, not a method. The same would apply to your do/end version. You could say:
["test"].each { |s| print s }
though because Arrays are Enumerable and Enumerable has an each method.
The {} are usually used for one liners.
do/end for multiple lines.
But there is no rule, do what you prefer.
Notice:
If ever you need to pass several instructions in a one liner, separate them with ;
A block is just a chunk of code enclosed in braces or keywords do/end. As mentioned already, you typically use braces for one liners, and do/end for multiple lines of code. Blocks can appear only immediately after the calling of some method. You can think of a block as an anonymous method (one that doesn't have a method name).
In your code, you were placing a block immediately after a string literal, not a method invocation. Blocks can be used for looping, as such:
2.times { puts "hello" } # => 2
# >> hello
# >> hello
In the above code, times is a method that belongs to all integers (that is to say, it is a instance method of the Integer class). The times method executes the code in the block twice, and returns the object (2 in this case) you called it on. You can pass a block to any method, although methods that are not expecting them will simply ignore the block.
Blocks can take parameters. The parameters are placed between pipes (the '|' character). It turns out, the first example could have accepted a parameter as seen here:
2.times { |i| puts i.to_s + " hello" } # => 2
# >> 0 hello
# >> 1 hello
I've only just scratched the surface of the power of blocks. You can read more about blocks for free in the online version of Programming Ruby: The Pragmatic Programmer's Guide (aka PickAx Book). It is a couple editions old now, but for an introduction to Ruby, you should find it sufficient. Once you understand blocks, you can start using power features of Enumerable which is included in Arrays and Hashes.
lambda is used in this example in both the compose and the hydrate methods. What does lambda do here?
def compose *lambdas
if lambdas.empty?
lambda { nil }
elsif lambdas.size == 1
lambdas.first
else
lambda do |n|
lambdas.first.call(compose(*lambdas[1..-1]).call(n))
end
end
end
def hydrate(modulus, printable_form)
i = 0
lambda do |n|
(i = (i + 1) % modulus) == 0 && printable_form || n
end
end
print(((1..100).map
&compose(
hydrate(15, 'Watermelon'),
hydrate(5, 'Melon'),
hydrate(3, 'Water'))).join(' '))
My second question is - what is the need for the ampersand in front of the word compose?
The function compose takes a list of functions and returns a newly allocated function that is the composition of all the functions on the list. It's been written to treat the empty list rather oddly; it may be that the first case should be ignored. (Normally composing the empty list of functions should produce the identity function, but that's not what your example does. I would have expected
lambda do |n| { n }
as the base case.)
It's necessary to use a lambda in order to create a new function You see that in the recursive case in compose: the lambda creates a new function which when given n returns the result of calling the composition of the remaining functions, then finally applies the first function. This is not good code to emulate, as the recursion over the list of functions is repeated every time the composition is called. In the example:
Creating the composition of functions uses constant time and space
Applying the composition of functions costs linear time and space
Whereas if the code were written properly
Creating the composition of functions should cost linear time and space
Applying the composition of functions should cost linear time and should require no allocations (zero space)
Unfortunately I don't know enough Ruby to write for you an example of compose the way it ought to be done. But others will.
As a side note, I don't know where you got this exact code, but it looks like a very lightly altered version of some code from Reginald Braithwaite's blog. (The code was a deliberately over-the-top solution to the FizzBuzz question used in a serious discussion of functional programming in Ruby and functional programming more generally.)
Here are the original posts:
Don't Overthink FizzBuzz
Closures and Higher-Order Functions
Your second question asks what the & is doing.
Looking at The unary ampersand in Ruby, the ampersand converts a proc to a block.
Example:
irb(main):001:0> def meth1
irb(main):002:1> yield "Hello"
irb(main):003:1> end
=> nil
Calling meth1 with a block, works as expected:
irb(main):004:0> meth1 { |s| puts s } # Calling meth1 with a block
Hello
=> nil
Calling with a Proc does not work:
irb(main):005:0> p = Proc.new { |s| puts "In proc: #{s}" }
=> #<Proc:0x13e5d60#(irb):5>
irb(main):006:0> meth1 p
ArgumentError: wrong number of arguments (1 for 0)
from (irb):6
from C:/Ruby19/bin/irb:12:in `<main>'
But it does work if you convert the Proc to a block:
irb(main):007:0> meth1 &p # Convert the proc to a block
In proc: Hello
=> nil
This is the same thing that is happening when you use the following code:
irb(main):001:0> def meth2(&block) # Block is converted to Proc
irb(main):002:1> puts block.class.to_s if block_given?
irb(main):003:1> end
=> nil
irb(main):004:0> meth2 { puts "Hi There" }
Proc
=> nil
irb(main):005:0>
Here is another article on the differences between blocks, block vs lambda vs proc.