-
Notifications
You must be signed in to change notification settings - Fork 1
/
head_first_ruby5_blocks.rb
150 lines (102 loc) · 4.34 KB
/
head_first_ruby5_blocks.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#Blocks
#Pass a chunk of code into a method like an argument, put looping code at the top & bottom of the method, then in the middle run the code that was passed in.
#Block is a chunk of code that you associate with a method call. While the method runs, it can invoke (execute) the block one or more times. Methods & blocks work in tandem to process data.
#Defining a method that takes blocks
#Can't have a block without having a method to accept it
#& - indicates a block
#Example block with method
def my_method (&my_block) #calling this method with a block stores to "my_block"
puts "We're in the method, about to invoke your block!" #first executes code in method
my_block.call #call instance method that invokes block's code- then goes to block & puts code after do
puts "We're back in the method!" #then comes back to method
end
#example of a block
my_method do #a block must always follow a method call
puts "We're in the block!" #block body
end
#start of block marked with keyword do, & ends with end
#body consistts of 1 or more lines of Ruby code
#when block is called from the method the code in the block body will be executed
#after the block runs, control retursn to the method that invoked it
#will give a syntax error if use block without a method separately
#You can pass many different blocks to a single method
#the code in the method is always the same but you can change the code you provide in the block
#Calling a block multiple times
def twice (&my_block)
puts "In the method, about to call the block!"
my_block.call
puts "Back in the method, about to call the block again!"
my_block.call
puts "Back in the method, about to return!"
end
twice do
puts "Wooo!"
end
#Block parameters
#When defining a Ruby method can specify that it will accept one or more parameters
def print_parameters (p1, p2)
puts p1, p2
end
#can pass arguments when calling the method that will determine the value of those parameters
print_parameters("one", "two")
#A method can pass one or two arguments to a block
#Block parameters similar to method parameters, values passed when the block is run & can be accessed within the block body
def give (&my_block)
my_block_call ("2 turtle doves", "1 partridge")#passed to block
end
give do |present1, present2|#parameters separated by commas
puts "My method gave to me..."
puts present1, present2
end
#the arguments to call are passed into the block as parameters which then get printed. Once block completes control returns to method as usual
#common to use just 1 block with a method, multiple blocks with a method would be used by procs
#using "yield" keyword
#been calling methods using call method on that object
def twice (&my_block)
my_block.call
my_block.call
end
#yield keyword will find & invoke the block a method was called with- no need to declare a parameter to accept the block
def twice
yield
yield
end
#As with call, we can also give one or more arguments to yield which will be passed to the block as parameters.
def give (&my_block)
my_block.call("2 turtle doves", "1 partridge")
end
def give
yield "2 turtle doves", "1 partridge"
end
#declaring a &block parameter is useful in a few rare instances. Use yield keyword in most cases, cleaner & easier to read
#Block formats
#curly brace is another format that can be used
def run_block
yield
end
run_block do
puts "do/end"
end
run_block {puts "braces"} #start of block at start of {, end of block at }
#also accept parameters
def take_this
yield "present"
end
take_this do |thing|
puts "do/end block got #{thing}"
end
take_this { |thing| puts "braces block got #{thing}"}
#ruby blocks that fit on a single line should be surrounded with curly braces. Blocks that span multiple lines should be surrounded with do...end. Common convention, though not the only one.
#method handles the general work needed on a variety of tasks
#block handles the logic specific to an individual task
#each method
#each method loops through each of the items in an array, yielding them to a block one at a time
def my_method
yield 1
yield 2
yield 3
end
my_method { |param| puts param} #123
["a", "b", "c"].each { |param| puts param} #abc
#each is similar to a while loop - key difference is we yield the elements to a black rather than an array - we pass the element to a block
#use each method & a block to process each of the items in an array