Ruby wizardry, p.11

Ruby Wizardry, page 11

 

Ruby Wizardry
Select Voice:
Brian (uk)
Emma (uk)  
Amy (uk)
Eric (us)
Ivy (us)
Joey (us)
Salli (us)  
Justin (us)
Jennifer (us)  
Kimberly (us)  
Kendra (us)
Russell (au)
Nicole (au)

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

Larger Font   Reset Font Size   Smaller Font  

  “Oh,” Ruben said, slowly putting his hands down again.

  “Wait, you can write your own Ruby methods that take blocks?” Scarlet asked.

  “Of course!” said the knight. “You’d write it like so,” she said, and typed in the Computing Contraption:

  >> def my_block_method >> yield >> end => nil

  “First,” said the knight, “we define a method, my_block_method, using def. Next, we use the yield keyword to tell the method to let the code inside the block run; when you call the method with a block, whatever happens in the block is what the method does! Let’s look at some examples.”

  >> my_block_method { 1 + 1 } => 2

  “Here, we’re calling my_block_method and passing in a block that just adds 1 + 1, so my_block_method returns 2. We can also do other things, like print text:

  >> my_block_method { puts 'Hello from the block!' } Hello from the block! => nil

  “my_block_method lets the code in the block run, so it prints out Hello from the block! We see the nil because puts prints out text on the screen, but the value it returns is nil,” the knight explained.

  “What’s a block, again?” the King asked.

  “A block is just a bit of Ruby code between curly brackets or between do and end,” said the knight. “You’ve probably seen built-in methods like each that use blocks, but now you can create your own methods that use blocks!”

  “That’s amazing!” said Scarlet. “But can you use splat parameters and blocks together?”

  “You can!” said the knight. “You can pass regular, default, and splat arguments to any method you write, and they can be in any order.”

  The knight cracked her knuckles and typed into the Computing Contraption, explaining as she went along. “Let’s build a little something we can use to quickly and easily introduce ourselves,” she said. “After all, we knights are always having to go around introducing ourselves as we sally forth into a new town.”

  >> def all_about_me(name, age=100, *pets) >> puts "My name is #{name}" >> puts "I'm #{age} years old" >> if block_given? >> yield pets >> else >> puts pets >> end >> end => nil

  “We’re not done yet,” said the knight, “but let’s go over this. First, I defined the all_about_me method to take three parameters. We see a regular old name parameter and an age parameter, which defaults to 100 if no age is passed in when the method is called.”

  “But you could have written the age parameter with its default first, then the name one,” Ruben said.

  “You got it,” said the knight. “Finally, the *pets splat parameter! That can come in any order with respect to the regular or default parameters, but we happened to put it at the end.”

  “I get that part,” said the King, “but what’s this block_given? business?”

  “That’s a built-in Ruby method,” said the knight. “It returns true if the method was passed a block as an argument and false otherwise. I wrote the all_about_me method so it yields to the block if there is one, sending the list of pets to the block; otherwise, it just uses puts to print out the pets. Don’t worry if block_given? doesn’t make perfect sense now—we’ll be seeing more of it later on.”

  “Why is it yield pets and not just yield?” Scarlet asked.

  “An excellent question,” said the knight. “Earlier, we just wanted to let the block handle everything that was passed to our method, so we simply typed yield. Now, though, we want our block to care only about pets, so we specifically give only our list of pets to the block.”

  The knight’s fingers moved again across the Computing Contraption, giving their newly defined method a try.

  >> all_about_me('Ruben', 12, 'Smalls', 'Chucky Jim') My name is Ruben. I'm 12 years old. Smalls Chucky Jim => nil

  “That’s me!” said Ruben. “That’s amazing. What else can we do?”

  “Well,” said the Off-White Knight, “We can use that block I mentioned earlier! Look what happens if we pass a block to our method, then refer to the pets we pass in with pets:

  >> all_about_me('Ruben', 12, 'Smalls', 'Chucky Jim') { |pets| puts pets.join(' and ') } My name is Ruben. I'm 12 years old. Smalls and Chucky Jim => nil

  “This looks a lot like the last example,” said Scarlet. “But the block is pretty tricky. What’s it doing?”

  “I’ll walk you through it! First, { |pets| puts pets} would simply tell Ruby: ‘Hey, block! I’m going to pass you a variable, pets, and you should print it out.’”

  “But then all_about_me would just print out the array elements, and it wouldn’t look very nice,” Scarlet said.

  “Exactly!” said the knight. “So I’m also using a built-in Ruby method, join. Ruby array elements can be joined to make strings, so I’m using join to turn the array of pets into a string with ' and ' in the middle.”

  “Could you show us another example?” Ruben asked.

  “Sure,” said the knight. “Here’s one where we can use join to turn an array of numbers into a string with 'plus' between each number:

  >> [1, 2, 3].join(' plus ') => "1 plus 2 plus 3"

  “There’s always something new to discover in Ruby,” marveled the King.

  Into the Dagron’s Lair

  “Speaking of discoveries,” said Scarlet, “that reminds me!” She rummaged around in her pockets. “Have you ever seen anything like this before?” She held out the glittering green scale for the Off-White Knight to examine.

  “Great googly moogly!” said the Off-White Knight. “That scale looks like it belongs to the Dagron!”

  “You mean the dragon,” Ruben offered.

  “No, the Dagron,” said the Off-White Knight. “That’s her name. Though she is a dragon.”

  “A lady dragon!” said Ruben.

  “No, just a dragon,” said the Off-White Knight. “If she were a man, would you call her a man dragon?”

  “I guess not,” admitted Ruben. He looked around nervously. “But there’s really a dragon in the Carmine Pines?”

  “Not to worry,” said the knight. “The Dagron is a very powerful dragon, but she’s also wise and well mannered. In fact, I’m surprised you found one of her scales anywhere trouble’s been brewing. That doesn’t sound like the Dagron I know.”

  “Well, it sounds like we’d best find her and ask what’s going on,” said the King. “Lead the way, madam knight!”

  “To the Dagron!” said the Off-White Knight, flipping her visor down over her eyes. “This way!” The knight set off deeper into the forest, and the King, Scarlet, and Ruben followed.

  After walking for a few minutes, they began to hear a low, rhythmic whooshing sound, like someone squeezing bellows on a fire.

  “What’s that?” Ruben whispered.

  “The Dagron!” whispered the knight. “Here she is!” And before they knew it, they found themselves in front of an enormous dragon curled up in a shining green circle, asleep.

  “Dagron!” the knight called, pushing her visor up on her helmet.

  The Dagron didn’t open her eyes. “Yes?” she boomed, a thin plume of smoke rising from her right nostril.

  “I’ve brought some guests to see you, including the King!”

  The Dagron’s eyes flashed open, focusing immediately on the four of them. The Dagron unfurled herself and reared up to her full height; her head nearly reached the tops of the pines around her.

  “Your Majesty!” said the Dagron, and she bowed so low that her head nearly brushed the earth.

  “Madame Dagron,” said the King. “We’ve come with a somewhat . . . unusual question.” The King nodded toward Scarlet. “Does this belong to you?”

  Scarlet pulled the scale from her pocket and held it out to the Dagron. The Dagron stared at it for a few seconds, then shook her head slowly.

  “I don’t think that’s one of mine,” said the Dagron, “but I do have a great many scales. If you’d like, you can check to see if I’m missing one.”

  The group spent almost an hour examining the Dagron, looking for a loose or missing scale. Scarlet and Ruben searched high and low. The Off-White Knight quested mightily. The King took a short nap beneath a tall red pine.

  “Well, there’s no doubt about it,” Scarlet finally said, holding the mystery scale near the tip of the Dagron’s tail. “This is definitely not one of the Dagron’s.” She put the scale in her pocket and sat glumly next to Ruben on a rock.

  “Though I’m pleased not to be a suspect in these strange goings-on,” said the Dagron, “I am sorry to disappoint you.” She thought for a moment. “While I’m not certain I can help, I may know someone who can.”

  Scarlet perked up. “Who?” she asked.

  “Wherefore the Wand’ring Minstrel,” said the Dagron. “He frolics and sings all throughout the Carmine Pines and has been almost everywhere in the kingdom. If anything strange is going on, I’m sure he’d know about it.”

  Ruben jumped off his rock. “Can you take us to him?” he asked.

  “Certainly,” said the Dagron. “It may take us a while to find him, though.”

  Scarlet stood and dusted herself off. “Actually, I’ll bet we can find him pretty quickly,” she said. “Now that we know how to define our own Ruby methods, I might know just the thing!”

  You Know This!

  Between defining your own methods, creating your own methods that use blocks, and learning about things like splat and default arguments, your head’s probably feeling pretty full! Let’s take some time to review what we talked about in this chapter.

  First, you learned how to write your own methods. We start our method definition with def, followed by the name of the method and then a list of parameters between parentheses. Finally, we type whatever code we want our method to perform and then finish it all up with end, like so:

  >> def multiply_by_three(number) >> number * 3 >> end >> multiply_by_three(2) => 6

  You also learned that methods can have default or optional parameters. If we provide an argument to a method that takes an optional parameter, the method will use that argument; otherwise, it’ll use whatever its default is:

  >> def multiply_by_three(number=2) >> number * 3 >> end >> multiply_by_three => 6 >> multiply_by_three 3 => 9

  If we want a method that takes any number of arguments, we can use splat parameters by putting an asterisk (*) before our parameter name:

  >> def print_all_the_names(*names) >> puts names >> end >> print_all_the_names('Larry', 'Curly', 'Moe') Larry Curly Moe => nil

  Speaking of nil, you learned that methods that don’t have an explicit return value will return nil, which is Ruby’s way of saying “nothing at all.” Remember, returning a value is different from just printing it on the screen!

  >> puts 'Beware the Dagron!' Beware the Dagron! => nil

  In fact, when it comes to return values, it’s more common to leave off the return and let Ruby automatically return the result of the last bit of code it runs. So while you can write this:

  >> def just_return_two >> return 2 >> end >> just_return_two => 2

  It’s much better Ruby style to write this:

  >> def also_returns_two >> 2 >> end >> also_returns_two => 2

  Finally, we saw that if we want to define a method that takes a block, we just need to use the handy yield keyword. We can yield without parameters to give control over to the block, or we can pass parameters in order to give the block arguments to work with.

  >> def block_party >> yield >> end >> block_party { puts 'Hello from the block!' } Hello from the block! => nil >> def block_party_part_two(name) >> yield name >> end >> block_party_part_two('Haldo') { |name| puts "This is #{name}'s party!" } This is Haldo's party! => nil

  You learned a lot in this chapter, but keep in mind: if you’re ever curious about what a method does or what arguments it expects, you can always look up the Ruby documentation at http://ruby-doc.org/. Just make sure to ask your local adult before going online!

  Speaking of looking up new things, we’ll be covering a bit of new Ruby code in the next chapter—specifically, how to organize, create, and control our very own Ruby objects.

  Chapter 8. Everything Is an Object (Almost)

  The Subject of Our Story Is an Object

  Scarlet ran to the Computing Contraption. “Do you know the name of that directory of everyone in the kingdom?” she called to the King. “It’s a hash that associates everyone’s name with his or her address.”

  “Let’s see,” said the King. “Ah, yes! I’m pretty sure it’s called citizens.”

  Scarlet nodded and began typing into IRB. When she pressed ENTER, this is what she saw:

  >> citizens => { :aaron_a_aardvark => 'A van down by the river', :alice_b_abracadabra => 'The green house with two chimneys', :trady_blix => 'Mal Abochny', # ...and so on and so forth

  The King peered over her shoulder. “That’s it!” he said. “But whoa! There must be a bajillion people in the kingdom! How will we find Wherefore?”

  Scarlet typed some more:

  >> citizens.size => 24042

  “Yeah, the hash is definitely too big to go through by hand,” Scarlet said, “but I bet we can write our own method to find him!”

  Ruben studied the citizens hash for a minute. “Remember how we could get the value of a hash key by typing the hash name, then the key in square brackets?” he asked.

  “Yep,” Scarlet said.

  “Well,” Ruben said, “what if we just write a method that takes a person’s name and the citizens hash, then tries to find that name in the hash?”

  “Ruben, you’re a genius!” Scarlet said. She quickly typed:

  >> def find_person(name, people) >> if people[name] >> puts people[name] >> else >> puts 'Not found!' >> end >> end

  “Hang on, hang on. What’s all this?” the King asked. “Just a quick method I whipped up,” Scarlet said. “See? It’s called find_person, and it takes a person’s name as a symbol and a hash of people as parameters. If it finds the name in the hash, it prints it out; otherwise, it says the name’s not found!” She typed:

  >> find_person(:wherefore, citizens) => One half mile due east!

  “There it is!” Scarlet said. “It found the :wherefore key in the citizens hash.”

  “One half mile due east!” said the Off-White Knight. “That should only take a few minutes, and east is that way. Let’s go!”

  The Dagron rose to her full height, blotting out the sun for an instant. “I’ll come as well,” she said. “Wherefore and I are old friends, and we haven’t spoken in some time. It will be good to see him again.”

  “Well, then,” said the King, “lead the way!”

  The Off-White Knight and the Dagron turned and headed toward the late morning sun, and the King, Scarlet, and Ruben followed. The trees became taller and closer together as they walked, and after a few minutes, the sun could only be seen as a warm red light through the tops of the Carmine Pines.

  “Hold on a second,” Ruben said, stopping and turning his head to one side. “Do you hear that?”

  They all paused. The King cupped his hand to his ear, shook his head, wiggled his little finger around in his ear, then cupped his hand to it again. “I don’t hear anything,” he said.

  “I think I hear it too,” said the Dagron. “It’s—”

  “Music!” cried Ruben. “It’s coming from over there!” He pointed a little to the right of where they’d been headed.

  “Let’s go!” said Scarlet, and the group pressed on into the Pines.

  The music grew louder, and after walking through a particularly dense thicket of trees, the group found themselves on the edge of a small meadow. In the very center, perched on a wide tree stump, was a man in a scarlet tunic and archer’s cap with a long white feather in it. He was playing a pink mandolin and occasionally stopping to furiously scribble on a long roll of parchment with a quill pen, which sported the same type of long white feather as his cap.

  “Wherefore!” boomed the Dagron.

  The man on the stump stopped scribbling and looked up. A wide grin broke out across his face. “The Dagron!” he called. “Wonderful to see you! Come in, come in, come in.”

  Led by the Dagron, the group crossed the meadow and circled around Wherefore. Wherefore leapt nimbly from his stump, removed his cap, and bowed deeply.

  “Friends,” he said, “welcome to my forest stronghold!” He gestured to the stump. “It’s not much to look at now, but I’ve always had a weak spot for a fixer-upper. And I,” he said, “am your humble host, Wherefore the Wand’ring Minstrel.” Wherefore replaced his cap on his head. “I know, of course, the Dagron, and I’ve met the Off-White Knight before.” He looked at the King and pressed his palms together. “Your Majesty,” he said. “I’ve not had the pleasure of meeting you before, but it is a pleasure.”

  “Likewise,” said the King. “We’ve heard much about you!”

  Wherefore turned to Ruben and Scarlet. “Which leaves you fine rapscallions. What do you call yourselves?”

  “I’m Scarlet,” said Scarlet, “and this is Ruben.”

  “Hi!” said Ruben.

  “Hello and hello!” said Wherefore. “Wonderful to meet you. I’m afraid you’ve caught me at a bit of a bad time, though.” He sighed. “I’ve spent all morning writing a ballad, and it’s hardly half done. I’ve got to get back to it immediately if I’m going to finish it before nightfall.”

  “A ballad?” said Scarlet.

  “Oh, yes,” Wherefore said, “you see, I’m something of a businessman. I operate a small-time ballad delivery service with dozens of customers. The only catch is,” he said, “that this means I do in fact have dozens of customers, and each ballad takes me hours to write. I can hardly keep up!” He pulled a handkerchief from his tunic pocket and mopped his brow.

  The Dagron hummed thoughtfully, exhaling little puffs of smoke. “You know,” she said, “I think I can be of service.” She looked around the nearly empty meadow. “But I’ll need a little Ruby magic. Do you happen to have a Computing Contraption nearby?”

 

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
Add Fast Bookmark
Load Fast Bookmark
Turn Navi On
Turn Navi On
Turn Navi On
Scroll Up
Turn Navi On
Scroll
Turn Navi On
183