How does this code with send :[] work? - ruby

The following code generates an output of 9. I understand send is simply calling the method :[], but am confused how the parameters work.
x = [1,2,3]
x.send :[]=,0,4 #why is x now [4,2,3]
x[0] + x.[](1) + x.send(:[],2) # 4 + 2 + 3
How do line 2 and line 3 work?

Object#send provides another way to invoke a method.
x.send :[]=,0,4
is saying, invoke []= method on x, and pass the argument 0, 4, it's equivalent to:
x[0] = 4
The name send is because in Ruby, methods are invoked by sending a message to an object. The message contains the method's name, along with parameters the method may need. This idea comes from SmallTalk.

x.send(:[]=, 0, 4)
is the same* as
x.[]=(0, 4)
which has the syntactic sugar of
x[0] = 4
which should be familiar from other languages.
Parentheses are, of course, optional.
The .send or .public_send variety has the advantage that the method to invoke doesn't have to be hardcoded—it can come from a variable.
All this is congruent with ruby's paradigm of object orientedness: objects communicate with each other by sending messages, and the messages trigger code execution.
*almost, #send will invoke private methods too

Line 2 is
x.send :[]=,0,4
That is basically a fancy way of writing this:
x[0] = 4
(Calling send allows you to call private methods though, and that is one difference between the two syntaxes. Also, an object could conceivably override the send method, which would break the first syntax.)
So line 2 has the effect of writing 4 into the first spot in the array.
Now on line 3, we see that we are adding up three things. Here is a list of the things we are adding:
x[0] - the first element
x.[](1) - another syntax for accessing elements, which accesses the second element. This syntax is a traditional method call, where the name of the method happens to be [].
x.send(:[], 2) - This shows another feature of Ruby, which is the send method. It accesses the third element.
So the result will be 9, because the third line adds the first, second, and third elements of the array.
These examples appear to illustrate an interesting point about the design of the Ruby language. Specifically, array accesses are implemented as method calls. The preferred syntax for writing to an array is x[0] = 4 and the preferred syntax for reading is x[0], because that syntax is familiar to programmers from many different languages. However, reading and writing from arrays is actually implemented using method calls under the hood, and that's why it is possible to use some other syntaxes that look more like a traditional method call.
A traditional method call looks like this: object.foo(arg1, arg2, arg3, ...).
The send thing shown above is a useful feature of Ruby that allows you to specify which method you are calling using a symbol, instead of forcing you to type the exact name. It also lets you call private methods.

Related

Sum array of numbers [duplicate]

