|
| 1 | +--- |
| 2 | +layout: page |
| 3 | +title: "Offical Ruby FAQ" |
| 4 | +lang: en |
| 5 | + |
| 6 | +header: | |
| 7 | + <div class="multi-page"> |
| 8 | + <a href="../" title="Part 1">1</a> |
| 9 | + <span class="separator"> | </span> |
| 10 | + <a href="../2/" title="Part 2">2</a> |
| 11 | + <span class="separator"> | </span> |
| 12 | + <a href="../3/" title="Part 3">3</a> |
| 13 | + <span class="separator"> | </span> |
| 14 | + <a href="../4/" title="Part 4">4</a> |
| 15 | + <span class="separator"> | </span> |
| 16 | + <a href="../5/" title="Part 5">5</a> |
| 17 | + <span class="separator"> | </span> |
| 18 | + <a href="../6/" title="Part 6">6</a> |
| 19 | + <span class="separator"> | </span> |
| 20 | + <a href="../7/" title="Part 7">7</a> |
| 21 | + <span class="separator"> | </span> |
| 22 | + <a href="../8/" title="Part 8">8</a> |
| 23 | + <span class="separator"> | </span> |
| 24 | + <a href="../9/" title="Part 9">9</a> |
| 25 | + <span class="separator"> | </span> |
| 26 | + <a href="../10/" title="Part 10">10</a> |
| 27 | + <span class="separator"> | </span> |
| 28 | + <strong>11</strong> |
| 29 | + </div> |
| 30 | + <h1>Official Ruby FAQ</h1> |
| 31 | +
|
| 32 | +--- |
| 33 | + |
| 34 | +11. Other Features |
| 35 | + |
| 36 | +11.1 What does a ? b : c mean? |
| 37 | + |
| 38 | +It's the same as saying if a then b else c end. |
| 39 | + |
| 40 | +11.2 How can I count the number of lines in a file? |
| 41 | + |
| 42 | +Assuming that the file ends in a linefeed, the following code may give the fastest result. |
| 43 | + |
| 44 | + |
| 45 | + |
| 46 | +open("example").read.count("\n") # -> 3 |
| 47 | + |
| 48 | +11.3 What do begin and end of MatchingData return? |
| 49 | + |
| 50 | +They act with $ , and return the start index and the end index of the matched data ($0) in the original string. See an example in tab expansion. |
| 51 | + |
| 52 | +11.4 How can I sum the elements in an array? |
| 53 | + |
| 54 | +Rather than solve the specific problem, let's solve the general case. The first thing we'll do is produce a method that will iterate over an Enumerable object and collect a single result. Smalltalk calls that method inject, so we will too: |
| 55 | + |
| 56 | + |
| 57 | + |
| 58 | +module Enumerable |
| 59 | + |
| 60 | + # inject(n) { |n, i| ...} |
| 61 | + def inject(n) |
| 62 | + each { |i| |
| 63 | + n = yield(n, i) |
| 64 | + } |
| 65 | + n |
| 66 | + end |
| 67 | +end |
| 68 | + |
| 69 | +Notice how we've added the method to Enumerable. This means that anything that includes Enumerable can now use inject. But how do we use it? It takes a single argument `n' and a block. For each element in the thing being enumerated, it calls the block, passing in `n' and the element itself. The result of the block is assigned back to `n'. So, to define sum, we could write: |
| 70 | + |
| 71 | + |
| 72 | + |
| 73 | +module Enumerable |
| 74 | + def sum |
| 75 | + inject(0) {|n, i| n + i } |
| 76 | + end |
| 77 | +end |
| 78 | + |
| 79 | +[1,3,5,7,9].sum # -> 25 |
| 80 | +(1..100).sum # -> 5050 |
| 81 | + |
| 82 | +11.5 How can I use continuations? |
| 83 | + |
| 84 | +Ruby's continuations allow you to create an object representing a place in a Ruby program, and then return to that place at any time (even if it has apparently gone out of scope). Continuations can be used to implement complex control structures, but are typically more useful as ways of confusing people. |
| 85 | + |
| 86 | +In [ruby-talk:4482], Jim Weirich posted the following examples of continuations: |
| 87 | + |
| 88 | + |
| 89 | + |
| 90 | +# -------------------------------------------------------------------- |
| 91 | +# Simple Producer/Consumer |
| 92 | +# -------------------------------------------------------------------- |
| 93 | +# Connect a simple counting task and a printing task together using |
| 94 | +# continuations. |
| 95 | +# |
| 96 | +# Usage: count(limit) |
| 97 | + |
| 98 | +def count_task(count, consumer) |
| 99 | + (1..count).each do |
| 100 | + |i| |
| 101 | + callcc {|cc| consumer.call cc, i } |
| 102 | + end |
| 103 | + nil |
| 104 | +end |
| 105 | + |
| 106 | +def print_task() |
| 107 | + producer, i = callcc { |cc| return cc } |
| 108 | + print "#{i} " |
| 109 | + callcc { |cc| producer.call } |
| 110 | +end |
| 111 | + |
| 112 | +def count(limit) |
| 113 | + count_task(limit, print_task()) |
| 114 | + print "\n" |
| 115 | +end |
| 116 | + |
| 117 | + |
| 118 | + |
| 119 | +# -------------------------------------------------------------------- |
| 120 | +# Filtering Out Multiples of a Given Number |
| 121 | +# -------------------------------------------------------------------- |
| 122 | +# Create a filter that is both a consumer and producer. Insert it |
| 123 | +# between the counting task and the printing task. |
| 124 | +# |
| 125 | +# Usage: omit (2, limit) |
| 126 | + |
| 127 | +def filter_task(factor, consumer) |
| 128 | + producer, i = callcc { |cc| return cc } |
| 129 | + if (i%factor) != 0 then |
| 130 | + callcc { |cc| consumer.call cc, i } |
| 131 | + end |
| 132 | + producer.call |
| 133 | +end |
| 134 | + |
| 135 | +def omit(factor, limit) |
| 136 | + printer = print_task() |
| 137 | + filter = filter_task(factor, printer) |
| 138 | + count_task(limit, filter) |
| 139 | + print "\n" |
| 140 | +end |
| 141 | + |
| 142 | + |
| 143 | + |
| 144 | +# -------------------------------------------------------------------- |
| 145 | +# Prime Number Generator |
| 146 | +# -------------------------------------------------------------------- |
| 147 | +# Create a prime number generator. When a new prime number is |
| 148 | +# discovered, dynamically add a new multiple filter to the chain of |
| 149 | +# producers and consumers. |
| 150 | +# |
| 151 | +# Usage: primes (limit) |
| 152 | + |
| 153 | +def prime_task(consumer) |
| 154 | + producer, i = callcc { |cc| return cc } |
| 155 | + if i >= 2 then |
| 156 | + callcc { |cc| consumer.call cc, i } |
| 157 | + consumer = filter_task(i, consumer) |
| 158 | + end |
| 159 | + producer.call |
| 160 | +end |
| 161 | + |
| 162 | +def primes(limit) |
| 163 | + printer = print_task() |
| 164 | + primes = prime_task(printer) |
| 165 | + count_task(limit, primes) |
| 166 | + print "\n" |
| 167 | +end |
| 168 | + |
| 169 | + |
0 commit comments