This commit is contained in:
Roman Pushkin 2019-02-01 21:21:37 -08:00
parent 99e1a1bfdd
commit dfd61fffd8
3 changed files with 177 additions and 0 deletions

98
manuscript/040.txt Normal file
View file

@ -0,0 +1,98 @@
## Arrays
Array is just a set of data. For example, array of tenants living in apartment building. Or array of numbers where each number has some meaning (for example, employee salary). Or array of objects: each object represents employee with multiple properties like salary, age, name, and so on.
In Ruby each element in array can be of different type. In other words, arrays look like a bucket where we can put apples, pears, some tape recordings, and a couple of aircraft ships. But usually arrays are homogeneous: all items (or "elements") are of the same type.
But the question is why do we need arrays? Why would we need to put something into array? The question is quite simple: arrays are useful, because they represent a _set_ of some data and we can perform bulk operations over this data. Let's say we have a list of visited cities:
```ruby
arr = ['San Francisco', 'Moscow', 'London', 'New York']
```
We initialized array with four elements inside of type _String_. Ruby knows it's array because we used square brackets for array definition. We can perform variety of different useful operations over this data. For example, get the number of elements (visited cities):
```
$ irb
...
> arr.size
=> 4
```
Or just sort array in alphabetical order:
```
$ irb
...
> arr.sort
=> ["London", "Moscow", "New York", "San Francisco"]
```
Or we can _iterate_ over array (walk over each element):
```ruby
arr = ['San Francisco', 'Moscow', 'London', 'New York']
arr.each do |word|
puts "Word #{word} has #{word.size} letters"
end
```
Output:
```
Word San Francisco has 13 letters
Word Moscow has 6 letters
Word London has 6 letters
Word New York has 8 letters
```
And nothing prevents developer from defining empty array:
```ruby
arr = []
```
But why would we need an empty array? For the same purpose we need empty bucket -- to put something inside on later steps. There are many ways to put something into array, but there are two standard ways:
* `arr.push(123)` - method `push` also implemented in some other languages (like JavaScript), and some programmers prefer this way.
* `arr << 123` - double arrow shows to _where_ we want to put something.
And trivial phonebook program could look like this:
{title="Trivial Phone Book Program, version 1", lang=ruby, line-numbers=on}
```ruby
arr = []
loop do
print 'Type name and number (empty string to finish): '
entry = gets.chomp
break if entry.empty?
arr << entry
end
puts 'Your phone book:'
arr.each do |element|
puts element
end
```
Result:
```
Type name and number (empty string to finish): Saul 12345
Type name and number (empty string to finish): Mummy (555) 111-22-33
Type name and number (empty string to finish): Honey (555) 12345
Type name and number (empty string to finish): Honey 2 (555) 98765
Type name and number (empty string to finish):
Your phone book:
Saul 12345
Mummy (555) 111-22-33
Honey (555) 12345
Honey 2 (555) 98765
```
Of course, this phone book application is minimalistic and lacks lots of features, program doesn't save any data to disk, no search by name or phone number, but it works! We were able to save data temporarily and show the list of contacts on the screen. We can invoke `arr.sort` to sort all elements in our phonebook, so result looks much better!
X> ## Exercise 1
X> Run this program and think about adding `arr.sort` line. Where would you put it?

76
manuscript/041.txt Normal file
View file

@ -0,0 +1,76 @@
## Few Words About "Each"
Array is [represented](https://ruby-doc.org/core-2.5.2/Array.html) by _Array_ type and this type implements method `each`. You are already familiar with this method when we were performing action over each element. Technically, method `each` _accepts block_. As we mentioned before, you can pass block to any method, and further behavior of a program depends on what's "under the hood" of this method.
So that method `each` runs what's inside the block for each element of array. In other words, it runs (usually tiny) sub-program for every item:
```ruby
arr.each do |item|
# here we have sub-program
# it may have multiple lines
end
```
Or it can be done with one line:
```ruby
arr.each { |item| ...here we have 1-line sub-program... }
```
Examples above show that blocks accept parameters (`item` in our case). This parameter comes from `each` method, and it's just next element of array. Everything between `do` and `end` (or between `{` and `}`) is block. This way ruby implements iteration over array (or "array iteration", "iteration over each element of array", "array traversal").
We can specify any name as parameter. In example from previous chapter (iteration over cities) we used `word` as parameter name. Phone book application has `element` as parameter name. And in this chapter we have `item`. The only rule here is parameter name should be understandable for you and your team (ideally, tools like Rubocop must be also okay with that).
Method `each` looks like calling your own method:
```ruby
def my_method(word)
puts "Word #{word} has #{word.size} letters"
end
```
Compare it with `each`:
```ruby
arr.each do |word|
puts "В слове #{word} #{word.size} букв"
end
```
It's sad that in Ruby you can't pass the name of a method to `each`:
```ruby
arr.each my_method
```
It would be a nice language feature. Note: actually, you can write the similar code, but 1) not exactly this way 2) with some limitations 3) nobody doesn't do it anyway.
Method `each` is also implemented in some other types. Iteration over something is operation which is pretty often used by programmers here and there, and you'll see iteration in some not very obvious places. For example, iteration over string (object of _String_ type):
```
$ irb
> 'hello'.each_char { |x| puts x }
h
e
l
l
o
```
 Method `each` for _Range_ type:
```ruby
(1001..1005).each do |x|
puts "I'm robot #{x}"
end
```
Result:
```
I'm robot 1001
I'm robot 1002
I'm robot 1003
I'm robot 1004
I'm robot 1005
```

View file

@ -37,6 +37,9 @@
037.txt
038.txt
039.txt
040.txt
041.txt