This question already has answers here:
How to sum array of numbers in Ruby?
(16 answers)
Closed 8 years ago.
Q: Write a method, sum which takes an array of numbers and returns the sum of the numbers.
A:
def sum(nums)
total = 0
i = 0
while i < nums.count
total += nums[i]
i += 1
end
# return total
total
end
There has to be another way to solve this without using while, right? Anyone know how?
Edit: This is not an exam or test. This is a practice problem provided on github for app academy. They provide the question and answer as an example. I just read however that good programmers don't like to use while or unless, so I was curious if I could learn something to solve this problem a better way. Like with enumerable? (Noob at Ruby here, obviously..)
Also, I would love any walkthrough or methods that I should learn.. This question is also different because I am asking for specific examples using this data.
The usual way of doing that would be this:
def sum(nums) nums.reduce(&:+) end
which is short for something like this:
def sum(nums) nums.reduce(0) { |total, num| total + num } end
I see that Neil posted a similar solution while I was typing this, so I'll just note that reduce and inject are two names for the same method - Ruby has several aliases like this so that people used to different other languages can find what they're looking for. He also left off the &, which is optional when using a named method for reduce/inject, but not in other cases.
Explanation follows.
In Ruby you don't normally use explicit loops (for, while, etc.). Instead you call methods on the collection you're iterating over, and pass them a block of code to execute on each item. Ruby's syntax places the block after the arguments to the method, between either do...end or {...}, so it looks like traditional imperative flow control, but it works differently.
The basic iteration method is each:
[1,2,3].each do |i| puts i end
That calls the block do |i| puts i end three times, passing it 1, then passing it 2, and finally passing it 3. The |i| is a block parameter, which tells Ruby where to put the value(s) passed into the block each time.
But each just throws away the return value of the block calls (in this case, the three nils returned by puts). If you want to do something with those return values, you have to call a different method. For example, map returns an array of the return values:
[1,2,3].map do |i| puts i end
#=> [nil, nil, nil]
That's not very interesting here, but it becomes more useful if the block returns something:
[1,2,3].map do |i| 2*i end
#=> [2,4,6]
If you want to combine the results into a single aggregate return value instead of getting back an array that's the same size as the input, that's when you reach for reduce. In addition to a block, it takes an extra argument, and the block itself is also called with an extra argument. The extra parameter corresponding to this argument is called the "accumulator"; the first time the block is called, it gets the argument originally passed to reduce, but from then on, it gets the return value of the previous call to the block, which is how each block call can pass information along to the next.
That makes reduce more general than map; in fact, you can build map out of reduce by passing in an empty array and having the block add to it:
[1,2,3].reduce([]) do |a,i| a + [2*i] end
#=> [2,4,6]
But since map is already defined, you would normally just use it for that, and only use reduce to do things that are more, well, reductive:
[1,2,3].reduce(0) do |s, i| s + 2*i end
#=> 12
...which is what we're doing in solving your problem.
Neil and I took a couple extra shortcuts. First, if a block does nothing but call a single method on its parameters and return the result, you can get an equivalent block by prefixing &: to the method name. That is, this:
some_array.reduce(x) do |a,b| a.some_method(b) end
can be rewritten more simply as this:
some_array.reduce(x, &:some_method)
and since a + b in Ruby is really just a more-familiar way of writing the method call a.+(b), that means that you can add up numbers by just passing in &:+:
[1,2,3].reduce(0, &:+)
#=> 6
Next, the initial accumulator value for reduce is optional; if you leave it out, then the first time the block is called, it gets the first two elements of the array. So you can leave off the 0:
[1,2,3].reduce(&:+)
#=> 6
Finally, you normally need the & any time you are passing in a block that is not a literal chunk of code. You can turn blocks into Proc objects and store them in variables and in general treat them like any other value, including passing them as regular arguments to method calls. So when you want to use one as the block on a method call instead, you indicate that with the &.
Some methods, including reduce, will also accept a bare Symbol (like :+) and create the Proc/block for you; and Neil took advantage of that fact. But other iterator methods, such as map, don't work that way:
irb(main):001:0> [-1,2,-3].map(:abs)
ArgumentError: wrong number of arguments (1 for 0)
from (irb):1:in `map'
from (irb):1
from /usr/bin/irb:12:in `<main>'
So I just always use the &.
irb(main):002:0> [-1,2,-3].map(&:abs)
#=> [1, 2, 3]
There are lots of good online tutorials for Ruby. For more general information about map/reduce and related concepts, and how to apply them to problem-solving, you should search for introductions to "functional programming", which is called that because it treats "functions" (that is, blocks of executable code, which in Ruby are realized as Proc objects) as values just like numbers and strings, which can be passed around, assigned to variables, etc.
Probably the most idiomatic way of doing this in Ruby is:
nums.inject(:+)
. . . although this basically hides all the working, so it depends what the test is trying to test.
Documentation for Array#inject

Why does 1+1 work, but not other methods, in Ruby?

In Ruby, it's possible to rewrite 1.+(1) as 1 + 1. However, it's not possible to do this for other methods, such as 1.to_s, and rewrite them as 1to_s or 1 to_s. Why is this?
In other words, why is it possible to call 1+1 but not for other methods? Is this, among other methods, a nicety that's allowed by the interpreter?
Note that this works for other math operators/methods such as / and **.
a + b is just syntactic sugar for the method call a.+(b) (and the same is true for the other operators). This transformation is done during parsing. You can see it here, in ruby's bison grammar. In particular, the rule for a + b uses call_bin_op to construct the abstract syntax tree node to return, which is a macro that forwards to call_bin_op_gen, which calls NEW_CALL, which builds an AST node representing a method call.
As you state: "In Ruby, everything is an object", therefore all the things you can do end up being method calls. There is some syntactic sugar involved in making 1+1 call the #+() method of the Fixnum object 1 (you actually cannot define this yourselves as pointed out by #Ismail Badawi, it is part of the ruby language definition).
However as to_s already is a method call there is not much you can do about it. You may call it as 1.to_s(), but it is only possible to omit the . if there is no ambiguity involved and there is bound to be some in your example.

Why were ruby loops designed that way?

As is stated in the title, I was curious to know why Ruby decided to go away from classical for loops and instead use the array.each do ...
I personally find it a little less readable, but that's just my personal opinion. No need to argue about that. On the other hand, I suppose they designed it that way on purpose, there should be a good reason behind.
So, what are the advantages of putting loops that way? What is the "raison d'etre" of this design decision?
This design decision is a perfect example of how Ruby combines the object oriented and functional programming paradigms. It is a very powerful feature that can produce simple readable code.
It helps to understand what is going on. When you run:
array.each do |el|
#some code
end
you are calling the each method of the array object, which, if you believe the variable name, is an instance of the Array class. You are passing in a block of code to this method (a block is equivalent to a function). The method can then evaluate this block and pass in arguments either by using block.call(args) or yield args. each simply iterates through the array and for each element it calls the block you passed in with that element as the argument.
If each was the only method to use blocks, this wouldn't be that useful but many other methods and you can even create your own. Arrays, for example have a few iterator methods including map, which does the same as each but returns a new array containing the return values of the block and select which returns a new array that only contains the elements of the old array for which the block returns a true value. These sorts of things would be tedious to do using traditional looping methods.
Here's an example of how you can create your own method with a block. Let's create an every method that acts a bit like map but only for every n items in the array.
class Array #extending the built in Array class
def every n, &block #&block causes the block that is passed in to be stored in the 'block' variable. If no block is passed in, block is set to nil
i = 0
arr = []
while i < self.length
arr << ( block.nil? ? self[i] : block.call(self[i]) )#use the plain value if no block is given
i += n
end
arr
end
end
This code would allow us to run the following:
[1,2,3,4,5,6,7,8].every(2) #= [1,3,5,7] #called without a block
[1,2,3,4,5,6,7,8,9,10].every(3) {|el| el + 1 } #= [2,5,8,11] #called with a block
Blocks allow for expressive syntax (often called internal DSLs), for example, the Sinatra web microframework.
Sinatra uses methods with blocks to succinctly define http interaction.
eg.
get '/account/:account' do |account|
#code to serve of a page for this account
end
This sort of simplicity would be hard to achieve without Ruby's blocks.
I hope this has allowed you to see how powerful this language feature is.
I think it was mostly because Matz was interested in exploring what a fully object oriented scripting language would look like when he built it; this feature is based heavily on the CLU programming language's iterators.
It has turned out to provide some interesting benefits; a class that provides an each method can 'mix in' the Enumerable module to provide a huge variety of pre-made iteration routines to clients, which reduces the amount of tedious boiler-plate array/list/hash/etc iteration code that must be written. (Ever see java 4 and earlier iterators?)
I think you are kind of biased when you ask that question. Another might ask "why were C for loops designed that way?". Think about it - why would I need to introduce counter variable if I only want to iterate through array's elements? Say, compare these two (both in pseudocode):
for (i = 0; i < len(array); i++) {
elem = array[i];
println(elem);
}
and
for (elem in array) {
println(elem);
}
Why would the first feel more natural than the second, except for historical (almost sociological) reasons?
And Ruby, highly object-oriented as is, takes this even further, making it an array method:
array.each do |elem|
puts elem
end
By making that decision, Matz just made the language lighter for superfluous syntax construct (foreach loop), delegating its use to ordinary methods and blocks (closures). I appreciate Ruby the most just for this very reason - being really rational and economical with language features, but retaining expressiveness.
I know, I know, we have for in Ruby, but most of the people consider it unneccessary.
The do ... end blocks (or { ... }) form a so-called block (almost a closure, IIRC). Think of a block as an anonymous method, that you can pass as argument to another method. Blocks are used a lot in Ruby, and thus this form of iteration is natural for it: the do ... end block is passed as an argument to the method each. Now you can write various variations to each, for example to iterate in reverse or whatnot.
There's also the syntactic sugar form:
for element in array
# Do stuff
end
Blocks are also used for example to filter an array:
array = (1..10).to_a
even = array.select do |element|
element % 2 == 0
end
# "even" now contains [2, 4, 6, 8, 10]
I think it's because it emphasizes the "everything is an object" philosophy behind Ruby: the each method is called on the object.
Then switching to another iterator is much smoother than changing the logic of, for example, a for loop.
Ruby was designed to be expressive, to read as if it was being spoken... Then I think it just evolved from there.
This comes from Smalltalk, that implements control structures as methods, thus reducing the number of keywords and simplifying the parser. Thus allowing controll strucures to serve as proff of concept for the language definition.
In ST, even if conditions are methods, in the fashion:
boolean.ifTrue ->{executeIfBody()}, :else=>-> {executeElseBody()}
In the end, If you ignore your cultural bias, what will be easier to parse for the machine will also be easier to parse by yourself.

Block in Ruby compared to Smalltalk

What does block in Ruby mean? It looks similar with Smalltalk, but you can't send messages to it.
For example, in smalltalk:
[:x | x + 3] value: 3
returns 6. But in ruby:
{|x| x + 3}.call 3
will cause SyntaxError.
Well, you can pass messages to lambda in ruby, though:
irb(main):025:0> ->(x){x+3}.call 3
=> 6
So in Ruby, block is not a block, but lambda is a block? Is this true? I mean, are there any differences between ruby lambda and smalltalk block? If this is true, then what is a ruby block?
Update:
From the comment and answer below, together with some googling, I guess I
have more understanding of Ruby block. In Ruby, usually a piece of code evaluates an value, and every value is an object. But, block doesn't evaluate an value. So it's not an object. Instead it can act as part of an object. For example, in {|x| x + 3} can act as a part of the object proc {|x| x + 3 }.
But it did confuse me. In smalltalk, almost every expression can be divided into objects (binding to variables are exceptions). It seems in Ruby, there are more exceptions.
First and the most important thing that Ruby block isn't: an object. It is a syntactic construct, and also obviously has an equivalent implementation - but it is not an object, and thus can't receive messages. Which makes your example of
{|x| x + 3}.call 3
ungrammatical. Lambdas, procs - those are objects that wrap a block, and have a call method which executes the block.
Thus, a block is simply a piece of code which can be passed to a method, outside the argument list - no more, no less. If you pass it to Proc.new constructor, for example, it will wrap it and give you an object you can handle:
Proc.new {|x| x + 3}.call 3
A precision:
I would even say that in smalltalk even binding is made up with object.
Think of the MethodContext.
What you are actually doing is to store the object in the MethodContext.
So
a := Object new
Can be rewrite in:
thisContext at: 1 put: Object new.
But obviously you wont write it this way since you need to know were are the temps variable.
A block in Smalltalk is an anonymous object. Syntactically, it is delimited by a [ ... ] pair.
When evaluated, it will return the last expression evaluated within itself, and there are lots of methods in its protocol.
Here are the Class comments for Blocks from a Smalltalk (in this instance, Dolphin Smalltalk 6.03 Community Edition)
"Blocks encapsulate a sequence of statements to be performed at a later time. Blocks may capture (or "close over") runtime state, such as the values of temporary variables, from the enclosing lexical scope at the point where they are created. When evaluated a block executes as if in the lexical scope in which it was defined, except that blocks may have arguments that are bound at the time of evaluation. Blocks may be passed as arguments with messages to other objects and evaluated by those objects when appropriate, and thus form a very powerful and generic "pluggability" mechanism that is a core feature which provides much of the power of Smalltalk".
By contrast, a block in Ruby is simply a parameter string. It's syntactically delimited by a { ... } pair, but it has no methods of its own.

Ruby method, Proc, and block confusion

I have a couple questions about Ruby's methods, procedures, and blocks that strike me as rather odd. They're not so much about syntax or function as the logic behind the decisions made.
Question 1:
Why is it that blocks can be passed to methods (e.g. each) but they cannot be assigned to a variable?
I know you can pass them around in procedures, i.e. p = Proc.new {...} (accessed with &p), but it doesn't make much sense to make the programmer go through these means.
Question 2:
Why is there a differentiation between methods and procedures?
For instance, I can accomplish the task of defining a function and calling that function in the following two ways:
def square(x)
x**2
end
square(3)
=> 9
or
square = lambda {|x| x**2}
square.call(3)
=> 9
Why the differentiation? In Python for example both defining a function in the standard way and by square = lambda x: x**2 accomplish the same task of creating the function and assigning it to square.
Question 1: Blocks are not objects, they are syntactic structures; this is why they cannot be assigned to a variable. This is a privilege reserved for objects.
Question 2: Methods are not objects, so they cannot receive messages. Inversely, procs and lambdas are objects, so they cannot be invoked like methods, but must receive a message that tells them to return a value on the basis of the parameters passed with the message.
Procs and Lambdas are objects, so they can receive the call message and be assigned to names. To summarize, it is being an object that makes procs and lambdas behave in ways you find odd. Methods and blocks are not objects and don't share that behavior.
To some extent at least, methods are objects:
class ABC
def some_method
end
end
ABC.instance_method(:some_method) #=> #<UnboundMethod: ABC#some_method>
Further to that, there is a built-in class: Method, as documented here.
See also this: http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Method_Calls
Haphazardly <bseg>, it does rather seem to bear out the everything-is-an-object thing. In this particular case, it just appears to take a little more digging to see.
(I really must make an effort to understand this better: I'm starting to think it's fundamental to getting a deeper understanding.)
Methods are methods — that is, they're actions that an object can take in response to messages. They are not functions.
Blocks are closures — they're functions that close over the enclosing scope. They don't conceptually "belong to" a given object.
In some languages, methods are merely functions that are members of an object, but Ruby does not view them this way. Separating a method from its owning object is more akin to surgery than simple assignment. Ruby takes its object-orientation model from Smalltalk, the granddaddy of modern OO.

Resources